@tamu-dor/famis-db 1.3.3 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/index.js +445 -102
  2. package/package.json +3 -3
package/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  const knex = require('knex');
2
- const cuid = require('cuid');
3
- const { map } = require('awaity');
2
+ const { createId } = require('@paralleldrive/cuid2');
3
+ const { each, map } = require('awaity');
4
4
  const revisionHash = require('rev-hash');
5
5
 
6
6
  const famisInvoiceNumbers = [
@@ -80,6 +80,15 @@ class FAMISDb {
80
80
  this.db = knex({
81
81
  client: 'pg',
82
82
  connection: config,
83
+ pool: {
84
+ min: 0,
85
+ max: 10,
86
+ createTimeoutMillis: 30000,
87
+ acquireTimeoutMillis: 30000,
88
+ idleTimeoutMillis: 30000,
89
+ reapIntervalMillis: 1000,
90
+ createRetryIntervalMillis: 100,
91
+ },
83
92
  });
84
93
  this.people = people;
85
94
  }
@@ -114,30 +123,53 @@ class FAMISDb {
114
123
  /**
115
124
  *
116
125
  * Process an invoice to have all necessary relationships
117
- * @param {object} invoice
118
- * @returns{Promise<object>} invoice object
126
+ * @param {object} invoice - the invoice object sent by iLab
127
+ * @param {boolean} [historical=false] - if true use historical accounts too
128
+ * @returns {Promise<object>} invoice object
119
129
  * @memberof FAMISDb
120
130
  */
121
- async processInvoice(invoice) {
131
+ async processInvoice(invoice, historical=false) {
122
132
  // console.log(invoice);
123
- const account = getCoreAccountNumber(invoice.data.details[0].famis);
124
- invoice.core = await this.getCoreByAccount(account);
125
- if (invoice.core) {
126
- invoice.core.systemPart = await this.getSystemById(invoice.core.systemId);
127
- } else {
128
- const e = Error(`Revenue account ${account} is not associated with a core.`)
129
- throw(e);
130
- }
131
- const customerAccountNumber = this.getAccountNumber(invoice.data.details[0].famis, invoice.replace_data);
132
- invoice.isIdt = customerAccountNumber && (customerAccountNumber.accountNumber.substring(0,2) === account.substring(0,2));
133
- invoice.customerAccountInfo = await this.getByAccountNumber(customerAccountNumber.accountNumber);
134
- invoice.poNumber = customerAccountNumber.poNumber;
135
- invoice.customerAccount = customerAccountNumber.accountNumber;
136
- if (invoice.customerAccountInfo && this.people) {
137
- const pi = invoice.customerAccountInfo.uin ? await this.people.getByUin(invoice.customerAccountInfo.uin) : [];
138
- if (pi.length) {
139
- invoice.pi = JSON.parse(JSON.stringify(pi[0]));
133
+ try {
134
+ const account = getCoreAccountNumber(invoice.data.details[0].famis);
135
+ invoice.core = await this.getCoreByAccount(account);
136
+ if (invoice.core) {
137
+ invoice.core.systemPart = await this.getSystemById(invoice.core.systemId);
138
+ } else {
139
+ const e = Error(`Revenue account ${account} is not associated with a core.`)
140
+ throw(e);
140
141
  }
142
+ const campus = account.substring(0,2);
143
+ const revenuAccount = await this.getByAccountNumber(account, campus, historical);
144
+ const customerAccountNumber = this.getAccountNumber(invoice.data.details[0].famis, invoice.replace_data);
145
+ invoice.customerAccountInfo = await this.getByAccountNumber(customerAccountNumber.accountNumber, campus, historical);
146
+ if (invoice.customerAccountInfo) {
147
+ let idtAllowed = 'idt_allowed' in invoice.customerAccountInfo && invoice.customerAccountInfo.idt_allowed !== null ?
148
+ invoice.customerAccountInfo.idt_allowed :
149
+ 'parent_account_idt_allowed' in invoice.customerAccountInfo && invoice.customerAccountInfo.parent_account_idt_allowed;
150
+ idtAllowed = idtAllowed &&
151
+ !( invoice.replace_data &&
152
+ typeof invoice.replace_data === 'object' &&
153
+ invoice.replace_data.forcedAr
154
+ );
155
+ const isIdt = customerAccountNumber && (customerAccountNumber.accountNumber.substring(0,2) === account.substring(0,2)) && idtAllowed;
156
+ invoice.isIdt = isIdt;
157
+ } else {
158
+ invoice.isIdt = false;
159
+ }
160
+ let poNumber = (customerAccountNumber.accountNumber.substring(0,2) !== '68') ? `${campus}-${revenuAccount.department}` : customerAccountNumber.poNumber;
161
+ invoice.poNumber = poNumber;
162
+ invoice.customerAccount = customerAccountNumber.accountNumber;
163
+ if (invoice.customerAccountInfo && this.people) {
164
+ const pi = invoice.customerAccountInfo.uin ? await this.people.getByUin(invoice.customerAccountInfo.uin) : [];
165
+ if (pi.length) {
166
+ invoice.pi = JSON.parse(JSON.stringify(pi[0]));
167
+ }
168
+ }
169
+ invoice.highRiskInfo = await this.isSrsHighRisk(invoice);
170
+ invoice.comments = await this.getInvoiceComments(invoice.uid);
171
+ } catch (e) {
172
+ throw e;
141
173
  }
142
174
  return invoice;
143
175
  }
@@ -147,7 +179,7 @@ class FAMISDb {
147
179
  *
148
180
  * Get invoice by uid
149
181
  * @param {string} uid
150
- * @returns{Promise<object>} invoice object
182
+ * @returns {Promise<object>} invoice object
151
183
  * @memberof FAMISDb
152
184
  */
153
185
  async getInvoiceByUid(uid) {
@@ -170,7 +202,7 @@ class FAMISDb {
170
202
  *
171
203
  * Get invoice by originating system assigned number
172
204
  * @param {string} number
173
- * @returns{Promise<object>} invoice object
205
+ * @returns {Promise<object>} invoice object
174
206
  * @memberof FAMISDb
175
207
  */
176
208
  async getInvoiceByNumber(number) {
@@ -178,10 +210,10 @@ class FAMISDb {
178
210
  let retVal;
179
211
 
180
212
  try {
181
- records = await this.db('invoices').where('number', number);
213
+ records = await this.db('invoices').whereILike('number', `${number}%`);
182
214
  if (records.length) {
183
215
  retVal = this.processInvoice(records[0]);
184
- }
216
+ }
185
217
  } catch (e) {
186
218
  throw e;
187
219
  }
@@ -192,7 +224,7 @@ class FAMISDb {
192
224
  *
193
225
  * Get invoice by fingerprint
194
226
  * @param {string} fingerPrint
195
- * @returns{Promise<object>} invoice object
227
+ * @returns {Promise<object>} invoice object
196
228
  * @memberof FAMISDb
197
229
  */
198
230
  async getInvoiceByFingerPrint(fingerPrint) {
@@ -214,7 +246,7 @@ class FAMISDb {
214
246
  *
215
247
  * Get all invoices associated with a specified account number
216
248
  * @param {string} accountNumber
217
- * @returns{Promise<array>} invoice objects
249
+ * @returns {Promise<array>} invoice objects
218
250
  * @memberof FAMISDb
219
251
  */
220
252
  async getInvoicesByAccount(accountNumber) {
@@ -254,35 +286,51 @@ class FAMISDb {
254
286
  * @param {string} [orderBy='date']
255
287
  * @param {string} [dir='desc']
256
288
  * @param {boolean} [deleted=false]
257
- * @returns{Promise<array>} invoice objects
289
+ * @param {integer} [page=null]
290
+ * @param {integer} [limit=null]
291
+ * @returns {Promise<array>} invoice objects
258
292
  * @memberof FAMISDb
259
293
  */
260
- async getAllInvoices(orderBy='date', dir='desc', deleted=false) {
294
+ async getAllInvoices(orderBy='date', dir='desc', deleted=false, page=null, limit=null) {
261
295
  const self = this;
262
296
  let records;
297
+ let metadata;
263
298
  try {
264
299
  const sql = this.db('invoices')
300
+ const meta = this.db('invoices');
265
301
  if (!deleted) {
266
- sql.whereNull('deleted')
302
+ sql.whereNull('deleted');
303
+ meta.whereNull('deleted');
304
+ }
305
+ //console.log(page, limit);
306
+ if (page && limit) {
307
+ sql.limit(limit).offset((page-1)*limit);
267
308
  }
268
309
  records = await sql.orderBy(orderBy, dir);
310
+ metadata = await meta.orderBy(orderBy, dir);
311
+ //console.log(records);
269
312
  records = await map(
270
313
  records,
271
314
  async (record) => {
272
- const rec = self.processInvoice(record);
315
+ const rec = self.processInvoice(record, true);
273
316
  return rec;
274
317
  }
275
318
  );
276
319
  } catch (e) {
277
320
  throw e;
278
321
  }
279
- return records;
322
+ return {
323
+ records,
324
+ metadata: {
325
+ total: metadata.length,
326
+ },
327
+ }
280
328
  }
281
329
 
282
330
  /**
283
331
  *
284
332
  * Retreives invoices from the latest date
285
- * @returns{Promise<array>} invoice objects
333
+ * @returns {Promise<array>} invoice objects
286
334
  * @memberof FAMISDb
287
335
  */
288
336
  async getLatestInvoices() {
@@ -311,17 +359,27 @@ class FAMISDb {
311
359
  /**
312
360
  *
313
361
  * Returns all held invoices
314
- * @returns{Promise<array>} held invoice objects
362
+ * @returns {Promise<array>} held invoice objects
315
363
  * @memberof FAMISDb
316
364
  */
317
- async getHeldInvoices() {
365
+ async getHeldInvoices(orderBy='date', dir='desc', page=null, limit=null) {
318
366
  const self = this;
319
367
  let records;
320
-
368
+ let metadata;
369
+ const sql = this.db('invoices');
370
+ const meta = this.db('invoices');
321
371
  try {
322
- records = await this.db('invoices')
372
+ if (page && limit) {
373
+ sql.limit(limit).offset((page-1)*limit);
374
+ }
375
+ records = await sql
323
376
  .whereNull('deleted')
324
- .andWhere('invoiced', '0');
377
+ .andWhere('invoiced', '0')
378
+ .orderBy(orderBy, dir);
379
+ metadata = await meta
380
+ .whereNull('deleted')
381
+ .andWhere('invoiced', '0')
382
+ .orderBy(orderBy, dir);
325
383
  records = await map(
326
384
  records,
327
385
  async (record) => {
@@ -332,13 +390,18 @@ class FAMISDb {
332
390
  } catch (e) {
333
391
  throw e;
334
392
  }
335
- return records;
393
+ return {
394
+ records,
395
+ metadata: {
396
+ total: metadata.length,
397
+ },
398
+ };
336
399
  }
337
400
 
338
401
  /**
339
402
  *
340
403
  * Returns all awaiting email invoices
341
- * @returns{Promise<array>} awaiting email invoice objects
404
+ * @returns {Promise<array>} awaiting email invoice objects
342
405
  * @memberof FAMISDb
343
406
  */
344
407
  async getInvoicesAwaitingEmail() {
@@ -366,7 +429,7 @@ class FAMISDb {
366
429
  *
367
430
  * Search invoices by originating system generated invoice number
368
431
  * @param {string} number
369
- * @returns{Promise<array>} invoice objects
432
+ * @returns {Promise<array>} invoice objects
370
433
  * @memberof FAMISDb
371
434
  */
372
435
  async searchInvoicesByNumber(number) {
@@ -397,7 +460,7 @@ class FAMISDb {
397
460
  *
398
461
  * Search invoices by FAMIS invoice number
399
462
  * @param {string} famis
400
- * @returns{Promise<array>} invoice objects
463
+ * @returns {Promise<array>} invoice objects
401
464
  * @memberof FAMISDb
402
465
  */
403
466
  async searchInvoicesByFamis(famis) {
@@ -430,7 +493,7 @@ class FAMISDb {
430
493
  * @param {object} invoice
431
494
  * @param {string} type
432
495
  * @param {string} famisInvoiceNumber
433
- * @returns{Promise<object>} invoice
496
+ * @returns {Promise<object>} invoice
434
497
  * @memberof FAMISDb
435
498
  */
436
499
  async addInvoice(invoice, type, famisInvoiceNumber) {
@@ -459,7 +522,7 @@ class FAMISDb {
459
522
  totalAmount: parseFloat(invoice.totalAmount),
460
523
  data: JSON.stringify(invoice),
461
524
  date: invoice.date,
462
- uid: cuid(),
525
+ uid: createId(),
463
526
  fingerprint: invoice.fingerprint,
464
527
  type: type,
465
528
  famisInvoiceNumber: famisInvoiceNumber,
@@ -478,7 +541,7 @@ class FAMISDb {
478
541
  * Updates an invoice
479
542
  * @param {string} uid
480
543
  * @param {object} invoice
481
- * @returns{Promise<object>} invoice object
544
+ * @returns {Promise<object>} invoice object
482
545
  * @memberof FAMISDb
483
546
  */
484
547
  async updateInvoice(uid, invoice) {
@@ -506,6 +569,7 @@ class FAMISDb {
506
569
  customerAccount: this.getAccountNumber(invoice.details[0].famis).accountNumber,
507
570
  sellingAccount: getCoreAccountNumber(invoice.details[0].famis),
508
571
  fingerprint: invoice.fingerprint ? invoice.fingerprint : null,
572
+ replace_data: invoice.replace_data,
509
573
  })
510
574
  .where('uid', uid);
511
575
  } catch (e) {
@@ -519,7 +583,7 @@ class FAMISDb {
519
583
  * Toggles an invoice as paid
520
584
  * @param {string} uid
521
585
  * @param {boolean} invoiced
522
- * @returns{Promise<object>} invoice object
586
+ * @returns {Promise<object>} invoice object
523
587
  * @memberof FAMISDb
524
588
  */
525
589
  async markInvoiced(uid, invoiced) {
@@ -543,7 +607,7 @@ class FAMISDb {
543
607
  * Toggles an invoice as emailed
544
608
  * @param {string} uid
545
609
  * @param {boolean} emailed
546
- * @returns{Promise<object>} invoice object
610
+ * @returns {Promise<object>} invoice object
547
611
  * @memberof FAMISDb
548
612
  */
549
613
  async markEmailed(uid, emailed) {
@@ -567,7 +631,7 @@ class FAMISDb {
567
631
  * Sets an invoice's deletion date
568
632
  * @param {string} uid
569
633
  * @param {date} deleted
570
- * @returns{Promise<object>} invoice object
634
+ * @returns {Promise<object>} invoice object
571
635
  * @memberof FAMISDb
572
636
  */
573
637
  async setDeleted(uid, deleted) {
@@ -591,7 +655,7 @@ class FAMISDb {
591
655
  * Sets an invoice's posted date
592
656
  * @param {string} uid
593
657
  * @param {date} postedDate
594
- * @returns{Promise<object>} invoice object
658
+ * @returns {Promise<object>} invoice object
595
659
  * @memberof FAMISDb
596
660
  */
597
661
  async setInvoicePostedDate(uid, postedDate) {
@@ -615,7 +679,7 @@ class FAMISDb {
615
679
  * Sets an invoice's fingerprint
616
680
  * @param {string} uid
617
681
  * @param {string} fingerprint
618
- * @returns{Promise<object>} invoice object
682
+ * @returns {Promise<object>} invoice object
619
683
  * @memberof FAMISDb
620
684
  */
621
685
  async setInvoiceFingerPrint(uid, fingerprint) {
@@ -638,35 +702,40 @@ class FAMISDb {
638
702
  *
639
703
  * Get PI accounts by account number
640
704
  * @param {string} number
641
- * @returns{Promise<object>} account object
705
+ * @param {string} campus
706
+ * @param {boolean} [historical=false]
707
+ * @returns {Promise<object>} account object
642
708
  * @memberof FAMISDb
643
709
  */
644
- async getByAccountNumber(number) {
710
+ async getByAccountNumber(number, campus, historical=false) {
645
711
  let records;
646
712
  let retVal;
713
+ let table = historical ? 'accounts_all' : 'accounts'
647
714
  const self = this;
648
715
 
649
- if (!number) console.log('Null account number');
716
+ if (!number) {
717
+ throw Error('Null account number');
718
+ }
650
719
  try {
651
- records = await this.db('accounts')
720
+ records = await this.db(`${table}`)
652
721
  .leftJoin('departments',
653
722
  function() {
654
723
  this
655
- .on('accounts.department', '=', 'departments.dept')
724
+ .on(`${table}.department`, '=', 'departments.dept')
656
725
  .on('departments.part', '=', self.db.raw('?', [number.substring(0,2)]))
657
726
  }
658
727
  )
659
- .leftJoin('accounts as parent_account',
728
+ .leftJoin(`${table} as parent_account`,
660
729
  function() {
661
730
  this
662
- .on('accounts.campus_code', '=', 'parent_account.campus_code')
663
- .on('accounts.account', '=', 'parent_account.account')
731
+ .on(`${table}.campus_code`, '=', 'parent_account.campus_code')
732
+ .on(`${table}.account`, '=', 'parent_account.account')
664
733
  .on('parent_account.support_account', '=', self.db.raw('?', ["00000"]))
665
- .on('accounts.fiscal_year', '=', 'parent_account.fiscal_year')
734
+ .on(`${table}.fiscal_year`, '=', 'parent_account.fiscal_year')
666
735
  }
667
736
  )
668
737
  .select(
669
- 'accounts.*',
738
+ `${table}.*`,
670
739
  'departments.idt_email as billingEmailId',
671
740
  'parent_account.idt_allowed as parent_account_idt_allowed'
672
741
  )
@@ -674,12 +743,13 @@ class FAMISDb {
674
743
  .andWhere(function() {
675
744
  this.whereNull('departments.exp_date').orWhere('departments.exp_date', '>', self.db.raw('CURRENT_DATE'))
676
745
  })
677
- .andWhere('accounts.account_number', number);
746
+ .andWhere(`${table}.account_number`, number);
678
747
  if (records.length) {
679
748
  retVal = records[0];
680
749
  } else {
681
750
  records = await this.db('customers')
682
- .where('account_number', number);
751
+ .where('account_number', number)
752
+ .andWhere('campus_code', campus);
683
753
  if (records.length) {
684
754
  retVal = Object.assign(
685
755
  {},
@@ -690,7 +760,7 @@ class FAMISDb {
690
760
  billingEmailId: records[0].email,
691
761
  }
692
762
  );
693
- }
763
+ }
694
764
  }
695
765
  } catch (e) {
696
766
  throw e;
@@ -702,7 +772,7 @@ class FAMISDb {
702
772
  *
703
773
  * Search PI accounts by partial account number
704
774
  * @param {string} number
705
- * @returns{Promise<array>} account object(s)
775
+ * @returns {Promise<array>} account object(s)
706
776
  * @memberof FAMISDb
707
777
  */
708
778
  async searchByAccountNumber(number) {
@@ -745,7 +815,7 @@ class FAMISDb {
745
815
  *
746
816
  * Get PI Accounts by UIN
747
817
  * @param {string} uin
748
- * @returns{Promise<array>} account object array
818
+ * @returns {Promise<array>} account object array
749
819
  * @memberof FAMISDb
750
820
  */
751
821
  async getAccountsByUin(uin) {
@@ -778,7 +848,7 @@ class FAMISDb {
778
848
  *
779
849
  * Get PI accounts by responsible UIN
780
850
  * @param {string} uin
781
- * @returns{Promise<array>} account object array
851
+ * @returns {Promise<array>} account object array
782
852
  * @memberof FAMISDb
783
853
  */
784
854
  async getAccountsByResponsibleUin(uin) {
@@ -811,7 +881,7 @@ class FAMISDb {
811
881
  *
812
882
  * Get next FAMIS invoice number in sequence for specified invoice type
813
883
  * @param {string} invoice
814
- * @returns{Promise<string>} next invoice number in sequence
884
+ * @returns {Promise<string>} next invoice number in sequence
815
885
  * @memberof FAMISDb
816
886
  */
817
887
  async getNextFAMISInvoiceNumber(type) {
@@ -825,7 +895,7 @@ class FAMISDb {
825
895
  });
826
896
  try {
827
897
  retVal = `${prefix.prefix}${prefix.start}`;
828
- records = await this.db('invoices').whereIn('type', prefix.aliases).orderBy('famisInvoiceNumber', 'desc').limit(5);
898
+ records = await this.db('invoices').whereIn('type', prefix.aliases).orderBy('famisInvoiceNumber', 'desc');
829
899
  if (records.length) {
830
900
  const number = parseInt(records[0].famisInvoiceNumber.substring(1), 10) + 1;
831
901
  retVal = `${prefix.prefix}${number}`;
@@ -857,18 +927,18 @@ class FAMISDb {
857
927
  return retVal;
858
928
  }
859
929
 
860
- /**
930
+ /**
861
931
  *
862
- * Get expense code object
863
- * @param {string} code
864
- * @returns {Promise<object>} expense code object
932
+ * Get revenue code object
933
+ * @param {string} revenue
934
+ * @returns {Promise<object>} revenue code object
865
935
  * @memberof FAMISDb
866
936
  */
867
- async getExpenseCode(code) {
937
+ async getRevenueCode(revenue) {
868
938
  let records;
869
939
  let retVal;
870
940
  try {
871
- records = await this.db('codes').where('expense', code).orderBy('id', 'desc');
941
+ records = await this.db('codes').where('revenue', revenue).orderBy('id', 'desc');
872
942
  if (records.length) {
873
943
  retVal = records[0];
874
944
  }
@@ -878,19 +948,18 @@ class FAMISDb {
878
948
  return retVal;
879
949
  }
880
950
 
881
-
882
951
  /**
883
952
  *
884
- * Get revenue code object
885
- * @param {string} revenue
886
- * @returns{Promise<object>} revenue code object
953
+ * Get expense code object
954
+ * @param {string} code
955
+ * @returns {Promise<object>} expense code object
887
956
  * @memberof FAMISDb
888
957
  */
889
- async getRevenueCode(revenue) {
958
+ async getExpenseCode(code) {
890
959
  let records;
891
960
  let retVal;
892
961
  try {
893
- records = await this.db('codes').where('revenue', revenue).orderBy('id', 'desc');
962
+ records = await this.db('codes').where('expense', code).orderBy('id', 'desc');
894
963
  if (records.length) {
895
964
  retVal = records[0];
896
965
  }
@@ -906,7 +975,7 @@ class FAMISDb {
906
975
  * @param {string} account
907
976
  * @param {string} code
908
977
  * @param {integer} fiscal
909
- * @returns{Promise<boolean>} truthy value
978
+ * @returns {Promise<boolean>} truthy value
910
979
  * @memberof FAMISDb
911
980
  */
912
981
  async allowableExpenseCode(accountNumber, code, fiscal) {
@@ -953,7 +1022,7 @@ class FAMISDb {
953
1022
  *
954
1023
  * Get allowable expense code ranges for specified account
955
1024
  * @param {string} account
956
- * @returns{Promise<boolean>} expense code range object(s)
1025
+ * @returns {Promise<boolean>} expense code range object(s)
957
1026
  * @memberof FAMISDb
958
1027
  */
959
1028
  async getAllowableExpenseCodes(accountNumber, fiscal) {
@@ -1013,7 +1082,7 @@ class FAMISDb {
1013
1082
  *
1014
1083
  * Get core by id
1015
1084
  * @param {string} id
1016
- * @returns{Promise<object>} core object
1085
+ * @returns {Promise<object>} core object
1017
1086
  * @memberof FAMISDb
1018
1087
  */
1019
1088
  async getCoreById(id) {
@@ -1078,7 +1147,7 @@ class FAMISDb {
1078
1147
  *
1079
1148
  * Get core by account number
1080
1149
  * @param {string} account
1081
- * @returns{Promise<object>} core object
1150
+ * @returns {Promise<object>} core object
1082
1151
  * @memberof FAMISDb
1083
1152
  */
1084
1153
  async getCoreByAccount(account) {
@@ -1118,7 +1187,7 @@ class FAMISDb {
1118
1187
  *
1119
1188
  * Get core current revenue account number
1120
1189
  * @param {string} coreId
1121
- * @returns{Promise<object>} core object
1190
+ * @returns {Promise<object>} core object
1122
1191
  * @memberof FAMISDb
1123
1192
  */
1124
1193
  async getCoreCurrentAccount(coreId) {
@@ -1180,7 +1249,7 @@ class FAMISDb {
1180
1249
  *
1181
1250
  * Get system part by ID
1182
1251
  * @param {number} id
1183
- * @returns{Promise<object>} system part object
1252
+ * @returns {Promise<object>} system part object
1184
1253
  * @memberof FAMISDb
1185
1254
  */
1186
1255
  async getSystemById(id) {
@@ -1201,7 +1270,7 @@ class FAMISDb {
1201
1270
  *
1202
1271
  * Get system part by two digit part number
1203
1272
  * @param {string} number
1204
- * @returns{Promise<object>} system part object
1273
+ * @returns {Promise<object>} system part object
1205
1274
  * @memberof FAMISDb
1206
1275
  */
1207
1276
  async getSystemByPartNumber(number) {
@@ -1222,7 +1291,7 @@ class FAMISDb {
1222
1291
  *
1223
1292
  * Get all enabled cores
1224
1293
  * @param {string} date
1225
- * @returns{Promise<array>} core objects
1294
+ * @returns {Promise<array>} core objects
1226
1295
  * @memberof FAMISDb
1227
1296
  */
1228
1297
  async getEnabledCores(date) {
@@ -1283,7 +1352,7 @@ class FAMISDb {
1283
1352
  /**
1284
1353
  *
1285
1354
  * Get all cores
1286
- * @returns{Promise<array>} core objects
1355
+ * @returns {Promise<array>} core objects
1287
1356
  * @memberof FAMISDb
1288
1357
  */
1289
1358
  async getAllCores() {
@@ -1304,7 +1373,7 @@ class FAMISDb {
1304
1373
  *
1305
1374
  * Get a core's users by core ID
1306
1375
  * @param {number} coreId
1307
- * @returns{Promise<array>} user objects
1376
+ * @returns {Promise<array>} user objects
1308
1377
  * @memberof FAMISDb
1309
1378
  */
1310
1379
  async getCoreUsers(coreId) {
@@ -1329,7 +1398,7 @@ class FAMISDb {
1329
1398
  *
1330
1399
  * Get a user's cores they manage
1331
1400
  * @param {string} userId
1332
- * @returns{Promise<array>} core objects
1401
+ * @returns {Promise<array>} core objects
1333
1402
  * @memberof FAMISDb
1334
1403
  */
1335
1404
  async getUserCores(userId) {
@@ -1355,7 +1424,7 @@ class FAMISDb {
1355
1424
  *
1356
1425
  * Get a system part's users by system ID
1357
1426
  * @param {number} systemId
1358
- * @returns{Promise<array>} user objects
1427
+ * @returns {Promise<array>} user objects
1359
1428
  * @memberof FAMISDb
1360
1429
  */
1361
1430
  async getSystemUsers(systemId) {
@@ -1380,7 +1449,7 @@ class FAMISDb {
1380
1449
  *
1381
1450
  * Get a user's system parts they manage
1382
1451
  * @param {*} userId
1383
- * @returns{Promise<object>} system objects
1452
+ * @returns {Promise<object>} system objects
1384
1453
  * @memberof FAMISDb
1385
1454
  */
1386
1455
  async getUserSystemParts(userId) {
@@ -1406,7 +1475,7 @@ class FAMISDb {
1406
1475
  /**
1407
1476
  *
1408
1477
  * Get all system parts
1409
- * @returns{Promise<object>} system objects
1478
+ * @returns {Promise<object>} system objects
1410
1479
  * @memberof FAMISDb
1411
1480
  */
1412
1481
  async getAllSystemParts() {
@@ -1420,11 +1489,27 @@ class FAMISDb {
1420
1489
  return retVal;
1421
1490
  }
1422
1491
 
1492
+ /**
1493
+ *
1494
+ * Get all admin users
1495
+ * @returns {Promise<array>} array of user objects
1496
+ * @memberof FAMISDb
1497
+ */
1498
+ async getAdminUsers() {
1499
+ let retVal;
1500
+ try {
1501
+ retVal = await this.db('users').where('admin', true);
1502
+ } catch (e) {
1503
+ throw e;
1504
+ }
1505
+ return retVal;
1506
+ }
1507
+
1423
1508
  /**
1424
1509
  *
1425
1510
  * Get user
1426
1511
  * @param {string} userId
1427
- * @returns{Promise<object>} user object
1512
+ * @returns {Promise<object>} user object
1428
1513
  * @memberof FAMISDb
1429
1514
  */
1430
1515
  async getUser(userId) {
@@ -1443,12 +1528,33 @@ class FAMISDb {
1443
1528
  return retVal;
1444
1529
  }
1445
1530
 
1531
+ /**
1532
+ *
1533
+ * Update user
1534
+ * @param {object} user
1535
+ * @returns {Promise<object>} user object
1536
+ * @memberof FAMISDb
1537
+ */
1538
+ async updateUser(user) {
1539
+ let retVal;
1540
+ const columns = ['id', 'userId', 'admin', 'role', 'roleName', 'roleEmail', 'deleted'];
1541
+ try {
1542
+ if ('id' in user) retVal = await this.db('users')
1543
+ .returning(columns)
1544
+ .update(user)
1545
+ .where('id', user.id);
1546
+ } catch (e) {
1547
+ throw e;
1548
+ }
1549
+ return retVal;
1550
+ }
1551
+
1446
1552
  /**
1447
1553
  *
1448
1554
  * Get customer by customer account number
1449
1555
  * @param {string} accountNumber
1450
1556
  * @param {string} campusCode
1451
- * @returns{Promise<object>} customer account object
1557
+ * @returns {Promise<object>} customer account object
1452
1558
  * @memberof FAMISDb
1453
1559
  */
1454
1560
  async getCustomerNumber(accountNumber, campusCode) {
@@ -1461,7 +1567,7 @@ class FAMISDb {
1461
1567
  .where('uid', `${code}${accountNumber}`);
1462
1568
  if (records.length) {
1463
1569
  retVal = records[0];
1464
- }
1570
+ }
1465
1571
  } catch (e) {
1466
1572
  throw e;
1467
1573
  }
@@ -1471,7 +1577,7 @@ class FAMISDb {
1471
1577
  /**
1472
1578
  *
1473
1579
  * Get current fiscal year
1474
- * @returns{<integer>} fiscal year
1580
+ * @returns {<integer>} fiscal year
1475
1581
  * @memberof FAMISDb
1476
1582
  */
1477
1583
  getCurrentFiscalYear() {
@@ -1489,7 +1595,7 @@ class FAMISDb {
1489
1595
  *
1490
1596
  * Return fingerprint of invoice
1491
1597
  * @param {object} invoice json object
1492
- * @returns{<string>} fingerprint
1598
+ * @returns {<string>} fingerprint
1493
1599
  * @memberof FAMISDb
1494
1600
  */
1495
1601
  getInvoiceFingerPrint(invoice) {
@@ -1506,7 +1612,7 @@ class FAMISDb {
1506
1612
  *
1507
1613
  * Return formatted account number
1508
1614
  * @param {string} accountNumber unformatted 13 digit famis account number
1509
- * @returns{<string>} formatted 13 digits famis account number
1615
+ * @returns {<string>} formatted 13 digits famis account number
1510
1616
  * @memberof FAMISDb
1511
1617
  */
1512
1618
  formatAccountNumber(accountNumber) {
@@ -1514,6 +1620,243 @@ class FAMISDb {
1514
1620
 
1515
1621
  return formatted;
1516
1622
  }
1623
+
1624
+ /**
1625
+ * @typedef {Object} HighRisk
1626
+ * @property {boolean} isHighRisk - indicates if invoice triggers SRS high risk policy
1627
+ * @property {object} flaggedTransactions - object of transactions that flag
1628
+ */
1629
+
1630
+ /**
1631
+ *
1632
+ * Is invoice flagged by SRS high risk policies
1633
+ * @param {object} invoice json object
1634
+ * @returns {Promise<HighRisk>} high risk object
1635
+ * @memberof FAMISDb
1636
+ */
1637
+ async isSrsHighRisk(invoice) {
1638
+ let srsHighRisk = false;
1639
+ const objectCodes = new Map();
1640
+ //console.log(invoice);
1641
+ try {
1642
+ await each(
1643
+ invoice.data.details,
1644
+ async (detail) => {
1645
+ //console.log(detail);
1646
+ if (detail.famis.customerAccountNumber && detail.famis.sellingCampusCode) {
1647
+ const acct = await this.getByAccountNumber(detail.famis.customerAccountNumber, detail.famis.sellingCampusCode);
1648
+ const acctNum = this.formatAccountNumber(detail.famis.customerAccountNumber);
1649
+ const objCode = await this.getRevenueCode(detail.sellingObjectCode);
1650
+ const isFederal = acct && acct.cfda_no && (acct.sponsor_type && acct.sponsor_type === 'F');
1651
+ const srsApproved = invoice.replace_data && "srs_approved" in invoice.replace_data ? invoice.replace_data.srs_approved : false;
1652
+ if (objCode && objCode.srs && acct && acct.srs && isFederal && !srsApproved && invoice.isIdt) {
1653
+ srsHighRisk = true;
1654
+ let val = [detail];
1655
+ if (objectCodes.has(objCode.expense)) val.push(...objectCodes.get(objCode.expense));
1656
+ objectCodes.set(objCode.expense, val);
1657
+ }
1658
+ }
1659
+ }
1660
+ );
1661
+ } catch (e) {
1662
+ //console.log(invoice);
1663
+ console.log(e);
1664
+ }
1665
+ return {
1666
+ isHighRisk: srsHighRisk,
1667
+ flaggedTransactions: Object.fromEntries(objectCodes),
1668
+ }
1669
+ }
1670
+
1671
+ /**
1672
+ * @typedef {Object} Comment
1673
+ * @property {integer} id - db generated id
1674
+ * @property {string} uid - uid
1675
+ * @property {string} invoice_id - invoice id
1676
+ * @property {string} user_id - user uid
1677
+ * @property {string} comment - text of comment
1678
+ * @property {string} type - type of comment
1679
+ * @property {date} created - created date
1680
+ * @property {date} deleted - deleted date
1681
+ */
1682
+
1683
+ /**
1684
+ *
1685
+ * Create/update invoice comment
1686
+ * @param {Comment} comment json object
1687
+ * @returns {Promise<Comment>} comment object
1688
+ * @memberof FAMISDb
1689
+ */
1690
+ async saveComment(comment) {
1691
+ const returningColumns = [
1692
+ 'id',
1693
+ 'uid',
1694
+ 'invoice_id',
1695
+ 'user_id',
1696
+ 'comment',
1697
+ 'type',
1698
+ 'created',
1699
+ 'deleted',
1700
+ ];
1701
+ let response;
1702
+ try {
1703
+ const records = await this.db('invoice_comments').where({ uid: comment.uid });
1704
+ if (records.length) {
1705
+ response = await this.db('invoice_comments')
1706
+ .returning(returningColumns)
1707
+ .update(comment)
1708
+ .where('uid', comment.uid);
1709
+ } else {
1710
+ response = await this.db('invoice_comments')
1711
+ .returning(returningColumns)
1712
+ .insert(comment);
1713
+ }
1714
+
1715
+ if (response.length) {
1716
+ response = response[0];
1717
+ }
1718
+ } catch (e) {
1719
+ //console.log(JSON.stringify(comment, null, 2));
1720
+ console.log(e);
1721
+ throw (e);
1722
+ }
1723
+ return response;
1724
+ }
1725
+
1726
+ /**
1727
+ *
1728
+ * Get invoice comments
1729
+ * @param {string} invoiceUid invoice uid
1730
+ * @returns {Promise(<Comment[]>} array of comment objects
1731
+ * @memberof FAMISDb
1732
+ */
1733
+ async getInvoiceComments(invoiceUid) {
1734
+ let self = this;
1735
+ let response;
1736
+ try {
1737
+ const records = await this.db('invoice_comments')
1738
+ .select(
1739
+ 'invoice_comments.*',
1740
+ )
1741
+ .where({ invoice_id: invoiceUid })
1742
+ .orderBy('created', 'desc');
1743
+ response = await map(
1744
+ records,
1745
+ async (r) => {
1746
+ const retVal = r;
1747
+ const files = await self.getCommentFiles(r.uid);
1748
+ r.files = files;
1749
+ if (self.people) {
1750
+ const user = await self.people.getByUid(r.user_id);
1751
+ if (user) {
1752
+ retVal.user = user;
1753
+ }
1754
+ }
1755
+ return retVal;
1756
+ }
1757
+ );
1758
+ } catch (e) {
1759
+ console.log(e);
1760
+ throw (e);
1761
+ }
1762
+ return response;
1763
+ }
1764
+
1765
+ /**
1766
+ * @typedef {Object} CommentFile
1767
+ * @property {integer} id - db generated id
1768
+ * @property {string} uid - uid
1769
+ * @property {string} invoice_id - invoice uid
1770
+ * @property {string} comment_id - comment uid
1771
+ * @property {string} original_filename - original file name
1772
+ * @property {string} filename - generate unique filename on filesystem
1773
+ * @property {date} created - created date
1774
+ * @property {date} deleted - deleted date
1775
+ */
1776
+
1777
+ /**
1778
+ *
1779
+ * Create/update invoice comment file
1780
+ * @param {CommentFile} commentFile json object
1781
+ * @returns {Promise<CommentFile>} comment object
1782
+ * @memberof FAMISDb
1783
+ */
1784
+ async saveCommentFile(commentFile) {
1785
+ const returningColumns = [
1786
+ 'id',
1787
+ 'uid',
1788
+ 'invoice_id',
1789
+ 'comment_id',
1790
+ 'original_filename',
1791
+ 'filename',
1792
+ 'created',
1793
+ 'deleted',
1794
+ ];
1795
+ let response;
1796
+ try {
1797
+ const records = await this.db('invoice_comment_files').where({ uid: commentFile.uid });
1798
+ if (records.length) {
1799
+ response = await this.db('invoice_comment_files')
1800
+ .returning(returningColumns)
1801
+ .update(commentFile)
1802
+ .where('uid', commentFile.uid);
1803
+ } else {
1804
+ response = await this.db('invoice_comment_files')
1805
+ .returning(returningColumns)
1806
+ .insert(commentFile);
1807
+ }
1808
+
1809
+ if (response.length) {
1810
+ response = response[0];
1811
+ }
1812
+ } catch (e) {
1813
+ //console.log(JSON.stringify(comment, null, 2));
1814
+ console.log(e);
1815
+ throw (e);
1816
+ }
1817
+ return response;
1818
+ }
1819
+
1820
+ /**
1821
+ *
1822
+ * Get invoice comment files
1823
+ * @param {string} commentUid comment uid
1824
+ * @returns {Promise(<CommentFile[]>} array of comment file objects
1825
+ * @memberof FAMISDb
1826
+ */
1827
+ async getCommentFiles(commentUid) {
1828
+ let response;
1829
+ try {
1830
+ const records = await this.db('invoice_comment_files')
1831
+ .where({ comment_id: commentUid })
1832
+ .orderBy('created', 'desc');
1833
+ response = records;
1834
+ } catch (e) {
1835
+ console.log(e);
1836
+ throw (e);
1837
+ }
1838
+ return response;
1839
+ }
1840
+
1841
+ /**
1842
+ *
1843
+ * Get invoice comment file
1844
+ * @param {string} fileUid file uid
1845
+ * @returns {Promise(<CommentFile>} array of comment file objects
1846
+ * @memberof FAMISDb
1847
+ */
1848
+ async getCommentFile(fileUid) {
1849
+ let response;
1850
+ try {
1851
+ const records = await this.db('invoice_comment_files')
1852
+ .where({ uid: fileUid });
1853
+ if (records.length) response = records[0];
1854
+ } catch (e) {
1855
+ console.log(e);
1856
+ throw (e);
1857
+ }
1858
+ return response;
1859
+ }
1517
1860
  }
1518
1861
 
1519
- module.exports = FAMISDb;
1862
+ module.exports = FAMISDb;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tamu-dor/famis-db",
3
- "version": "1.3.3",
3
+ "version": "2.0.2",
4
4
  "description": "DB library for FAMIS database",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -16,10 +16,10 @@
16
16
  "author": "Matt Voss",
17
17
  "license": "ISC",
18
18
  "dependencies": {
19
+ "@paralleldrive/cuid2": "^2.2.2",
19
20
  "awaity": "^1.0.0",
20
- "cuid": "^2.1.8",
21
21
  "knex": "^3.1.0",
22
22
  "pg": "^8.11.3",
23
23
  "rev-hash": "^3.0.0"
24
24
  }
25
- }
25
+ }