DBA Data[Home] [Help]

PACKAGE BODY: APPS.AP_WEB_AUDIT_PROCESS

Source


1 PACKAGE BODY AP_WEB_AUDIT_PROCESS AS
2 /* $Header: apwaudpb.pls 120.39 2010/12/23 12:53:06 dsadipir ship $ */
3 
4 -- jrautiai ADJ Fix Start
5 C_CompanyPay			CONSTANT VARCHAR2(10) := 'COMPANY';
6 -- jrautiai ADJ End
7 
8 /*========================================================================
9  | Prototype Declarations Procedures
10  *=======================================================================*/
11 PROCEDURE process_policy_violations(p_report_header_id IN NUMBER, p_audit_report OUT NOCOPY BOOLEAN);
12 PROCEDURE process_audit_list_member(p_report_header_id IN NUMBER, p_employee_id IN NUMBER, p_audit_report OUT NOCOPY BOOLEAN);
13 PROCEDURE process_old_receipts(p_report_header_id IN NUMBER, p_age_limit IN NUMBER, p_audit_report OUT NOCOPY BOOLEAN);
14 PROCEDURE process_receipts_required(p_report_header_id IN  NUMBER, p_audit_report OUT NOCOPY BOOLEAN);
15 PROCEDURE process_justification_required(p_report_header_id IN  NUMBER, p_audit_report OUT NOCOPY BOOLEAN);
16 PROCEDURE process_inactive(p_report_header_id IN  NUMBER, p_audit_report OUT NOCOPY BOOLEAN);
17 PROCEDURE process_unused_advance(p_report_header_id IN  NUMBER, p_audit_report OUT NOCOPY BOOLEAN);
18 PROCEDURE process_amount(p_report_header_id IN NUMBER, p_audit_all_amount_limit IN NUMBER, p_audit_all_amount_currency IN VARCHAR2, p_audit_report OUT NOCOPY BOOLEAN);
19 PROCEDURE process_random_audit(p_report_header_id             IN  NUMBER,
20                                p_random_audit_percentage      IN  NUMBER,
21                                p_ignore_credit_only_flag      IN  VARCHAR2,
22                                p_ignore_rj_not_req_only_flag  IN  VARCHAR2,
23                                p_audit_report                 OUT NOCOPY BOOLEAN);
24 PROCEDURE process_custom_audit(p_report_header_id IN NUMBER, p_audit_report OUT NOCOPY BOOLEAN, p_override_default_processing OUT NOCOPY BOOLEAN);
25 PROCEDURE update_audit_code(p_report_header_id IN NUMBER, p_audit_code IN VARCHAR2);
26 PROCEDURE process_paperless_audit(p_report_header_id          IN  NUMBER,
27                                   p_pl_audit_all_flag	      IN  VARCHAR2,
28                                   p_pl_audit_cc_only_flag     IN  VARCHAR2,
29                                   p_pl_audit_violation_flag   IN  VARCHAR2,
30                                   p_pl_audit_pdm_only_flag    IN  VARCHAR2,
31                                   p_assign_auditor_stage_code IN  VARCHAR2,
32                                   p_audit_report              OUT NOCOPY BOOLEAN);
33 
34 PROCEDURE process_audit_list(p_report_header_id IN NUMBER);
35 PROCEDURE insert_audit_reason(p_report_header_id IN NUMBER, p_audit_reason_code IN VARCHAR2);
36 PROCEDURE update_audit_reason(p_report_header_id IN NUMBER, p_audit_reason_code IN VARCHAR2);
37 PROCEDURE process_receiptbased_audit(p_report_header_id IN NUMBER, p_audit_code OUT NOCOPY VARCHAR2);
38 FUNCTION get_report_violation_count(p_report_header_id IN  NUMBER) RETURN NUMBER;
39 FUNCTION get_employee_violation_count(p_employee_id IN  NUMBER, p_months IN  NUMBER) RETURN NUMBER;
40 PROCEDURE process_random_audit(p_report_header_id IN NUMBER, p_audit_code OUT NOCOPY VARCHAR2);
41 
42 /*========================================================================
43  | Prototype Declarations Functions
44  *=======================================================================*/
45 FUNCTION construct_random_percentage(pn_random_number NUMBER) RETURN NUMBER;
46 FUNCTION get_random_percentage RETURN NUMBER;
47 FUNCTION get_shortpaid_audit_code(p_report_header_id IN NUMBER) RETURN VARCHAR2;
48 
49 /*========================================================================
50  | PUBLIC FUNCTION get_shortpaid_audit_code
51  |
52  | DESCRIPTION
53  |   This function returns the audit code of parent report for a shortpaid expense report.
54  |
55  | CALLED FROM PROCEDURES/FUNCTIONS (local to this package body)
56  |
57  | RETURNS
58  |   audit_code  VARCHAR2
59  |
60  | PARAMETERS
61  |   p_report_header_id IN  Expense Report identifier
62  |
63  | MODIFICATION HISTORY
64  | Date                  Author                 Description of Changes
65  | 20-Dec-2005           SaiKumar Talasila      Created
66   *=======================================================================*/
67 
68 FUNCTION get_shortpaid_audit_code(p_report_header_id IN NUMBER) RETURN VARCHAR2 IS
69 l_audit_code                    VARCHAR2(30);
70 l_parent_report_id              NUMBER;
71 BEGIN
72 
73         SELECT shortpay_parent_id INTO l_parent_report_id
74         FROM   ap_expense_report_headers_all
75         WHERE  report_header_id = p_report_header_id;
76 
77         IF l_parent_report_id is NOT NULL THEN
78           SELECT audit_code into l_audit_code
79           FROM   ap_expense_report_headers_all
80           WHERE  report_header_id = l_parent_report_id;
81 
82           RETURN l_audit_code;
83         ELSE
84           RETURN NULL;
85         END IF;
86 
87 EXCEPTION
88         WHEN NO_DATA_FOUND THEN
89          RETURN NULL;
90         WHEN OTHERS THEN
91          AP_WEB_DB_UTIL_PKG.RaiseException('get_shortpaid_audit_code');
92          APP_EXCEPTION.RAISE_EXCEPTION;
93 
94 END get_shortpaid_audit_code;
95 
96 /*========================================================================
97  | PUBLIC FUNCTION process_expense_report
98  |
99  | DESCRIPTION
100  |   This function does audit processing for a given expense report.
101  |
102  | CALLED FROM PROCEDURES/FUNCTIONS (local to this package body)
103  |   Called from BC4J.
104  |
105  | CALLS PROCEDURES/FUNCTIONS (local to this package body)
106  |
107  | RETURNS
108  |   Tag containing auditing information as VARCHAR2.
109  |
110  | PARAMETERS
111  |   p_report_header_id IN  Expense Report identifier
112  |
113  | MODIFICATION HISTORY
114  | Date                  Author            Description of Changes
115  | 13-Oct-2002           J Rautiainen      Created
116  | 11-Mar-2005           Maulik Vadera     Bug 4192680: Modified code to set the audit code
117  |                                         AUTO_APPROVE for the reports those contain
118  |                                         only both pay personal expense.
119  *=======================================================================*/
120 FUNCTION process_expense_report(p_report_header_id IN NUMBER) RETURN VARCHAR2 IS
121 --PRAGMA AUTONOMOUS_TRANSACTION;
122 
123   CURSOR process_cur IS
124     select rs.rule_set_id,
125            rs.rule_set_type,
126            rs.description,
127            rs.start_date,
128            rs.end_date,
129            rs.paperless_audit_cc_only_flag,
130            rs.paperless_audit_violation_flag,
131            rs.paperless_audit_pdm_only_flag,
132            rs.assign_auditor_stage_code,
133            rs.audit_all_violations_flag,
134            rs.audit_all_from_audit_list_flag,
135            rs.audit_all_old_receipts_flag,
136            rs.audit_all_receipt_days_limit,
137            rs.random_audit_flag,
138            rs.random_audit_percentage,
139            rs.ignore_credit_only_flag,
140            rs.ignore_rj_not_req_only_flag,
141            rs.auto_approval_tag,
142            rs.requires_audit_tag,
143            rs.paperless_audit_tag,
144            aerh.employee_id,
145            aerh.audit_code,
146            rs.rule_set_name,
147            aerh.org_id,
148            rs.audit_all_amount_code,
149            rs.audit_all_amount_limit,
150            rs.audit_all_amount_currency_code,
151            rs.audit_all_receipts_code,
152            rs.audit_all_justification_code,
153            rs.audit_all_inactive_code,
154 	   rs.audit_all_unused_advances,
155 	   rs.AUD_IMG_RECEIPT_REQUIRED,
156 	   rs.AUD_PAPER_RECEIPT_REQUIRED,
157 	   rs.RECPT_ASSIGN_STAGE_CODE,
158 	   rs.IMAGE_AUDIT_TAG,
159            rs.audit_all
160     from AP_EXPENSE_REPORT_HEADERS_ALL aerh,
161          AP_AUD_RULE_SETS rs,
162          AP_AUD_RULE_ASSIGNMENTS_ALL rsa
163     where aerh.report_header_id = p_report_header_id
164     and   aerh.org_id = rsa.org_id
165     and   rsa.rule_set_id = rs.rule_set_id
166     and   rs.rule_set_type = 'RULE'
167     and   TRUNC(SYSDATE)
168             BETWEEN TRUNC(NVL(rsa.START_DATE,SYSDATE))
169             AND     TRUNC(NVL(rsa.END_DATE,SYSDATE));
170 
171   process_rec                   process_cur%ROWTYPE;
172   audit_report                  boolean := false;
173   audit_report_tmp              boolean := false;
174   override_default_processing   boolean := false;
175   l_bpay_personal_cc_only       boolean := false;
176   l_shortpaid_report            boolean := false;
177   audit_code                    VARCHAR2(30);
178   l_audit_code                  VARCHAR2(30);
179   l_old_audit_code         ap_expense_report_headers_all.audit_code%type := null;
180   l_old_audit_reason_code  ap_aud_audit_reasons.audit_reason_code%type := null;
181 BEGIN
182 
183   IF p_report_header_id is null THEN
184     return null;
185   END IF;
186 
187   OPEN process_cur;
188   FETCH process_cur INTO process_rec;
189 
190   IF process_cur%NOTFOUND THEN
191     CLOSE process_cur;
192     return null;
193   END IF;
194 
195   CLOSE process_cur;
196 
197   -- Bug 9363646: (sodash) moved the code so that the check for credit card transactions is done first
198   l_bpay_personal_cc_only := bothpay_personal_cc_only(p_report_header_id);
199 
200   IF l_bpay_personal_cc_only THEN
201 
202     audit_code := 'AUTO_APPROVE';
203     update_audit_code(p_report_header_id, audit_code);
204     COMMIT;
205 
206     RETURN process_rec.auto_approval_tag;
207 
208   END IF;
209 
210   --Bug#6632506 : AuditCode should be copied form parent report for a shortpaid report
211   l_shortpaid_report := ap_web_audit_queue_utils.report_shortpaid(p_report_header_id);
212 
213   -- Bug# 10385358: To insert the audit reasons for the shortpaid expense report
214   IF l_shortpaid_report THEN
215     l_audit_code := null;
216   ELSE
217     l_audit_code := process_rec.audit_code;
218   END IF;
219 
220   /*IF l_shortpaid_report THEN
221     audit_code := get_shortpaid_audit_code(p_report_header_id);
222 
223     IF audit_code is NOT NULL THEN
224 
225       update_audit_code(p_report_header_id, audit_code);
226       COMMIT;
227 
228       IF audit_code = 'PAPERLESS_AUDIT' THEN
229         IF (NVL(process_rec.assign_auditor_stage_code,'MANAGER_APPROVAL') = 'SUBMISSION') THEN
230           AP_WEB_AUDIT_QUEUE_UTILS.enqueue_for_audit(p_report_header_id);
231           COMMIT;
232         END IF;
233       END IF;
234 
235       IF audit_code = 'PAPERLESS_AUDIT' THEN
236         RETURN process_rec.paperless_audit_tag;
237       ELSIF audit_code = 'AUTO_APPROVE' THEN
238         RETURN process_rec.auto_approval_tag;
239       ELSIF audit_code = 'RECEIPT_BASED' THEN
240         RETURN process_rec.image_audit_tag;
241       ELSE
242         RETURN process_rec.requires_audit_tag;
243       END IF;
244      END IF;
245 
246   END IF;*/
247 
248  process_audit_list(p_report_header_id);
249 
250  IF l_audit_code IS NULL OR l_audit_code = 'AUTO_APPROVE' THEN
251     IF l_shortpaid_report THEN
252       AP_WEB_AUDIT_UTILS.clear_audit_reason_codes(p_report_header_id);
253     END IF;
254 
255     process_custom_audit(p_report_header_id, audit_report_tmp, override_default_processing);
256 
257     audit_report := audit_report_tmp;
258 
259     IF (NVL(override_default_processing, FALSE) = TRUE) THEN
260       null;
261     ELSE
262 
263       IF NVL(process_rec.audit_all_violations_flag, 'N') = 'Y' THEN
264         process_policy_violations(p_report_header_id, audit_report_tmp);
265 
266         IF audit_report = false THEN
267           audit_report := audit_report_tmp;
268         END IF;
269       END IF;
270 
271       IF NVL(process_rec.audit_all_from_audit_list_flag, 'N') = 'Y' THEN
272         process_audit_list_member(p_report_header_id, process_rec.employee_id, audit_report_tmp);
273 
274         IF audit_report = false THEN
275           audit_report := audit_report_tmp;
276         END IF;
277       END IF;
278 
279       IF NVL(process_rec.audit_all_old_receipts_flag, 'N') = 'Y' THEN
280         process_old_receipts(p_report_header_id, process_rec.audit_all_receipt_days_limit, audit_report_tmp);
281 
282         IF audit_report = false THEN
283           audit_report := audit_report_tmp;
284         END IF;
285       END IF;
286 
287       /* Bug 4019412 : If the expense report  was previously randomly chosen for
288        * audit, it should be audited even if it is withdrawn and resubmitted.
289        */
290       BEGIN
291         select audit_reason_code, audit_code
292         into   l_old_audit_reason_code, l_old_audit_code
293         from
294         (
295             select audit_code, audit_reason_code
296             from   ap_expense_report_headers_all aerh,
297                    ap_aud_audit_reasons aud
298             where  aerh.report_header_id = p_report_header_id
299             and    aerh.report_header_id = aud.report_header_id
300             and    aud.audit_reason_code = 'RANDOM'
301         )
302         where rownum=1;
303       EXCEPTION WHEN NO_DATA_FOUND THEN
304          NULL;
305       END;
306 
307       IF l_old_audit_code is NULL and l_old_audit_reason_code = 'RANDOM' then
308             update_audit_reason(p_report_header_id, 'RANDOM');
309             audit_report := TRUE;
310       ELSIF NVL(process_rec.random_audit_flag, 'N') = 'Y' THEN
311         process_random_audit(p_report_header_id,
312                              process_rec.random_audit_percentage,
313                              process_rec.ignore_credit_only_flag,
314                              process_rec.ignore_rj_not_req_only_flag,
315                              audit_report_tmp);
316 
317         IF audit_report = false THEN
318           audit_report := audit_report_tmp;
319         END IF;
320 
321       END IF;
322 
323       IF NVL(process_rec.audit_all_amount_code, 'NOT_ACTIVE') = 'GREATER_THAN' THEN
324         process_amount(p_report_header_id,
325                        process_rec.audit_all_amount_limit,
326                        process_rec.audit_all_amount_currency_code,
327                        audit_report_tmp);
328 
329         IF audit_report = false THEN
330           audit_report := audit_report_tmp;
331         END IF;
332       END IF;
333 
334       IF NVL(process_rec.audit_all_receipts_code, 'NOT_ACTIVE') = 'REQUIRED' THEN
335         process_receipts_required(p_report_header_id, audit_report_tmp);
336 
337         IF audit_report = false THEN
338           audit_report := audit_report_tmp;
339         END IF;
340       END IF;
341 
342       IF NVL(process_rec.audit_all_justification_code, 'NOT_ACTIVE') = 'REQUIRED' THEN
343         process_justification_required(p_report_header_id, audit_report_tmp);
344 
345         IF audit_report = false THEN
346           audit_report := audit_report_tmp;
347         END IF;
348       END IF;
349 
350       IF NVL(process_rec.audit_all_inactive_code, 'NOT_ACTIVE') = 'INACTIVE' THEN
351         process_inactive(p_report_header_id, audit_report_tmp);
352 
353         IF audit_report = false THEN
354           audit_report := audit_report_tmp;
355         END IF;
356       END IF;
357 
358       IF NVL(process_rec.audit_all_unused_advances, 'N') = 'Y' THEN
359         process_unused_advance(p_report_header_id, audit_report_tmp);
360 
361         IF audit_report = false THEN
362           audit_report := audit_report_tmp;
363         END IF;
364       END IF;
365 
366     END IF; -- override_default_processing = TRUE
367 
368 
369     audit_code := 'AUDIT';
370     IF (audit_report = false) THEN
371       audit_code := 'AUTO_APPROVE';
372 
373     ELSIF (NVL(process_rec.AUD_IMG_RECEIPT_REQUIRED, 'N') = 'Y'
374            OR NVL(process_rec.AUD_PAPER_RECEIPT_REQUIRED, 'N') = 'Y' ) THEN
375 
376 	process_receiptbased_audit(p_report_header_id, audit_code);
377 
378 	/*IF audit_report_tmp = true THEN
379 	 audit_code := 'RECEIPT_BASED';
380 	END IF;*/
381 
382     ELSIF (NVL(process_rec.audit_all, 'N') = 'Y'
383         OR NVL(process_rec.paperless_audit_cc_only_flag, 'N') = 'Y'
384         OR NVL(process_rec.paperless_audit_violation_flag, 'N') = 'Y'
385         OR NVL(process_rec.paperless_audit_pdm_only_flag, 'N') = 'Y') THEN
386 
387       process_paperless_audit(p_report_header_id,
388                               NVL(process_rec.audit_all, 'N'),
389                               NVL(process_rec.paperless_audit_cc_only_flag, 'N'),
390                               NVL(process_rec.paperless_audit_violation_flag, 'N'),
391                               NVL(process_rec.paperless_audit_pdm_only_flag, 'N'),
392                               NVL(process_rec.assign_auditor_stage_code,'MANAGER_APPROVAL'),
393                               audit_report_tmp);
394 
395       IF audit_report_tmp = true THEN
396         audit_code := 'PAPERLESS_AUDIT';
397       END IF;
398     END IF;
399 
400     IF(audit_code IS NULL OR audit_code = 'AUDIT') THEN
401 	process_random_audit(p_report_header_id, audit_code);
402         IF (audit_code = 'PAPERLESS_AUDIT' AND
403             (NVL(process_rec.audit_all, 'N') = 'Y'
404              OR (NVL(process_rec.paperless_audit_cc_only_flag, 'N') = 'Y' AND AP_WEB_UTILITIES_PKG.ReportHasOnlyCCLines(p_report_header_id) = TRUE)
405              OR (NVL(process_rec.paperless_audit_violation_flag, 'N') = 'Y' AND AP_WEB_UTILITIES_PKG.ReportHasViolations(p_report_header_id) = TRUE)
406              OR (NVL(process_rec.paperless_audit_pdm_only_flag, 'N') = 'Y' AND AP_WEB_UTILITIES_PKG.ReportHasNonRecLines(p_report_header_id) = TRUE)))
407         THEN
408           IF (NVL(process_rec.assign_auditor_stage_code,'MANAGER_APPROVAL') = 'SUBMISSION') THEN
409              AP_WEB_AUDIT_QUEUE_UTILS.enqueue_for_audit(p_report_header_id);
410           END IF;
411         END IF;
412 
413     END IF;
414 
415     IF l_shortpaid_report AND audit_code = 'AUTO_APPROVE' THEN
416       audit_code := 'AUDIT';
417     END IF;
418 
419     update_audit_code(p_report_header_id, audit_code);
420 
421     COMMIT;
422  ELSE
423     audit_code := process_rec.audit_code;
424 
425     IF (audit_code = 'PAPERLESS_AUDIT' AND
426 	(NVL(process_rec.audit_all, 'N') = 'Y'
427         OR (NVL(process_rec.paperless_audit_cc_only_flag, 'N') = 'Y' AND AP_WEB_UTILITIES_PKG.ReportHasOnlyCCLines(p_report_header_id) = TRUE)
428         OR (NVL(process_rec.paperless_audit_violation_flag, 'N') = 'Y' AND AP_WEB_UTILITIES_PKG.ReportHasViolations(p_report_header_id) = TRUE)
429         OR (NVL(process_rec.paperless_audit_pdm_only_flag, 'N') = 'Y' AND AP_WEB_UTILITIES_PKG.ReportHasNonRecLines(p_report_header_id) = TRUE)))
430     THEN
431       IF (NVL(process_rec.assign_auditor_stage_code,'MANAGER_APPROVAL') = 'SUBMISSION') THEN
432         AP_WEB_AUDIT_QUEUE_UTILS.enqueue_for_audit(p_report_header_id);
433         COMMIT;
434       END IF;
435     END IF;
436  END IF; --process_rec.audit_code IS NULL
437 
438   IF audit_code = 'PAPERLESS_AUDIT' THEN
439     RETURN process_rec.paperless_audit_tag;
440   ELSIF audit_code = 'AUTO_APPROVE' THEN
441     RETURN process_rec.auto_approval_tag;
442   ELSIF audit_code = 'RECEIPT_BASED' THEN
443     RETURN process_rec.image_audit_tag;
444   ELSE
445     RETURN process_rec.requires_audit_tag;
446   END IF;
447 
448 END process_expense_report;
449 
450 /*========================================================================
451  | PRIVATE PROCEDURE process_policy_violations
452  |
453  | DESCRIPTION
454  |   This procedure does policy violation processing for a given expense report.
455  |
456  | CALLED FROM PROCEDURES/FUNCTIONS (local to this package body)
457  |   Called from BC4J.
458  |
459  | CALLS PROCEDURES/FUNCTIONS (local to this package body)
460  |
461  | RETURNS
462  |
463  | PARAMETERS
464  |   p_report_header_id IN  Expense Report identifier
465  |   p_audit_report     OUT NOCOPY TRUE if report needs to be audited
466  |
467  | MODIFICATION HISTORY
468  | Date                  Author            Description of Changes
469  | 13-Oct-2002           J Rautiainen      Created
470  |
471  *=======================================================================*/
472 PROCEDURE process_policy_violations(p_report_header_id IN  NUMBER,
473                                     p_audit_report     OUT NOCOPY BOOLEAN) IS
474 BEGIN
475   p_audit_report := FALSE;
476 
477   IF get_report_violation_count(p_report_header_id) > 0 THEN
478     insert_audit_reason(p_report_header_id, 'POLICY_VIOLATION');
479     p_audit_report := TRUE;
480   END IF;
481 
482 END process_policy_violations;
483 
484 /*========================================================================
485  | PRIVATE PROCEDURE process_audit_list_member
486  |
487  | DESCRIPTION
488  |   This procedure does audit list member processing for a given expense report.
489  |
490  | CALLED FROM PROCEDURES/FUNCTIONS (local to this package body)
491  |   Called from BC4J.
492  |
493  | CALLS PROCEDURES/FUNCTIONS (local to this package body)
494  |
495  | RETURNS
496  |
497  | PARAMETERS
498  |   p_report_header_id IN  Expense Report identifier
499  |   p_employee_id      IN  Employee identifier
500  |   p_audit_report     OUT NOCOPY TRUE if report needs to be audited
501  |
502  | MODIFICATION HISTORY
503  | Date                  Author            Description of Changes
504  | 13-Oct-2002           J Rautiainen      Created
505  |
506  *=======================================================================*/
507 PROCEDURE process_audit_list_member(p_report_header_id IN NUMBER,
508                                     p_employee_id      IN NUMBER,
509                                     p_audit_report     OUT NOCOPY BOOLEAN) IS
510 
511   CURSOR audit_list_cur IS
512     select auto_audit_id
513     from AP_AUD_AUTO_AUDITS
514     where employee_id = p_employee_id
515     and   TRUNC(SYSDATE)
516             BETWEEN TRUNC(NVL(START_DATE,SYSDATE))
517             AND     TRUNC(NVL(END_DATE,SYSDATE));
518 
519   audit_list_rec audit_list_cur%ROWTYPE;
520 
521 BEGIN
522   p_audit_report := FALSE;
523 
524   OPEN audit_list_cur;
525   FETCH audit_list_cur INTO audit_list_rec;
526 
527   IF audit_list_cur%FOUND THEN
528     insert_audit_reason(p_report_header_id, 'AUDIT_LIST');
529     p_audit_report := TRUE;
530   END IF;
531 
532   CLOSE audit_list_cur;
533 
534 END process_audit_list_member;
535 
536 /*========================================================================
537  | PRIVATE PROCEDURE process_old_receipts
538  |
539  | DESCRIPTION
540  |   This procedure does old receipt processing for a given expense report.
541  |
542  | CALLED FROM PROCEDURES/FUNCTIONS (local to this package body)
543  |   Called from BC4J.
544  |
545  | CALLS PROCEDURES/FUNCTIONS (local to this package body)
546  |
547  | RETURNS
548  |
549  | PARAMETERS
550  |   p_report_header_id IN  Expense Report identifier
551  |   p_audit_report     OUT NOCOPY TRUE if report needs to be audited
552  |
553  | MODIFICATION HISTORY
554  | Date                  Author            Description of Changes
555  | 13-Oct-2002           J Rautiainen      Created
556  |
557  *=======================================================================*/
558 PROCEDURE process_old_receipts(p_report_header_id IN  NUMBER,
559                                p_age_limit        IN  NUMBER,
560                                p_audit_report     OUT NOCOPY BOOLEAN) IS
561 
562   CURSOR receipt_cur IS
563     select min(start_expense_date) oldest_receipt_date
564     from AP_EXPENSE_REPORT_LINES_ALL
565     where report_header_id = p_report_header_id;
566 
567   receipt_rec receipt_cur%ROWTYPE;
568 
569 BEGIN
570   p_audit_report := FALSE;
571 
572   OPEN receipt_cur;
573   FETCH receipt_cur INTO receipt_rec;
574 
575   IF receipt_cur%FOUND THEN
576     IF trunc(receipt_rec.oldest_receipt_date) < (trunc(SYSDATE) - p_age_limit) THEN
577       insert_audit_reason(p_report_header_id, 'OVERDUE_RECEIPTS');
578       p_audit_report := TRUE;
579     END IF;
580   END IF;
581 
582   CLOSE receipt_cur;
583 
584 END process_old_receipts;
585 
586 /*========================================================================
587  | PRIVATE PROCEDURE process_receipts_required
588  |
589  | DESCRIPTION
590  |   This procedure does receipts required rule processing for a given
591  |   expense report.
592  |
593  | CALLED FROM PROCEDURES/FUNCTIONS (local to this package body)
594  |   Called from BC4J.
595  |
596  | CALLS PROCEDURES/FUNCTIONS (local to this package body)
597  |
598  | RETURNS
599  |
600  | PARAMETERS
601  |   p_report_header_id IN  Expense Report identifier
602  |   p_audit_report     OUT NOCOPY TRUE if report needs to be audited
603  |
604  | MODIFICATION HISTORY
605  | Date                  Author            Description of Changes
606  | 16-Dec-2004           J Rautiainen      Created
607  |
608  *=======================================================================*/
609 PROCEDURE process_receipts_required(p_report_header_id IN  NUMBER,
610                                     p_audit_report     OUT NOCOPY BOOLEAN) IS
611 
612   CURSOR receipt_cur IS
613     select count(1) required_count
614     from AP_EXPENSE_REPORT_LINES_ALL
615     where report_header_id = p_report_header_id
616     and   (NVL(receipt_required_flag,'N') = 'Y'
617 	   OR NVL(image_receipt_required_flag,'N') = 'Y');
618 
619   receipt_rec receipt_cur%ROWTYPE;
620 
621 BEGIN
622   p_audit_report := FALSE;
623 
624   OPEN receipt_cur;
625   FETCH receipt_cur INTO receipt_rec;
626   IF receipt_rec.required_count > 0 THEN
627     insert_audit_reason(p_report_header_id, 'RECEIPT_REQUIRED');
628     p_audit_report := TRUE;
629   END IF;
630 
631   CLOSE receipt_cur;
632 
633 END process_receipts_required;
634 
635 /*========================================================================
636  | PRIVATE PROCEDURE process_justification_required
637  |
638  | DESCRIPTION
639  |   This procedure does justification required rule processing for a given
640  |   expense report.
641  |
642  | CALLED FROM PROCEDURES/FUNCTIONS (local to this package body)
643  |   Called from BC4J.
644  |
645  | CALLS PROCEDURES/FUNCTIONS (local to this package body)
646  |
647  | RETURNS
648  |
649  | PARAMETERS
650  |   p_report_header_id IN  Expense Report identifier
651  |   p_audit_report     OUT NOCOPY TRUE if report needs to be audited
652  |
653  | MODIFICATION HISTORY
654  | Date                  Author            Description of Changes
655  | 16-Dec-2004           J Rautiainen      Created
656  |
657  *=======================================================================*/
658 PROCEDURE process_justification_required(p_report_header_id IN  NUMBER,
659                                          p_audit_report     OUT NOCOPY BOOLEAN) IS
660 
661   CURSOR line_cur IS
662     select count(aerl.report_header_id) required_count
663     from AP_EXPENSE_REPORT_LINES_ALL aerl
664     where aerl.report_header_id = p_report_header_id
665     and   ((   NVL(aerl.justification_required_flag,'N') = 'Y'
666            OR (
667                     NVL(aerl.justification_required_flag,'N') = 'V'
668                 AND EXISTS(select 1
669                            from ap_pol_violations_all pv
670                            where pv.report_header_id = aerl.report_header_id
671                            and   pv.distribution_line_number = aerl.distribution_line_number
672                            )
673               )
674           )
675 	  OR (EXISTS(select 1 from ap_expense_report_headers_all aerh
676                      where aerh.report_header_id = aerl.report_header_id
677                      and   aerh.missing_img_just IS NOT NULL)));
678 
679   line_rec line_cur%ROWTYPE;
680 
681 BEGIN
682   p_audit_report := FALSE;
683 
684   OPEN line_cur;
685   FETCH line_cur INTO line_rec;
686   IF line_rec.required_count > 0 THEN
687     insert_audit_reason(p_report_header_id, 'REQUIRED_JUSTIFICATION');
688     p_audit_report := TRUE;
689   END IF;
690 
691   CLOSE line_cur;
692 
693 END process_justification_required;
694 
695 /*========================================================================
696  | PRIVATE PROCEDURE process_inactive
697  |
698  | DESCRIPTION
699  |   This procedure does inactive employee rule processing for a given
700  |   expense report.
701  |
702  | CALLED FROM PROCEDURES/FUNCTIONS (local to this package body)
703  |   Called from BC4J.
704  |
705  | CALLS PROCEDURES/FUNCTIONS (local to this package body)
706  |
707  | RETURNS
708  |
709  | PARAMETERS
710  |   p_report_header_id IN  Expense Report identifier
711  |   p_audit_report     OUT NOCOPY TRUE if report needs to be audited
712  |
713  | MODIFICATION HISTORY
714  | Date                  Author            Description of Changes
715  | 16-Dec-2004           J Rautiainen      Created
716  |
717  *=======================================================================*/
718 PROCEDURE process_inactive(p_report_header_id IN  NUMBER,
719                            p_audit_report     OUT NOCOPY BOOLEAN) IS
720 
721   CURSOR report_cur IS
722     select AP_WEB_AUDIT_UTILS.is_employee_active(employee_id, org_id) active
723     from AP_EXPENSE_REPORT_HEADERS_ALL
724     where report_header_id = p_report_header_id;
725 
726   report_rec report_cur%ROWTYPE;
727 
728 BEGIN
729   p_audit_report := FALSE;
730 
731   OPEN report_cur;
732   FETCH report_cur INTO report_rec;
733   IF     report_cur%FOUND
734      AND report_rec.active = 'N' THEN
735     insert_audit_reason(p_report_header_id, 'INACTIVE_EMPLOYEE');
736     p_audit_report := TRUE;
737   END IF;
738 
739   CLOSE report_cur;
740 
741 END process_inactive;
742 
743 /*========================================================================
744  | PRIVATE PROCEDURE process_unused_advance
745  |
746  | DESCRIPTION
747  |   This procedure does unused advance rule processing for a given
748  |   expense report.
749  |
750  | CALLED FROM PROCEDURES/FUNCTIONS (local to this package body)
751  |   Called from BC4J.
752  |
753  | CALLS PROCEDURES/FUNCTIONS (local to this package body)
754  |
755  | RETURNS
756  |
757  | PARAMETERS
758  |   p_report_header_id IN  Expense Report identifier
759  |   p_audit_report     OUT NOCOPY TRUE if report needs to be audited |
760  |
761  *=======================================================================*/
762 PROCEDURE process_unused_advance(p_report_header_id IN  NUMBER,
763                                  p_audit_report     OUT NOCOPY BOOLEAN) IS
764 
765   adv_not_applied_flag VARCHAR2(1) := 'N';
766 
767 BEGIN
768   p_audit_report := FALSE;
769 
770   BEGIN
771     SELECT 'Y'
772     INTO adv_not_applied_flag
773     FROM dual
774     WHERE EXISTS(
775       SELECT 'Y'
776       FROM  ap_expense_report_headers_all XH,
777             ap_invoices_all AI,
778             po_vendors PV
779       WHERE XH.report_header_id = p_report_header_id
780       AND XH.prepay_num IS NULL
781       AND XH.advance_invoice_to_apply IS NULL
782       AND Nvl(XH.maximum_amount_to_apply,0) = 0
783       AND PV.employee_id = XH.employee_id
784       AND AI.vendor_id = PV.vendor_id
785       AND AI.invoice_type_lookup_code = 'PREPAYMENT'
786       AND AI.earliest_settlement_date <= sysdate
787       AND AI.payment_status_flag = 'Y'
788       AND AI.invoice_currency_code = XH.payment_currency_code
789       AND AP_WEB_PAYMENTS_PKG.get_prepay_amount_remaining(AI.invoice_id,AI.invoice_num,PV.employee_id,XH.default_currency_code,null,null,200) > 0
790     );
791   EXCEPTION
792     WHEN NO_DATA_FOUND THEN
793        adv_not_applied_flag := 'N';
794   END;
795 
796   IF  ( adv_not_applied_flag = 'Y' ) THEN
797     insert_audit_reason(p_report_header_id, 'UNAPPLIED_ADVANCE');
798     p_audit_report := TRUE;
799   END IF;
800 
801 END process_unused_advance;
802 
803 
804 /*========================================================================
805  | PRIVATE PROCEDURE process_amount
806  |
807  | DESCRIPTION
808  |   This procedure does amount rule processing for a given
809  |   expense report.
810  |
811  | CALLED FROM PROCEDURES/FUNCTIONS (local to this package body)
812  |   Called from BC4J.
813  |
814  | CALLS PROCEDURES/FUNCTIONS (local to this package body)
815  |
816  | RETURNS
817  |
818  | PARAMETERS
819  |   p_report_header_id IN  Expense Report identifier
820  |   p_audit_report     OUT NOCOPY TRUE if report needs to be audited
821  |
822  | MODIFICATION HISTORY
823  | Date                  Author            Description of Changes
824  | 16-Dec-2004           J Rautiainen      Created
825  |
826  *=======================================================================*/
827 PROCEDURE process_amount(p_report_header_id               IN NUMBER,
828                          p_audit_all_amount_limit         IN NUMBER,
829                          p_audit_all_amount_currency IN VARCHAR2,
830                          p_audit_report                   OUT NOCOPY BOOLEAN) IS
831 
832   CURSOR report_cur IS
833     select aerh.default_currency_code,
834            aerh.total,
835            sp.default_exchange_rate_type
836     from AP_EXPENSE_REPORT_HEADERS_ALL aerh,
837          ap_system_parameters_all sp
838     where aerh.report_header_id = p_report_header_id
839     and   sp.org_id = aerh.org_id;
840 
841   report_rec report_cur%ROWTYPE;
842   l_total    NUMBER := to_number(null);
843   denominator                 NUMBER;--Bug#8997430
844   numerator                   NUMBER;--Bug#8997430
845   rate                        NUMBER;--Bug#8997430
846 
847 BEGIN
848   p_audit_report := FALSE;
849 
850   OPEN report_cur;
851   FETCH report_cur INTO report_rec;
852   IF report_cur%FOUND THEN
853 
854     IF report_rec.default_currency_code = p_audit_all_amount_currency THEN
855       l_total := report_rec.total;
856     ELSE
857       BEGIN
858         --Bug#8997430 - Audit Expense Report if Exchange Rate does not exist.
859         --If the rate_type is User and if there is no fixed rate between currencies
860         --then select the report for audit.
861         gl_currency_api.convert_closest_amount(
862                                             report_rec.default_currency_code ,
863                                             p_audit_all_amount_currency ,
864                                             SYSDATE ,
865                                             report_rec.default_exchange_rate_type ,
866                                             null ,
867                                             report_rec.total ,
868                                             7 ,
869                                             l_total ,
870                                             denominator ,
871                                             numerator ,
872                                             rate );
873 
874       EXCEPTION
875         WHEN OTHERS THEN
876          /* If amount cannot be converted, then the rule is ignored as per the
877           * functional design */
878           l_total := null;
879       END;
880     END IF;
881 
882     IF ((l_total IS NOT NULL AND l_total > p_audit_all_amount_limit)
883         OR (l_total IS NULL)) THEN
884       insert_audit_reason(p_report_header_id, 'AMOUNT');
885       p_audit_report := TRUE;
886     END IF;
887   END IF;
888 
889   CLOSE report_cur;
890 
891 END process_amount;
892 
893 /*========================================================================
894  | PRIVATE PROCEDURE process_random_audit
895  |
896  | DESCRIPTION
897  |   This procedure randomly selects expense reports for audit.
898  |
899  | CALLED FROM PROCEDURES/FUNCTIONS (local to this package body)
900  |   Called from BC4J.
901  |
902  | CALLS PROCEDURES/FUNCTIONS (local to this package body)
903  |
904  | RETURNS
905  |
906  | PARAMETERS
907  |   p_report_header_id             IN  Expense Report identifier
908  |   p_random_audit_percentage      IN  Probability this report will be audited
909  |   p_ignore_credit_only_flag      IN  Ignore reports which contain only credit lines
910  |   p_ignore_rj_not_req_only_flag  IN  Ignore reports which contain only receipts where
911  |                                      receipt and justification is not required.
912  |   p_audit_report            OUT NOCOPY TRUE if report needs to be audited
913  |
914  | MODIFICATION HISTORY
915  | Date                  Author            Description of Changes
916  | 13-Oct-2002           J Rautiainen      Created
917  |
918  *=======================================================================*/
919 PROCEDURE process_random_audit(p_report_header_id             IN  NUMBER,
920                                p_random_audit_percentage      IN  NUMBER,
921                                p_ignore_credit_only_flag      IN  VARCHAR2,
922                                p_ignore_rj_not_req_only_flag  IN  VARCHAR2,
923                                p_audit_report                 OUT NOCOPY BOOLEAN) IS
924 
925   CURSOR debit_cur IS
926     select count(1) debit_line_count
927     from ap_expense_report_lines_all aerl
928     where aerl.report_header_id = p_report_header_id
929     and   amount > 0;
930 
931   debit_rec                debit_cur%ROWTYPE;
932   ln_random_percentage     NUMBER;
933   ln_num_rct_req_receipts  NUMBER;
934   ln_num_just_req_receipts NUMBER;
935   lb_ignore                BOOLEAN := FALSE;
936 BEGIN
937   p_audit_report := FALSE;
938 
939   IF p_random_audit_percentage = 0 THEN
940     null;
941   ELSE
942     IF NVL(p_ignore_credit_only_flag, 'N') = 'Y' THEN
943 
944       OPEN debit_cur;
945       FETCH debit_cur INTO debit_rec;
946       CLOSE debit_cur;
947 
948       IF (debit_rec.debit_line_count = 0) THEN
949         lb_ignore := TRUE;
950       END IF;
951     END IF;
952 
953     IF lb_ignore = false AND NVL(p_ignore_rj_not_req_only_flag, 'N') = 'Y' THEN
954 
955       IF (NOT AP_WEB_DB_EXPLINE_PKG.GetNumReceiptRequiredLines(p_report_header_id, ln_num_rct_req_receipts)) THEN
956 	ln_num_rct_req_receipts := 0;
957       END IF;
958 
959       IF (NOT AP_WEB_DB_EXPLINE_PKG.GetNumJustReqdLines(p_report_header_id, ln_num_just_req_receipts)) THEN
960 	ln_num_just_req_receipts := 0;
961       END IF;
962 
963       IF (     ln_num_rct_req_receipts = 0
964           AND ln_num_just_req_receipts = 0) THEN
965         lb_ignore := TRUE;
966       END IF;
967     END IF;
968 
969     IF     p_random_audit_percentage = 100
970        AND lb_ignore = FALSE THEN
971 
972       insert_audit_reason(p_report_header_id, 'RANDOM');
973       p_audit_report := TRUE;
974 
975     ELSIF lb_ignore = FALSE THEN
976 
977       ln_random_percentage := AP_WEB_AUDIT_PROCESS.get_random_percentage();
978 
979       IF ln_random_percentage < p_random_audit_percentage THEN
980          insert_audit_reason(p_report_header_id, 'RANDOM');
981          p_audit_report := TRUE;
982       END IF;
983 
984     END IF;
985   END IF;
986 END process_random_audit;
987 
988 /*========================================================================
989  | PRIVATE PROCEDURE process_custom_audit
990  |
991  | DESCRIPTION
992  |   This procedure provides customization hook to audit expense reports.
993  |
994  | CALLED FROM PROCEDURES/FUNCTIONS (local to this package body)
995  |   Called from BC4J.
996  |
997  | CALLS PROCEDURES/FUNCTIONS (local to this package body)
998  |
999  | RETURNS
1000  |
1001  | PARAMETERS
1002  |   p_report_header_id            IN  Expense Report identifier
1003  |   p_audit_report                OUT NOCOPY TRUE if report needs to be audited
1004  |   p_override_default_processing OUT NOCOPY TRUE if default audit logic is overridden
1005  |
1006  | MODIFICATION HISTORY
1007  | Date                  Author            Description of Changes
1008  | 13-Oct-2002           J Rautiainen      Created
1009  |
1010  *=======================================================================*/
1011 PROCEDURE process_custom_audit(p_report_header_id            IN  NUMBER,
1012                                p_audit_report                OUT NOCOPY BOOLEAN,
1013                                p_override_default_processing OUT NOCOPY BOOLEAN) IS
1014 
1015   p_audit_reason_code           VARCHAR2(30) := null;
1016 BEGIN
1017   p_audit_report := FALSE;
1018 
1019   AP_WEB_AUDIT_HOOK.audit_expense_report(p_report_header_id,
1020                                          p_audit_reason_code,
1021                                          p_audit_report,
1022                                          p_override_default_processing);
1023 
1024   IF (p_audit_report = TRUE AND p_audit_reason_code IS NOT NULL) THEN
1025     insert_audit_reason(p_report_header_id, p_audit_reason_code);
1026   END IF;
1027 
1028 END process_custom_audit;
1029 
1030 /*========================================================================
1031  | PRIVATE PROCEDURE update_audit_code
1032  |
1033  | DESCRIPTION
1034  |   This procedure update expense report header with the audit code.
1035  |
1036  | CALLED FROM PROCEDURES/FUNCTIONS (local to this package body)
1037  |   Called from BC4J.
1038  |
1039  | CALLS PROCEDURES/FUNCTIONS (local to this package body)
1040  |
1041  | RETURNS
1042  |
1043  | PARAMETERS
1044  |   p_report_header_id IN  Expense Report identifier
1045  |   p_audit_code       IN  Audit code, one of the following:
1046  |                            AUTO_APPROVE
1047  |                            PAPERLESS_AUDIT
1048  |                            AUDIT
1049  |
1050  | MODIFICATION HISTORY
1051  | Date                  Author            Description of Changes
1052  | 13-Oct-2002           J Rautiainen      Created
1053  |
1054  *=======================================================================*/
1055 PROCEDURE update_audit_code(p_report_header_id IN NUMBER,
1056                             p_audit_code       IN VARCHAR2) IS
1057 
1058 BEGIN
1059 
1060   IF (    p_report_header_id IS NOT NULL
1061       AND p_audit_code IS NOT NULL) THEN
1062 
1063     UPDATE ap_expense_report_headers_all erh
1064     SET    audit_code = p_audit_code
1065     WHERE  report_header_id = p_report_header_id;
1066   END IF;
1067 
1068 EXCEPTION
1069   WHEN OTHERS THEN
1070     null;
1071 
1072 END update_audit_code;
1073 
1074 /*========================================================================
1075  | PRIVATE PROCEDURE process_paperless_audit
1076  |
1077  | DESCRIPTION
1078  |   This procedure processes expense report paperless audit.
1079  |
1080  | CALLED FROM PROCEDURES/FUNCTIONS (local to this package body)
1081  |   Called from BC4J.
1082  |
1083  | CALLS PROCEDURES/FUNCTIONS (local to this package body)
1084  |
1085  | RETURNS
1086  |
1087  | PARAMETERS
1088  |   p_report_header_id IN  Expense Report identifier
1089  |
1090  | MODIFICATION HISTORY
1091  | Date                  Author            Description of Changes
1092  | 13-Oct-2002           J Rautiainen      Created
1093  |
1094  *=======================================================================*/
1095 PROCEDURE process_paperless_audit(p_report_header_id          IN  NUMBER,
1096                                   p_pl_audit_all_flag         IN  VARCHAR2,
1097                                   p_pl_audit_cc_only_flag     IN  VARCHAR2,
1098                                   p_pl_audit_violation_flag   IN  VARCHAR2,
1099                                   p_pl_audit_pdm_only_flag    IN  VARCHAR2,
1100                                   p_assign_auditor_stage_code IN  VARCHAR2,
1101                                   p_audit_report              OUT NOCOPY BOOLEAN) IS
1102 
1103   CURSOR cc_cur IS
1104     select count(1) non_cc_line_count
1105     from ap_expense_report_lines_all aerl
1106     where aerl.report_header_id = p_report_header_id
1107     and   (     CREDIT_CARD_TRX_ID is null
1108            OR (     CREDIT_CARD_TRX_ID is not null
1109                 AND (NVL(receipt_required_flag,'N') = 'Y' OR NVL(image_receipt_required_flag,'N') = 'Y')
1110               )
1111           );
1112 
1113   CURSOR pdm_cur IS
1114     select count(1) non_pdm_line_count
1115     from ap_expense_report_lines_all aerl
1116     where aerl.report_header_id = p_report_header_id
1117     and   NVL(aerl.category_code,'NONE') not in ('PER_DIEM','MILEAGE');
1118 
1119   CURSOR rr_cur IS
1120     select count(1) rr_line_count
1121     from ap_expense_report_lines_all aerl
1122     where aerl.report_header_id = p_report_header_id
1123     and   (nvl(aerl.receipt_required_flag, 'N') = 'Y' OR  nvl(aerl.image_receipt_required_flag, 'N') = 'Y');
1124 
1125   pdm_rec                pdm_cur%ROWTYPE;
1126   cc_rec                 cc_cur%ROWTYPE;
1127   rr_rec                 rr_cur%ROWTYPE;
1128   paperless_audit        BOOLEAN := FALSE;
1129   cc_flag		 BOOLEAN := FALSE;
1130   viol_flag		 BOOLEAN := FALSE;
1131   rec_flag		 BOOLEAN := FALSE;
1132 
1133 BEGIN
1134   p_audit_report := FALSE;
1135   IF (p_pl_audit_cc_only_flag = 'Y') THEN
1136 
1137     OPEN cc_cur;
1138     FETCH cc_cur INTO cc_rec;
1139     CLOSE cc_cur;
1140 
1141     IF (cc_rec.non_cc_line_count = 0) THEN
1142       paperless_audit := TRUE;
1143       cc_flag := TRUE;
1144     END IF;
1145   END IF;
1146 
1147   IF (paperless_audit = FALSE AND p_pl_audit_violation_flag = 'Y') THEN
1148 
1149     IF (get_report_violation_count(p_report_header_id) > 0) THEN
1150       paperless_audit := TRUE;
1151       viol_flag := TRUE;
1152     END IF;
1153 
1154   END IF;
1155 
1156   IF (paperless_audit = FALSE AND p_pl_audit_pdm_only_flag = 'Y') THEN
1157 
1158     OPEN pdm_cur;
1159     FETCH pdm_cur INTO pdm_rec;
1160     CLOSE pdm_cur;
1161 
1162     IF (pdm_rec.non_pdm_line_count = 0) THEN
1163       paperless_audit := TRUE;
1164       rec_flag := TRUE;
1165     ELSE
1166       OPEN rr_cur;
1167       FETCH rr_cur INTO rr_rec;
1168       CLOSE rr_cur;
1169 
1170       IF (rr_rec.rr_line_count = 0) THEN
1171         paperless_audit := TRUE;
1172         rec_flag := TRUE;
1173       END IF;
1174     END IF;
1175 
1176   END IF;
1177 
1178   IF (paperless_audit = FALSE) THEN
1179     OPEN rr_cur;
1180     FETCH rr_cur INTO rr_rec;
1181     CLOSE rr_cur;
1182 
1183     IF (rr_rec.rr_line_count = 0) THEN
1184       paperless_audit := TRUE;
1185       rec_flag := TRUE;
1186     END IF;
1187   END IF;
1188 
1189   IF (paperless_audit = TRUE AND (p_pl_audit_all_flag = 'Y'
1190        OR (p_pl_audit_cc_only_flag = 'Y' AND cc_flag = TRUE)
1191        OR (p_pl_audit_violation_flag = 'Y' AND viol_flag = TRUE)
1192        OR (p_pl_audit_pdm_only_flag='Y' AND rec_flag = TRUE))) THEN
1193     IF (p_assign_auditor_stage_code = 'SUBMISSION') THEN
1194       AP_WEB_AUDIT_QUEUE_UTILS.enqueue_for_audit(p_report_header_id);
1195     END IF;
1196 
1197     p_audit_report := TRUE;
1198   END IF;
1199 
1200 END process_paperless_audit;
1201 
1202 /*========================================================================
1203  | PRIVATE PROCEDURE process_audit_list
1204  |
1205  | DESCRIPTION
1206  |   This procedure adds user to automatic audit list if needed.
1207  |
1208  | CALLED FROM PROCEDURES/FUNCTIONS (local to this package body)
1209  |   Called from BC4J.
1210  |
1211  | CALLS PROCEDURES/FUNCTIONS (local to this package body)
1212  |
1213  | RETURNS
1214  |
1215  | PARAMETERS
1216  |   p_report_header_id IN  Expense Report identifier
1217  |
1218  | MODIFICATION HISTORY
1219  | Date                  Author            Description of Changes
1220  | 13-Oct-2002           J Rautiainen      Created
1221  | 11-Mar-2005           Maulik Vadera     Bug 4192680: Added extra condition
1222  |                                         to not include both pay personal credit
1223  |                                         card reports in the calculation of
1224  |                                         expense_report_count
1225  *=======================================================================*/
1226 PROCEDURE process_audit_list(p_report_header_id IN NUMBER) IS
1227   CURSOR list_cur IS
1228     select rs.receipt_delay_rule_flag,
1229            rs.receipt_delay_days,
1230            rs.monthly_total_rule_flag,
1231            rs.monthly_total_allowed,
1232            rs.monthly_violations_rule_flag,
1233            rs.monthly_violations_allowed,
1234            rs.monthly_reports_rule_flag,
1235            rs.monthly_reports_allowed,
1236            rs.audit_term_duration_days,
1237            aerh.employee_id,
1238            rs.rule_set_name,
1239            aerh.org_id,
1240            rs.rule_set_type,
1241            rs.start_date,
1242            rs.end_date,
1243            rs.rule_set_id,
1244            aerh.default_currency_code,
1245            aerh.default_exchange_rate_type,
1246            aerh.week_end_date
1247     from AP_EXPENSE_REPORT_HEADERS_ALL aerh,
1248          AP_AUD_RULE_SETS rs,
1249          AP_AUD_RULE_ASSIGNMENTS_ALL rsa
1250     where aerh.report_header_id = p_report_header_id
1251     and   aerh.org_id = rsa.org_id
1252     and   rsa.rule_set_id = rs.rule_set_id
1253     and   rs.rule_set_type = 'AUDIT_LIST'
1254     and   TRUNC(SYSDATE)
1255             BETWEEN TRUNC(NVL(rsa.START_DATE,SYSDATE))
1256             AND     TRUNC(NVL(rsa.END_DATE,SYSDATE));
1257 
1258   --Bug 4192680: Changed the cursor definition to exclude thee both pay personal credit
1259   --card Report from report count.
1260   CURSOR reports_cur(p_employee_id IN NUMBER, p_org_id IN NUMBER, p_ex_rate IN NUMBER) IS
1261     select sum(NVL(aerh.total,0)*NVL(aerh.default_exchange_rate,p_ex_rate)) expense_report_total,
1262            count(aerh.expense_report_id) expense_report_count
1263     from AP_EXPENSE_REPORT_HEADERS_ALL aerh
1264     where employee_id = p_employee_id
1265     and aerh.org_id = p_org_id
1266     and aerh.report_submitted_date > add_months(sysdate,-1)
1267     and (   aerh.source in ('WebExpense', 'SelfService')
1268          or aerh.report_header_id = p_report_header_id)
1269     and exists(select 'Y'
1270 	       from AP_EXPENSE_REPORT_LINES_ALL aerl
1271                where aerh.report_header_id = aerl.report_header_id);
1272 
1273 
1274   list_rec    list_cur%ROWTYPE;
1275   reports_rec reports_cur%ROWTYPE;
1276   lb_added    boolean := false;
1277   l_base_currency_code          AP_WEB_DB_AP_INT_PKG.apSetUp_baseCurrencyCode;
1278   l_ex_rate   NUMBER := 1;
1279 
1280 BEGIN
1281   OPEN list_cur;
1282   FETCH list_cur INTO list_rec;
1283 
1284   IF list_cur%FOUND THEN
1285 
1286     BEGIN
1287       SELECT base_currency_code INTO l_base_currency_code
1288       FROM ap_system_parameters_all
1289       WHERE org_id = list_rec.org_id;
1290       l_ex_rate :=  AP_UTILITIES_PKG.get_exchange_rate(
1291                                         list_rec.default_currency_code,
1292                                         l_base_currency_code,
1293                                         list_rec.default_exchange_rate_type,
1294                                         list_rec.week_end_date,
1295                                         'ProcessAuditList');
1296     EXCEPTION
1297       WHEN OTHERS THEN
1298        l_ex_rate := 1;
1299     END;
1300     OPEN reports_cur(list_rec.employee_id, list_rec.org_id, l_ex_rate);
1301     FETCH reports_cur INTO reports_rec;
1302     CLOSE reports_cur;
1303 
1304     IF NVL(list_rec.monthly_total_rule_flag, 'N') = 'Y' AND lb_added = false THEN
1305 
1306       IF list_rec.monthly_total_allowed < reports_rec.expense_report_total THEN
1307         add_to_audit_list(list_rec.employee_id, list_rec.audit_term_duration_days, 'EXPENSE_TOTAL');
1308         lb_added := true;
1309       END IF;
1310     END IF;
1311 
1312     IF NVL(list_rec.monthly_violations_rule_flag, 'N') = 'Y' AND lb_added = false THEN
1313 
1314       IF list_rec.monthly_violations_allowed < get_employee_violation_count(list_rec.employee_id, 1) THEN
1315         add_to_audit_list(list_rec.employee_id, list_rec.audit_term_duration_days, 'POLICY_VIOLATION');
1316         lb_added := true;
1317       END IF;
1318     END IF;
1319 
1320     IF NVL(list_rec.monthly_reports_rule_flag, 'N') = 'Y' AND lb_added = false THEN
1321       IF list_rec.monthly_reports_allowed < reports_rec.expense_report_count THEN
1322         add_to_audit_list(list_rec.employee_id, list_rec.audit_term_duration_days, 'EXPENSE_COUNT');
1323         lb_added := true;
1324       END IF;
1325     END IF;
1326   END IF; -- list_cur FOUND
1327 
1328   CLOSE list_cur;
1329 
1330 END process_audit_list;
1331 
1332 /*========================================================================
1333  | PUBLIC PROCEDURE add_to_audit_list
1334  |
1335  | DESCRIPTION
1336  |   This procedure inserts given employee to audit list.
1337  |
1338  | CALLED FROM PROCEDURES/FUNCTIONS (local to this package body)
1339  |   Called from BC4J.
1340  |
1341  | CALLS PROCEDURES/FUNCTIONS (local to this package body)
1342  |
1343  | RETURNS
1344  |
1345  | PARAMETERS
1346  |   p_employee_id IN  Employee identifier
1347  |   p_reason_code IN  Reason code
1348  |
1349  | MODIFICATION HISTORY
1350  | Date                  Author            Description of Changes
1351  | 13-Oct-2002           J Rautiainen      Created
1352  |
1353  *=======================================================================*/
1354 PROCEDURE add_to_audit_list(p_employee_id  IN NUMBER,
1355                             p_duration     IN NUMBER,
1356                             p_reason_code  IN VARCHAR2) IS
1357 PRAGMA AUTONOMOUS_TRANSACTION;
1358 
1359   CURSOR audit_cur IS
1360     SELECT auto_audit_id,
1361            employee_id,
1362            audit_reason_code,
1363            start_date,
1364            end_date
1365     FROM ap_aud_auto_audits
1366     WHERE employee_id = p_employee_id
1367     AND   trunc(sysdate) between trunc(start_date) and trunc(NVL(end_date, sysdate))
1368     order by end_date desc;
1369 
1370   audit_rec     audit_cur%ROWTYPE;
1371   record_exists boolean := false;
1372   open_dated    boolean := false;
1373   create_record boolean := true;
1374   ld_start_date DATE;
1375   ld_end_date DATE;
1376 BEGIN
1377   IF (p_employee_id IS NOT NULL AND p_reason_code IS NOT NULL) THEN
1378     OPEN audit_cur;
1379     FETCH audit_cur INTO audit_rec;
1380 
1381     IF audit_cur%FOUND THEN
1382       record_exists := true;
1383 
1384       ld_start_date := audit_rec.start_date;
1385       ld_end_date   := SYSDATE-1;
1386       IF ld_start_date > ld_end_date THEN
1387         ld_start_date := ld_end_date;
1388       END IF;
1389 
1390       IF audit_rec.end_date is null THEN
1391         open_dated := true;
1392       END IF;
1393     END IF;
1394 
1395     CLOSE audit_cur;
1396 
1397     IF record_exists = true THEN
1398       IF (    audit_rec.audit_reason_code = 'TERMINATION'
1399            OR audit_rec.audit_reason_code = 'LEAVE_OF_ABSENCE'
1400            OR open_dated = true
1401          ) THEN
1402         create_record := false;
1403       ELSE
1404         UPDATE AP_AUD_AUTO_AUDITS
1405         SET END_DATE = ld_end_date, START_DATE = ld_start_date
1406         WHERE AUTO_AUDIT_ID = audit_rec.auto_audit_id;
1407       END IF;
1408     END IF; -- record_exists = true
1409 
1410     IF create_record = true THEN
1411       INSERT INTO AP_AUD_AUTO_AUDITS(
1412         AUTO_AUDIT_ID,
1413         EMPLOYEE_ID,
1414         AUDIT_REASON_CODE,
1415         START_DATE,
1416         END_DATE,
1417         CREATION_DATE,
1418         CREATED_BY,
1419         LAST_UPDATE_LOGIN,
1420         LAST_UPDATE_DATE,
1421         LAST_UPDATED_BY)
1422       VALUES (
1423         AP_AUD_AUTO_AUDITS_S.nextval,
1424         p_employee_id,
1425         p_reason_code,
1426         SYSDATE,
1427         DECODE(p_duration,
1428                null, null,
1429                SYSDATE+p_duration),
1430         SYSDATE,
1431         nvl(fnd_global.user_id, -1),
1432         fnd_global.conc_login_id,
1433         SYSDATE,
1434         nvl(fnd_global.user_id, -1));
1435     END IF; --create_record = true
1436 
1437     commit;
1438   END IF;
1439 
1440 END add_to_audit_list;
1441 
1442 /*========================================================================
1443  | PRIVATE PROCEDURE insert_audit_reason
1444  |
1445  | DESCRIPTION
1446  |   This procedure inserts given audit reason code for a expense report.
1447  |
1448  |   Changes to this procedure may require changes to update_audit_reason
1449  |
1450  | CALLED FROM PROCEDURES/FUNCTIONS (local to this package body)
1451  |   Called from BC4J.
1452  |
1453  | CALLS PROCEDURES/FUNCTIONS (local to this package body)
1454  |
1455  | RETURNS
1456  |
1457  | PARAMETERS
1458  |   p_report_header_id IN  Expense Report identifier
1459  |   p_audit_reson_code IN  Audit reason code
1460  |
1461  | MODIFICATION HISTORY
1462  | Date                  Author            Description of Changes
1463  | 13-Oct-2002           J Rautiainen      Created
1464  |
1465  *=======================================================================*/
1466 PROCEDURE insert_audit_reason(p_report_header_id  IN NUMBER,
1467                               p_audit_reason_code IN VARCHAR2) IS
1468 --PRAGMA AUTONOMOUS_TRANSACTION;
1469 
1470 BEGIN
1471   IF (p_report_header_id IS NOT NULL AND p_audit_reason_code IS NOT NULL) THEN
1472     INSERT INTO AP_AUD_AUDIT_REASONS(
1473       AUDIT_REASON_ID,
1474       REPORT_HEADER_ID,
1475       AUDIT_REASON_CODE,
1476       CREATION_DATE,
1477       CREATED_BY,
1478       LAST_UPDATE_LOGIN,
1479       LAST_UPDATE_DATE,
1480       LAST_UPDATED_BY)
1481     VALUES (
1482       AP_AUD_AUDIT_REASONS_S.nextval,
1483       p_report_header_id,
1484       p_audit_reason_code,
1485       SYSDATE,
1486       nvl(fnd_global.user_id, -1),
1487       fnd_global.conc_login_id,
1488       SYSDATE,
1489       nvl(fnd_global.user_id, -1));
1490     commit;
1491   END IF;
1492 
1493 END insert_audit_reason;
1494 
1495 /*========================================================================
1496  | PRIVATE PROCEDURE update_audit_reason
1497  |
1498  | DESCRIPTION
1499  |   This procedure updates the given audit reason code entry
1500  |   in AP_AUD_AUDIT_REASONS table for an expense report .
1501  |
1502  |   Changes to this procedure may require changes to insert_audit_reason
1503  |
1504  | CALLED FROM PROCEDURES/FUNCTIONS (local to this package body)
1505  |   Called from BC4J.
1506  |
1507  | CALLS PROCEDURES/FUNCTIONS (local to this package body)
1508  |
1509  | RETURNS
1510  |
1511  | PARAMETERS
1512  |   p_report_header_id IN  Expense Report identifier
1513  |   p_audit_reson_code IN  Audit reason code
1514  |
1515  | MODIFICATION HISTORY
1516  | Date                  Author            Description of Changes
1517  | 01-May-2008           STALASIL          Created
1518  |
1519  *=======================================================================*/
1520 PROCEDURE update_audit_reason(p_report_header_id  IN NUMBER,
1521                               p_audit_reason_code IN VARCHAR2) IS
1522 
1523 BEGIN
1524 
1525   IF (p_report_header_id IS NOT NULL AND p_audit_reason_code IS NOT NULL) THEN
1526     UPDATE AP_AUD_AUDIT_REASONS
1527     SET LAST_UPDATE_LOGIN = fnd_global.conc_login_id,
1528         LAST_UPDATE_DATE  = SYSDATE,
1529         LAST_UPDATED_BY   = nvl(fnd_global.user_id, -1)
1530     WHERE report_header_id = p_report_header_id
1531     AND   AUDIT_REASON_CODE = p_audit_reason_code ;
1532     commit;
1533   END IF;
1534 
1535 END update_audit_reason;
1536 
1537 /*========================================================================
1538  | PUBLIC function get_random_percentage
1539  |
1540  | DESCRIPTION
1541  |      Returns a random 2 digit percentage used to decide whether
1542  |      expense report is going to be randomly picked
1543  |
1544  | PSEUDO CODE/LOGIC
1545  |
1546  | PARAMETERS
1547  |
1548  | RETURNS
1549  |   NUMBER 2 digit number between 0-99
1550  | KNOWN ISSUES
1551  |
1552  | NOTES
1553  |
1554  | MODIFICATION HISTORY
1555  | Date                  Author            Description of Changes
1556  | 13-Oct-2002           J Rautiainen      Created
1557  *=======================================================================*/
1558 FUNCTION get_random_percentage RETURN NUMBER IS
1559 
1560  ln_random_number  NUMBER;
1561  lv_percentage     NUMBER;
1562 
1563 BEGIN
1564 
1565  /*------------------------+
1566   | Get the random number  |
1567   +------------------------*/
1568   ln_random_number  := FND_CRYPTO.RANDOMNUMBER;
1569 
1570 
1571  /*-------------------------------------------------------------+
1572   | Construct the random percentage based on the random number. |
1573   +-------------------------------------------------------------*/
1574   lv_percentage := construct_random_percentage(ln_random_number);
1575 
1576   return lv_percentage;
1577 
1578 END get_random_percentage;
1579 
1580 /*========================================================================
1581  | PUBLIC function construct_random_percentage
1582  |
1583  | DESCRIPTION
1584  |      Creates a 2 digit random percentage from a random number.
1585  |
1586  | PSEUDO CODE/LOGIC
1587  |
1588  | PARAMETERS
1589  |   pn_random_number        random integer
1590  |
1591  | RETURNS
1592  |   NUMBER 2 digit random percentage
1593  | KNOWN ISSUES
1594  |
1595  | NOTES
1596  |
1597  | MODIFICATION HISTORY
1598  | Date                  Author            Description of Changes
1599  | 14-Oct-2002           J Rautiainen      Created
1600  *=======================================================================*/
1601 FUNCTION construct_random_percentage(pn_random_number NUMBER) RETURN NUMBER IS
1602 
1603  /*-----------------------------------------------------------+
1604   | Array containing digits 0-9. This is  used to map the     |
1605   | random number into percentafe digits                      |
1606   +-----------------------------------------------------------*/
1607   TYPE t_number IS VARRAY(10) OF VARCHAR2(1);
1608   v_numberList     t_number := t_number('1','2','3','4','5','6','7','8','9','0');
1609 
1610   lv_result        VARCHAR2(100) := '';
1611   lv_temp          VARCHAR2(100) := '';
1612   lv_random_number VARCHAR2(100);
1613 
1614 BEGIN
1615 
1616  /*------------------------------------------------------------+
1617   | Convert random number in to a string, we use the string to |
1618   | process the random number 2 characters at time.            |
1619   +------------------------------------------------------------*/
1620   lv_random_number := to_char(abs(pn_random_number));
1621 
1622  /*-----------------------------------------------------------+
1623   | Loop twice to get the 2 digits for the random percentage. |
1624   +-----------------------------------------------------------*/
1625 
1626   FOR i IN 1..2 LOOP
1627 
1628    /*--------------------------------------------------------+
1629     | Take 2 character block from the remaining random number|
1630     +--------------------------------------------------------*/
1631     lv_temp          := SUBSTR(lv_random_number,1,2);
1632 
1633    /*--------------------------------------------------------------+
1634     | Module 10 is used to get the index for the entry in          |
1635     | the array. Without this we would get array index out nocopy of      |
1636     | bounds error. 1 is added to deal with the fact that the      |
1637     | array has indexes from 1 to 10 NOT 0 to 9.                   |
1638     +--------------------------------------------------------------*/
1639     lv_result      := lv_result || v_numberList(mod(to_number(lv_temp),10)+1);
1640 
1641    /*---------------------------------------------------------------+
1642     | Remove the processed 2 character block from the random number |
1643     +---------------------------------------------------------------*/
1644     lv_random_number := SUBSTR(lv_random_number,3,length(lv_random_number));
1645 
1646   END LOOP;
1647 
1648  /*-----------------------------------+
1649   | Return the constructed percentage |
1650   +-----------------------------------*/
1651   return to_number(lv_result);
1652 
1653 END construct_random_percentage;
1654 
1655 /*========================================================================
1656  | PRIVATE FUNCTION get_report_violation_count
1657  |
1658  | DESCRIPTION
1659  |   This function returns the number of policy violation for a given expense report.
1660  |
1661  | CALLED FROM PROCEDURES/FUNCTIONS (local to this package body)
1662  |   Called from BC4J.
1663  |
1664  | CALLS PROCEDURES/FUNCTIONS (local to this package body)
1665  |
1666  | RETURNS
1667  |   Count of violations on a given expense report
1668  |
1669  | PARAMETERS
1670  |   p_report_header_id IN  Expense Report identifier
1671  |
1672  | MODIFICATION HISTORY
1673  | Date                  Author            Description of Changes
1674  | 13-Oct-2002           J Rautiainen      Created
1675  |
1676  *=======================================================================*/
1677 FUNCTION get_report_violation_count(p_report_header_id IN  NUMBER) RETURN NUMBER IS
1678 
1679   CURSOR violation_cur IS
1680     select count(1) violation_count
1681     from AP_POL_VIOLATIONS_ALL
1682     where report_header_id = p_report_header_id;
1683 
1684   violation_rec violation_cur%ROWTYPE;
1685 
1686 BEGIN
1687   OPEN violation_cur;
1688   FETCH violation_cur INTO violation_rec;
1689   CLOSE violation_cur;
1690 
1691   RETURN NVL(violation_rec.violation_count,0);
1692 
1693 END get_report_violation_count;
1694 
1695 /*========================================================================
1696  | PRIVATE FUNCTION get_report_violation_count
1697  |
1698  | DESCRIPTION
1699  |   This function returns the number of policy violation for a given employee
1700  |   during last given months.
1701  |
1702  | CALLED FROM PROCEDURES/FUNCTIONS (local to this package body)
1703  |   Called from BC4J.
1704  |
1705  | CALLS PROCEDURES/FUNCTIONS (local to this package body)
1706  |
1707  | RETURNS
1708  |   Count of violations for a given employee
1709  |
1710  | PARAMETERS
1711  |   p_report_header_id IN  Expense Report identifier
1712  |   p_months           IN  Time in months for which reports are examined
1713  |
1714  | MODIFICATION HISTORY
1715  | Date                  Author            Description of Changes
1716  | 13-Oct-2002           J Rautiainen      Created
1717  |
1718  *=======================================================================*/
1719 FUNCTION get_employee_violation_count(p_employee_id IN  NUMBER,
1720                                       p_months      IN  NUMBER) RETURN NUMBER IS
1721 
1722   CURSOR violation_cur IS
1723     select count(1) violation_count
1724     from AP_POL_VIOLATIONS_ALL viol,
1725          AP_EXPENSE_REPORT_HEADERS_ALL aerh
1726     where aerh.employee_id      = p_employee_id
1727     and   viol.report_header_id = aerh.report_header_id
1728     and   aerh.week_end_date > add_months(sysdate,-p_months);
1729 
1730   violation_rec violation_cur%ROWTYPE;
1731 
1732 BEGIN
1733   OPEN violation_cur;
1734   FETCH violation_cur INTO violation_rec;
1735   CLOSE violation_cur;
1736 
1737   RETURN NVL(violation_rec.violation_count,0);
1738 
1739 END get_employee_violation_count;
1740 
1741 /**
1742  * jrautiai ADJ Fix end
1743  */
1744 
1745 /*========================================================================
1746  | PUBLIC PROCEDURE process_audit_actions
1747  |
1748  | DESCRIPTION
1749  |   This procedure deals with auditor adjustments. This logic is called
1750  |   when audit is completed and it deals with adjustments in reimbursable
1751  |   amount and shortpayments.
1752  |
1753  | CALLED FROM PROCEDURES/FUNCTIONS (local to this package body)
1754  |   Called from expense report form and HTML UI when auditor
1755  |   completes audit.
1756  |
1757  | CALLS PROCEDURES/FUNCTIONS (local to this package body)
1758  |
1759  | RETURNS
1760  |   None
1761  |
1762  | PARAMETERS
1763  |   p_report_header_id       IN  Expense report to processed
1764  |
1765  | MODIFICATION HISTORY
1766  | Date                  Author            Description of Changes
1767  | 15-Jul-2003           J Rautiainen      Created
1768  |
1769  *=======================================================================*/
1770 PROCEDURE process_audit_actions(p_report_header_id IN  NUMBER) IS
1771 
1772   CURSOR report_lines_c IS
1773     SELECT AERL.*
1774     FROM AP_EXPENSE_REPORT_LINES_ALL AERL
1775     WHERE REPORT_HEADER_ID = p_report_header_id
1776       AND (itemization_parent_id is null OR itemization_parent_id <> -1)
1777     FOR UPDATE OF REPORT_HEADER_ID NOWAIT;
1778 
1779   report_lines_rec                report_lines_c%ROWTYPE;
1780 
1781   ln_next_itemization_id          NUMBER;
1782   ln_personal_expense_id          NUMBER;
1783   l_payment_due                   VARCHAR2(10);
1784 
1785 BEGIN
1786 
1787   OPEN report_lines_c;
1788 
1789   LOOP
1790     FETCH report_lines_c into report_lines_rec;
1791     EXIT WHEN report_lines_c%NOTFOUND;
1792 
1793    /**
1794     * Check whether a line was adjusted
1795     */
1796     IF report_lines_rec.AMOUNT <> NVL(report_lines_rec.SUBMITTED_AMOUNT, report_lines_rec.AMOUNT) THEN
1797 
1798       /**
1799       * Line was adjusted, Update the CC transaction with the adjustment for credit card line
1800       */
1801       IF report_lines_rec.CREDIT_CARD_TRX_ID IS NOT NULL THEN
1802          update_cc_transaction(report_lines_rec);
1803       END IF; -- report_lines_rec.CREDIT_CARD_TRX_ID is null
1804 
1805     END IF; -- if line was adjusted
1806 
1807   END LOOP;
1808 
1809   CLOSE report_lines_c;
1810 
1811 EXCEPTION
1812   WHEN OTHERS THEN
1813     AP_WEB_DB_UTIL_PKG.RaiseException('process_audit_actions');
1814     APP_EXCEPTION.RAISE_EXCEPTION;
1815 END process_audit_actions;
1816 
1817 /*========================================================================
1818  | PUBLIC PROCEDURE update_cc_transaction
1819  |
1820  | DESCRIPTION
1821  |   This procedure updates the CC transaction amounts to match the
1822  |   amounts on the expense line.
1823  |
1824  | CALLED FROM PROCEDURES/FUNCTIONS (local to this package body)
1825  |   process_audit_actions
1826  |
1827  | CALLS PROCEDURES/FUNCTIONS (local to this package body)
1828  |
1829  | RETURNS
1830  |   None
1831  | PARAMETERS
1832  |   Expense line record containing the data on the modified expense line
1833  |
1834  | MODIFICATION HISTORY
1835  | Date                  Author            Description of Changes
1836  | 21-Jul-2003           J Rautiainen      Created
1837  |
1838  *=======================================================================*/
1839 PROCEDURE update_cc_transaction(expense_line_rec IN AP_EXPENSE_REPORT_LINES_ALL%ROWTYPE) IS
1840 
1841   CURSOR trx_c(p_trx_id IN NUMBER) IS
1842     SELECT cct.*
1843     FROM   AP_CREDIT_CARD_TRXNS_ALL cct
1844     WHERE  cct.trx_id = p_trx_id
1845     FOR UPDATE OF TRX_ID NOWAIT;
1846 
1847   CURSOR total_c(p_report_header_id IN NUMBER, p_trx_id IN NUMBER, p_personal_expense_id IN NUMBER) IS
1848     SELECT sum(amount) total_amount
1849     FROM   AP_EXPENSE_REPORT_LINES_ALL
1850     WHERE  report_header_id = p_report_header_id
1851     AND    web_parameter_id <> p_personal_expense_id
1852     AND    credit_card_trx_id = p_trx_id
1853     AND (itemization_parent_id is null OR itemization_parent_id <> -1);
1854 
1855   trx_rec                trx_c%ROWTYPE;
1856   total_rec              total_c%ROWTYPE;
1857   ln_personal_expense_id NUMBER;
1858 
1859 BEGIN
1860   IF expense_line_rec.credit_card_trx_id IS NOT NULL THEN
1861 
1862     ln_personal_expense_id := AP_WEB_AUDIT_UTILS.get_personal_expense_id;
1863 
1864     OPEN total_c(expense_line_rec.report_header_id, expense_line_rec.credit_card_trx_id, ln_personal_expense_id);
1865     FETCH total_c into total_rec;
1866     CLOSE total_c;
1867 
1868     OPEN trx_c(expense_line_rec.credit_card_trx_id);
1869     FETCH trx_c into trx_rec;
1870 
1871     UPDATE AP_CREDIT_CARD_TRXNS_ALL
1872     SET    expensed_amount = total_rec.total_amount
1873     WHERE CURRENT OF trx_c;
1874 
1875     CLOSE trx_c;
1876 
1877      IF (total_rec.total_amount=0) THEN        -- Bug 6628290 (sodash) when the Expensed Amount is zero, set the category as personal for the Credit Card Trxn.
1878 
1879        UPDATE  AP_CREDIT_CARD_TRXNS_ALL
1880        SET        category = 'PERSONAL'
1881        WHERE   trx_id = expense_line_rec.credit_card_trx_id;
1882 
1883      END IF;
1884 
1885 
1886   END IF;
1887 END update_cc_transaction;
1888 
1889 
1890 /*========================================================================
1891  | PUBLIC PROCEDURE process_shortpays
1892  |
1893  | DESCRIPTION
1894  |   This procedure processes shortpayments on a line, namely if one of
1895  |   itemized lines is shortpaid, then all the itemized lines are
1896  |   shortpaid as well.
1897  |
1898  | CALLED FROM PROCEDURES/FUNCTIONS (local to this package body)
1899  |   process_audit_actions
1900  |
1901  | CALLS PROCEDURES/FUNCTIONS (local to this package body)
1902  |
1903  | RETURNS
1904  |   None
1905  | PARAMETERS
1906  |   Expense line record containing the data on the modified expense line
1907  |
1908  | MODIFICATION HISTORY
1909  | Date                  Author            Description of Changes
1910  | 21-Jul-2003           J Rautiainen      Created
1911  |
1912  *=======================================================================*/
1913 PROCEDURE process_shortpays(expense_line_rec IN AP_EXPENSE_REPORT_LINES_ALL%ROWTYPE) IS
1914 BEGIN
1915   IF (expense_line_rec.report_header_id IS NOT NULL
1916      AND expense_line_rec.itemization_parent_id IS NOT NULL) THEN
1917 
1918    /*
1919     * When a itemized line is shortpaid, all the other itemized lines will be shortpaid also.
1920     * In addition for company pay there might exist a personal row, which is not itemized,
1921     * with the CC cc transaction, but has to also be shortpaid when any of the other
1922     * itemization is shortpaid. So the query has OR statement which will deal with
1923     * cash and CC lines separately. For cash the itemized lines are shortpaid, for
1924     * CC transactions all lines belonging to the same transactions are shortpaid
1925     */
1926     UPDATE AP_EXPENSE_REPORT_LINES_ALL
1927     SET    policy_shortpay_flag = DECODE(expense_line_rec.policy_shortpay_flag,
1928                                          'Y','Y',
1929                                           policy_shortpay_flag),
1930            receipt_verified_flag = DECODE(NVL(expense_line_rec.receipt_verified_flag,'N'),
1931                                           'N','N',
1932                                           receipt_verified_flag)
1933     WHERE report_header_id = expense_line_rec.report_header_id
1934     AND (itemization_parent_id = expense_line_rec.itemization_parent_id
1935              OR
1936              /* Deal with itemized personal CC line */
1937              (     expense_line_rec.credit_card_trx_id IS NOT NULL
1938                AND credit_card_trx_id = expense_line_rec.credit_card_trx_id)
1939          );
1940   END IF;
1941 END process_shortpays;
1942 
1943 
1944 /*========================================================================
1945  | PUBLIC PROCEDURE process_rate_rounding
1946  |
1947  | DESCRIPTION
1948  |   This procedure calculates and creates any rounding lines needed due
1949  |   to rounding issues.
1950  |
1951  | CALLED FROM PROCEDURES/FUNCTIONS (local to this package body)
1952  |   process_audit_actions
1953  |
1954  | CALLS PROCEDURES/FUNCTIONS (local to this package body)
1955  |
1956  | RETURNS
1957  |   None
1958  |
1959  | PARAMETERS
1960  |   Expense report header identifier to be processed
1961  |
1962  | MODIFICATION HISTORY
1963  | Date                  Author            Description of Changes
1964  | 21-Jul-2003           J Rautiainen      Created
1965  |
1966  *=======================================================================*/
1967 PROCEDURE process_rate_rounding(p_report_header_id IN  NUMBER) IS
1968 
1969   CURSOR totals_c(p_personal_expense_id IN NUMBER, p_rounding_expense_id IN NUMBER) IS
1970     SELECT itemization_parent_id,
1971            credit_card_trx_id,
1972            sum(amount) total_amount,
1973            sum(daily_amount
1974                 * NVL((end_expense_date - start_expense_date)+1,1)
1975                 * NVL(receipt_conversion_rate,1)) total_daily_amount,
1976            currency_code
1977     FROM ap_expense_report_lines_all
1978     WHERE report_header_id = p_report_header_id
1979     AND currency_code <> NVL(receipt_currency_code,currency_code)
1980     AND web_parameter_id <> p_personal_expense_id
1981     AND web_parameter_id <> p_rounding_expense_id
1982     AND itemization_parent_id is not null
1983     AND itemization_parent_id <> -1      -- do not include parent line
1984     GROUP BY itemization_parent_id, credit_card_trx_id, currency_code;
1985 
1986   CURSOR rounding_line_c(p_itemization_parent_id IN NUMBER, p_trx_id IN NUMBER, p_rounding_expense_id IN NUMBER) IS
1987     SELECT AERL.*
1988     FROM AP_EXPENSE_REPORT_LINES_ALL AERL
1989     WHERE REPORT_HEADER_ID = p_report_header_id
1990     AND WEB_PARAMETER_ID = p_rounding_expense_id
1991     AND ITEMIZATION_PARENT_ID = p_itemization_parent_id
1992     AND ( (p_trx_id IS NULL AND credit_card_trx_id is NULL)
1993            OR
1994           (p_trx_id IS NOT NULL AND credit_card_trx_id IS NOT NULL)
1995         )
1996     FOR UPDATE OF REPORT_HEADER_ID NOWAIT;
1997 
1998   CURSOR lines_c(p_itemization_parent_id IN NUMBER, p_trx_id IN NUMBER, p_personal_expense_id IN NUMBER) IS
1999     SELECT AERL.*
2000     FROM AP_EXPENSE_REPORT_LINES_ALL AERL
2001     WHERE REPORT_HEADER_ID = p_report_header_id
2002     AND WEB_PARAMETER_ID <> p_personal_expense_id
2003     AND ITEMIZATION_PARENT_ID = p_itemization_parent_id
2004     AND ( (p_trx_id IS NULL AND credit_card_trx_id is NULL)
2005            OR
2006           (p_trx_id IS NOT NULL AND credit_card_trx_id IS NOT NULL)
2007         )
2008     ORDER BY distribution_line_number;
2009 
2010   CURSOR rounding_expense_c(p_parameter_id IN NUMBER) IS
2011     SELECT parameter_id,
2012            LINE_TYPE_LOOKUP_CODE,
2013            category_code, prompt
2014     FROM ap_expense_report_params_all
2015     WHERE parameter_id = p_parameter_id;
2016 
2017   CURSOR distribution_c(p_report_line_id IN NUMBER) IS
2018     SELECT REPORT_HEADER_ID
2019       FROM AP_EXP_REPORT_DISTS
2020       WHERE (REPORT_LINE_ID = p_report_line_id)
2021       FOR UPDATE OF REPORT_HEADER_ID NOWAIT;
2022 
2023   rounding_line_rec      rounding_line_c%ROWTYPE;
2024   rounding_expense_rec   rounding_expense_c%ROWTYPE;
2025   lines_rec              lines_c%ROWTYPE;
2026   new_report_line_rec    AP_EXPENSE_REPORT_LINES_ALL%ROWTYPE;
2027   distribution_rec       distribution_c%ROWTYPE;
2028   l_exp_line_ccid        AP_WEB_DB_EXPLINE_PKG.expLines_codeCombID;
2029 
2030   ln_total_amount          NUMBER;
2031   ln_total_daily_amount    NUMBER;
2032   ln_rounding_amount       NUMBER;
2033 
2034   ln_personal_expense_id   NUMBER;
2035   ln_rounding_expense_id   NUMBER;
2036   ln_next_dist_line_number NUMBER;
2037 
2038   l_precision            NUMBER  := 0;
2039   l_extended_precision   NUMBER  := 0;
2040   l_min_acct_unit        NUMBER  := 0;
2041 
2042 BEGIN
2043   ln_personal_expense_id := AP_WEB_AUDIT_UTILS.get_seeded_expense_id('PERSONAL');
2044   ln_rounding_expense_id := AP_WEB_AUDIT_UTILS.get_seeded_expense_id('ROUNDING');
2045 
2046   FOR totals_rec IN totals_c(ln_personal_expense_id, ln_rounding_expense_id) LOOP
2047 
2048     fnd_currency.get_info(totals_rec.CURRENCY_CODE,l_precision,l_extended_precision,l_min_acct_unit);
2049     ln_total_amount       := ROUND(totals_rec.total_amount, l_precision);
2050     ln_total_daily_amount := ROUND(totals_rec.total_daily_amount, l_precision);
2051 
2052     IF ln_total_amount <> ln_total_daily_amount THEN
2053 
2054       /**
2055       * Find the a existing line for the itemization to copy the data from
2056       * Since the information we use are identical on all itemized lines the
2057       * cursor is ordered by distribution_line_number, so we are taking the
2058       * information from the line first created within the itemization.
2059       */
2060       OPEN lines_c(totals_rec.itemization_parent_id, totals_rec.credit_card_trx_id, ln_personal_expense_id);
2061       FETCH lines_c into lines_rec;
2062       CLOSE lines_c;
2063 
2064       ln_rounding_amount := ln_total_daily_amount-ln_total_amount;
2065 
2066       OPEN rounding_line_c(totals_rec.itemization_parent_id, totals_rec.credit_card_trx_id, ln_rounding_expense_id);
2067       FETCH rounding_line_c into rounding_line_rec;
2068 
2069       IF rounding_line_c%FOUND THEN
2070 
2071         UPDATE AP_EXPENSE_REPORT_LINES_ALL
2072         SET    amount           = ln_rounding_amount
2073         WHERE CURRENT OF rounding_line_c;
2074 
2075         CLOSE rounding_line_c;
2076       ELSE
2077         CLOSE rounding_line_c;
2078 
2079         /**
2080         * Itemized rounding line does not exists, we need
2081         * to create a new rounding line for the adjusted amount.
2082         */
2083 
2084         /**
2085         * Find the expense type information for rounding expenses.
2086         */
2087         OPEN rounding_expense_c(ln_rounding_expense_id);
2088         FETCH rounding_expense_c into rounding_expense_rec;
2089         CLOSE rounding_expense_c;
2090 
2091         /**
2092         * Fetch the rounding error account to which the rounding amount is accounted.
2093         */
2094         l_exp_line_ccid := AP_WEB_AUDIT_UTILS.get_rounding_error_ccid(lines_rec.org_id);
2095 
2096         ln_next_dist_line_number := AP_WEB_AUDIT_UTILS.get_next_distribution_line_id(p_report_header_id);
2097 
2098         /**
2099         * Populate the new rounding row with data from the original row and overwriting
2100         * the following data.
2101         */
2102         new_report_line_rec.report_header_id            := lines_rec.report_header_id;
2103         new_report_line_rec.distribution_line_number    := ln_next_dist_line_number;
2104         new_report_line_rec.itemization_parent_id       := lines_rec.itemization_parent_id;
2105         new_report_line_rec.amount                      := ln_rounding_amount;
2106         new_report_line_rec.web_parameter_id            := rounding_expense_rec.parameter_id;
2107        -- new_report_line_rec.code_combination_id         := l_exp_line_ccid;
2108         new_report_line_rec.item_description            := rounding_expense_rec.line_type_lookup_code;
2109         new_report_line_rec.line_type_lookup_code       := rounding_expense_rec.line_type_lookup_code;
2110         new_report_line_rec.start_expense_date          := lines_rec.start_expense_date;
2111         new_report_line_rec.currency_code               := lines_rec.currency_code;
2112         new_report_line_rec.receipt_currency_code       := lines_rec.receipt_currency_code;
2113         new_report_line_rec.set_of_books_id             := lines_rec.set_of_books_id;
2114         new_report_line_rec.org_id                      := lines_rec.org_id;
2115         new_report_line_rec.last_update_login           := FND_GLOBAL.login_id;
2116         new_report_line_rec.last_updated_by             := FND_GLOBAL.user_id;
2117         new_report_line_rec.last_update_date            := SYSDATE;
2118         new_report_line_rec.created_by                  := FND_GLOBAL.user_id;
2119         new_report_line_rec.creation_date               := SYSDATE;
2120         new_report_line_rec.category_code               := 'ROUNDING';
2121         new_report_line_rec.justification_required_flag := 'N';
2122 
2123         AP_WEB_DB_EXPLINE_PKG.InsertLine(new_report_line_rec);
2124 
2125        OPEN rounding_line_c(totals_rec.itemization_parent_id, totals_rec.credit_card_trx_id, ln_rounding_expense_id);
2126        FETCH rounding_line_c into rounding_line_rec;
2127        CLOSE rounding_line_c;
2128         /* Create distribution line */
2129         AP_WEB_DB_EXPDIST_PKG.updateAccountValues (
2130                    p_report_header_id => rounding_line_rec.report_header_id,
2131                    p_report_line_id   => rounding_line_rec.report_line_id,
2132                    p_report_distribution_id => null,
2133                    p_ccid             => l_exp_line_ccid);
2134 
2135       END IF; -- rounding_line_c%FOUND
2136     ELSE -- ln_total_amount = ln_total_daily_amount
2137 
2138       OPEN rounding_line_c(totals_rec.itemization_parent_id, totals_rec.credit_card_trx_id, ln_rounding_expense_id);
2139       FETCH rounding_line_c into rounding_line_rec;
2140 
2141       IF rounding_line_c%FOUND THEN
2142         DELETE AP_EXPENSE_REPORT_LINES_ALL
2143         WHERE CURRENT OF rounding_line_c;
2144       END IF;
2145       CLOSE rounding_line_c;
2146 
2147 
2148       OPEN distribution_c(rounding_line_rec.report_line_id);
2149       FETCH distribution_c into distribution_rec;
2150       IF distribution_c%FOUND THEN
2151         DELETE AP_EXP_REPORT_DISTS_ALL
2152         WHERE CURRENT OF distribution_c;
2153       END IF;
2154       CLOSE distribution_c;
2155 
2156     END IF; -- ln_total_amount <> ln_total_daily_amount
2157   END LOOP;
2158 
2159 END process_rate_rounding;
2160 
2161 /*========================================================================
2162  | PUBLIC FUNCTION bothpay_personal_cc_only
2163  |
2164  | DESCRIPTION
2165  |   This function checks if the report has only bothpay personal credit card expenses
2166  |
2167  | CALLED FROM PROCEDURES/FUNCTIONS (local to this package body)
2168  |   Called from function process_expense_report(p_report_header_id IN NUMBER)
2169  |
2170  | CALLS PROCEDURES/FUNCTIONS (local to this package body)
2171  |
2172  | RETURNS
2173  |   TRUE in case the report has only bothpay personal credit card expenses,
2174  |   otherwise FALSE
2175  |
2176  | PARAMETERS
2177  |   p_report_header_id IN  Expense Report identifier
2178  |
2179  | MODIFICATION HISTORY
2180  | Date                  Author            Description of Changes
2181  | 28-Feb-2005           Maulik Vadera     Created
2182  |
2183  *=======================================================================*/
2184 
2185 FUNCTION bothpay_personal_cc_only(p_report_header_id IN  NUMBER) RETURN BOOLEAN
2186 IS
2187   line_count              NUMBER(15);
2188 BEGIN
2189 
2190  SELECT COUNT(REPORT_LINE_ID) into line_count
2191  FROM AP_EXPENSE_REPORT_LINES_ALL
2192  WHERE REPORT_HEADER_ID = p_report_header_id;
2193 
2194  IF line_count = 0 THEN
2195   RETURN TRUE;
2196  ELSE
2197   RETURN FALSE;
2198  END IF;
2199 
2200 END bothpay_personal_cc_only;
2201 
2202 PROCEDURE process_receiptbased_audit(p_report_header_id IN NUMBER, p_audit_code OUT NOCOPY VARCHAR2) IS
2203 l_receipt_count		NUMBER;
2204 l_img_receipt_count	NUMBER;
2205 BEGIN
2206 
2207   SELECT COUNT(1) into l_img_receipt_count
2208   FROM AP_EXPENSE_REPORT_LINES_ALL
2209   WHERE REPORT_HEADER_ID = p_report_header_id
2210   AND NVL(IMAGE_RECEIPT_REQUIRED_FLAG, 'N') = 'Y';
2211 
2212   SELECT COUNT(1) into l_receipt_count
2213   FROM AP_EXPENSE_REPORT_LINES_ALL
2214   WHERE REPORT_HEADER_ID = p_report_header_id
2215   AND NVL(RECEIPT_REQUIRED_FLAG, 'N') = 'Y';
2216 
2217   IF l_img_receipt_count > 0 THEN
2218    p_audit_code := 'RECEIPT_BASED';
2219   ELSIF(l_receipt_count > 0) THEN
2220    p_audit_code := 'AUDIT';
2221   END IF;
2222 END process_receiptbased_audit;
2223 
2224 PROCEDURE process_random_audit(p_report_header_id IN NUMBER, p_audit_code OUT NOCOPY VARCHAR2) IS
2225 CURSOR rr_cur IS
2226     select count(1) rr_line_count
2227     from ap_expense_report_lines_all aerl
2228     where aerl.report_header_id = p_report_header_id
2229     and   (nvl(aerl.receipt_required_flag, 'N') = 'Y' OR  nvl(aerl.image_receipt_required_flag, 'N') = 'Y');
2230 
2231 rr_rec                 rr_cur%ROWTYPE;
2232 BEGIN
2233  OPEN rr_cur;
2234  FETCH rr_cur INTO rr_rec;
2235  CLOSE rr_cur;
2236 
2237  IF (rr_rec.rr_line_count = 0) THEN
2238     p_audit_code := 'PAPERLESS_AUDIT';
2239  ELSE
2240     process_receiptbased_audit(p_report_header_id, p_audit_code);
2241  END IF;
2242 
2243 END process_random_audit;
2244 
2245 /**
2246  * jrautiai ADJ Fix end
2247  */
2248 END AP_WEB_AUDIT_PROCESS;