@tamu-dor/famis-db 1.3.2 → 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 +458 -93
  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);
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
+ }
140
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
376
+ .whereNull('deleted')
377
+ .andWhere('invoiced', '0')
378
+ .orderBy(orderBy, dir);
379
+ metadata = await meta
323
380
  .whereNull('deleted')
324
- .andWhere('invoiced', '0');
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}`;
@@ -840,10 +910,10 @@ class FAMISDb {
840
910
  *
841
911
  * Get matching expense code for specified revenue code
842
912
  * @param {string} revenue
843
- * @returns{Promise<string>} expense code
913
+ * @returns {Promise<string>} expense code
844
914
  * @memberof FAMISDb
845
915
  */
846
- async getExpenseCode(revenue) {
916
+ async getExpenseCodeByRevenue(revenue) {
847
917
  let records;
848
918
  let retVal;
849
919
  try {
@@ -861,7 +931,7 @@ class FAMISDb {
861
931
  *
862
932
  * Get revenue code object
863
933
  * @param {string} revenue
864
- * @returns{Promise<object>} revenue code object
934
+ * @returns {Promise<object>} revenue code object
865
935
  * @memberof FAMISDb
866
936
  */
867
937
  async getRevenueCode(revenue) {
@@ -878,13 +948,34 @@ class FAMISDb {
878
948
  return retVal;
879
949
  }
880
950
 
951
+ /**
952
+ *
953
+ * Get expense code object
954
+ * @param {string} code
955
+ * @returns {Promise<object>} expense code object
956
+ * @memberof FAMISDb
957
+ */
958
+ async getExpenseCode(code) {
959
+ let records;
960
+ let retVal;
961
+ try {
962
+ records = await this.db('codes').where('expense', code).orderBy('id', 'desc');
963
+ if (records.length) {
964
+ retVal = records[0];
965
+ }
966
+ } catch (e) {
967
+ throw e;
968
+ }
969
+ return retVal;
970
+ }
971
+
881
972
  /**
882
973
  *
883
974
  * Check if expense code is within the allowable range for specified account and the specified fiscal year (defaults to current)
884
975
  * @param {string} account
885
976
  * @param {string} code
886
977
  * @param {integer} fiscal
887
- * @returns{Promise<boolean>} truthy value
978
+ * @returns {Promise<boolean>} truthy value
888
979
  * @memberof FAMISDb
889
980
  */
890
981
  async allowableExpenseCode(accountNumber, code, fiscal) {
@@ -931,7 +1022,7 @@ class FAMISDb {
931
1022
  *
932
1023
  * Get allowable expense code ranges for specified account
933
1024
  * @param {string} account
934
- * @returns{Promise<boolean>} expense code range object(s)
1025
+ * @returns {Promise<boolean>} expense code range object(s)
935
1026
  * @memberof FAMISDb
936
1027
  */
937
1028
  async getAllowableExpenseCodes(accountNumber, fiscal) {
@@ -991,7 +1082,7 @@ class FAMISDb {
991
1082
  *
992
1083
  * Get core by id
993
1084
  * @param {string} id
994
- * @returns{Promise<object>} core object
1085
+ * @returns {Promise<object>} core object
995
1086
  * @memberof FAMISDb
996
1087
  */
997
1088
  async getCoreById(id) {
@@ -1056,7 +1147,7 @@ class FAMISDb {
1056
1147
  *
1057
1148
  * Get core by account number
1058
1149
  * @param {string} account
1059
- * @returns{Promise<object>} core object
1150
+ * @returns {Promise<object>} core object
1060
1151
  * @memberof FAMISDb
1061
1152
  */
1062
1153
  async getCoreByAccount(account) {
@@ -1096,7 +1187,7 @@ class FAMISDb {
1096
1187
  *
1097
1188
  * Get core current revenue account number
1098
1189
  * @param {string} coreId
1099
- * @returns{Promise<object>} core object
1190
+ * @returns {Promise<object>} core object
1100
1191
  * @memberof FAMISDb
1101
1192
  */
1102
1193
  async getCoreCurrentAccount(coreId) {
@@ -1158,7 +1249,7 @@ class FAMISDb {
1158
1249
  *
1159
1250
  * Get system part by ID
1160
1251
  * @param {number} id
1161
- * @returns{Promise<object>} system part object
1252
+ * @returns {Promise<object>} system part object
1162
1253
  * @memberof FAMISDb
1163
1254
  */
1164
1255
  async getSystemById(id) {
@@ -1179,7 +1270,7 @@ class FAMISDb {
1179
1270
  *
1180
1271
  * Get system part by two digit part number
1181
1272
  * @param {string} number
1182
- * @returns{Promise<object>} system part object
1273
+ * @returns {Promise<object>} system part object
1183
1274
  * @memberof FAMISDb
1184
1275
  */
1185
1276
  async getSystemByPartNumber(number) {
@@ -1200,7 +1291,7 @@ class FAMISDb {
1200
1291
  *
1201
1292
  * Get all enabled cores
1202
1293
  * @param {string} date
1203
- * @returns{Promise<array>} core objects
1294
+ * @returns {Promise<array>} core objects
1204
1295
  * @memberof FAMISDb
1205
1296
  */
1206
1297
  async getEnabledCores(date) {
@@ -1261,7 +1352,7 @@ class FAMISDb {
1261
1352
  /**
1262
1353
  *
1263
1354
  * Get all cores
1264
- * @returns{Promise<array>} core objects
1355
+ * @returns {Promise<array>} core objects
1265
1356
  * @memberof FAMISDb
1266
1357
  */
1267
1358
  async getAllCores() {
@@ -1282,7 +1373,7 @@ class FAMISDb {
1282
1373
  *
1283
1374
  * Get a core's users by core ID
1284
1375
  * @param {number} coreId
1285
- * @returns{Promise<array>} user objects
1376
+ * @returns {Promise<array>} user objects
1286
1377
  * @memberof FAMISDb
1287
1378
  */
1288
1379
  async getCoreUsers(coreId) {
@@ -1307,7 +1398,7 @@ class FAMISDb {
1307
1398
  *
1308
1399
  * Get a user's cores they manage
1309
1400
  * @param {string} userId
1310
- * @returns{Promise<array>} core objects
1401
+ * @returns {Promise<array>} core objects
1311
1402
  * @memberof FAMISDb
1312
1403
  */
1313
1404
  async getUserCores(userId) {
@@ -1333,7 +1424,7 @@ class FAMISDb {
1333
1424
  *
1334
1425
  * Get a system part's users by system ID
1335
1426
  * @param {number} systemId
1336
- * @returns{Promise<array>} user objects
1427
+ * @returns {Promise<array>} user objects
1337
1428
  * @memberof FAMISDb
1338
1429
  */
1339
1430
  async getSystemUsers(systemId) {
@@ -1358,7 +1449,7 @@ class FAMISDb {
1358
1449
  *
1359
1450
  * Get a user's system parts they manage
1360
1451
  * @param {*} userId
1361
- * @returns{Promise<object>} system objects
1452
+ * @returns {Promise<object>} system objects
1362
1453
  * @memberof FAMISDb
1363
1454
  */
1364
1455
  async getUserSystemParts(userId) {
@@ -1384,7 +1475,7 @@ class FAMISDb {
1384
1475
  /**
1385
1476
  *
1386
1477
  * Get all system parts
1387
- * @returns{Promise<object>} system objects
1478
+ * @returns {Promise<object>} system objects
1388
1479
  * @memberof FAMISDb
1389
1480
  */
1390
1481
  async getAllSystemParts() {
@@ -1398,11 +1489,27 @@ class FAMISDb {
1398
1489
  return retVal;
1399
1490
  }
1400
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
+
1401
1508
  /**
1402
1509
  *
1403
1510
  * Get user
1404
1511
  * @param {string} userId
1405
- * @returns{Promise<object>} user object
1512
+ * @returns {Promise<object>} user object
1406
1513
  * @memberof FAMISDb
1407
1514
  */
1408
1515
  async getUser(userId) {
@@ -1421,12 +1528,33 @@ class FAMISDb {
1421
1528
  return retVal;
1422
1529
  }
1423
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
+
1424
1552
  /**
1425
1553
  *
1426
1554
  * Get customer by customer account number
1427
1555
  * @param {string} accountNumber
1428
1556
  * @param {string} campusCode
1429
- * @returns{Promise<object>} customer account object
1557
+ * @returns {Promise<object>} customer account object
1430
1558
  * @memberof FAMISDb
1431
1559
  */
1432
1560
  async getCustomerNumber(accountNumber, campusCode) {
@@ -1439,7 +1567,7 @@ class FAMISDb {
1439
1567
  .where('uid', `${code}${accountNumber}`);
1440
1568
  if (records.length) {
1441
1569
  retVal = records[0];
1442
- }
1570
+ }
1443
1571
  } catch (e) {
1444
1572
  throw e;
1445
1573
  }
@@ -1449,7 +1577,7 @@ class FAMISDb {
1449
1577
  /**
1450
1578
  *
1451
1579
  * Get current fiscal year
1452
- * @returns{<integer>} fiscal year
1580
+ * @returns {<integer>} fiscal year
1453
1581
  * @memberof FAMISDb
1454
1582
  */
1455
1583
  getCurrentFiscalYear() {
@@ -1467,7 +1595,7 @@ class FAMISDb {
1467
1595
  *
1468
1596
  * Return fingerprint of invoice
1469
1597
  * @param {object} invoice json object
1470
- * @returns{<string>} fingerprint
1598
+ * @returns {<string>} fingerprint
1471
1599
  * @memberof FAMISDb
1472
1600
  */
1473
1601
  getInvoiceFingerPrint(invoice) {
@@ -1484,7 +1612,7 @@ class FAMISDb {
1484
1612
  *
1485
1613
  * Return formatted account number
1486
1614
  * @param {string} accountNumber unformatted 13 digit famis account number
1487
- * @returns{<string>} formatted 13 digits famis account number
1615
+ * @returns {<string>} formatted 13 digits famis account number
1488
1616
  * @memberof FAMISDb
1489
1617
  */
1490
1618
  formatAccountNumber(accountNumber) {
@@ -1492,6 +1620,243 @@ class FAMISDb {
1492
1620
 
1493
1621
  return formatted;
1494
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
+ }
1495
1860
  }
1496
1861
 
1497
- 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.2",
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
+ }