Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Advanced approvals] Add optimistic steps for advanced approvals #44940

Merged
merged 32 commits into from
Aug 9, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
c1a5e67
add build approval chain
rushatgabhane Jul 7, 2024
a8e29ef
fix lint
rushatgabhane Jul 7, 2024
a9afa16
rename to get
rushatgabhane Jul 7, 2024
a7adbba
add next steps for multiple approvers
rushatgabhane Jul 7, 2024
38c65d0
Update src/libs/PolicyUtils.ts
rushatgabhane Jul 8, 2024
5500e9c
Update src/libs/PolicyUtils.ts
rushatgabhane Jul 8, 2024
a4fdf8e
Update src/libs/PolicyUtils.ts
rushatgabhane Jul 8, 2024
bae63de
fix conflict
rushatgabhane Aug 2, 2024
5aa1ce9
fix conflict
rushatgabhane Aug 2, 2024
b08590d
Merge branch 'main' of github.com:rushatgabhane/exfy into additional-…
rushatgabhane Aug 5, 2024
a697d1b
rm next approval step
rushatgabhane Aug 5, 2024
ae18457
rm has advanced approval
rushatgabhane Aug 5, 2024
c2f2352
keep state as submitted if more than one approver
rushatgabhane Aug 5, 2024
5f2be76
get display name for next approver
rushatgabhane Aug 5, 2024
d387a8e
early return if AA is not enabled
rushatgabhane Aug 5, 2024
2e5612c
check if last approver
rushatgabhane Aug 5, 2024
0d5ce30
fix last approver logic
rushatgabhane Aug 5, 2024
7f0d770
fix next approver logic
rushatgabhane Aug 5, 2024
a78ce47
use ownerAccountID for building approval chain
rushatgabhane Aug 5, 2024
ecbbbaa
fix crash when next approver is undefined
rushatgabhane Aug 5, 2024
43edb0b
Merge branch 'main' of github.com:rushatgabhane/exfy into additional-…
rushatgabhane Aug 5, 2024
8787b3f
Merge branch 'main' of github.com:rushatgabhane/exfy into additional-…
rushatgabhane Aug 7, 2024
1bbbc24
extract display name to a func
rushatgabhane Aug 7, 2024
7f5885c
move approval chain, related methods to report utils
rushatgabhane Aug 7, 2024
1fea5ea
add docs
rushatgabhane Aug 7, 2024
cd89b9e
move submit to policyutils
rushatgabhane Aug 7, 2024
38441ea
handle self submit
rushatgabhane Aug 7, 2024
dcb4926
Revert "handle self submit"
rushatgabhane Aug 7, 2024
ab691ac
cleanup
rushatgabhane Aug 7, 2024
05f5276
Merge branch 'main' into additional-approver
rushatgabhane Aug 7, 2024
916ba40
improve readability of last approver
rushatgabhane Aug 9, 2024
c5bd485
Merge branch 'additional-approver' of github.com:rushatgabhane/exfy i…
rushatgabhane Aug 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions src/libs/NextStepUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,62 @@ function buildNextStep(report: OnyxEntry<Report>, predictedNextStatus: ValueOf<t

// Generates an optimistic nextStep once a report has been approved
case CONST.REPORT.STATUS_NUM.APPROVED:
if (PolicyUtils.hasAdvancedApprovalEnabled(policy)) {
const approvalChain = PolicyUtils.getApprovalChain(policy, currentUserAccountID, report?.total ?? 0);
if (approvalChain[0] === currentUserEmail) {
rushatgabhane marked this conversation as resolved.
Show resolved Hide resolved
// Self review
optimisticNextStep = {
type,
title: 'Next Steps:',
message: [
{
text: 'Waiting for ',
},
{
text: 'you',
type: 'strong',
},
{
text: ' to ',
},
{
text: 'pay',
type: 'strong',
},
{
text: ' %expenses.',
},
],
};
}

// Another owner
optimisticNextStep = {
type,
title: 'Next Steps:',
message: [
{
text: ' Waiting for ',
},
{
text: approvalChain[0],
type: 'strong',
},
{
text: ' to ',
},
{
text: 'approve',
type: 'strong',
},
{
text: ' this report.',
},
],
};
break;
}

if (
ReportUtils.isInvoiceReport(report) ||
!ReportUtils.isPayer(
Expand Down
39 changes: 39 additions & 0 deletions src/libs/PolicyUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,10 @@ function getApprovalWorkflow(policy: OnyxEntry<Policy>): ValueOf<typeof CONST.PO
return policy?.approvalMode ?? CONST.POLICY.APPROVAL_MODE.ADVANCED;
}

function hasAdvancedApprovalEnabled(policy: OnyxEntry<Policy>): boolean {
return policy?.approvalMode === CONST.POLICY.APPROVAL_MODE.ADVANCED;
}

function getDefaultApprover(policy: OnyxEntry<Policy>): string {
return policy?.approver ?? policy?.owner ?? '';
}
Expand All @@ -407,6 +411,39 @@ function getSubmitToAccountID(policy: OnyxEntry<Policy>, employeeAccountID: numb
return getAccountIDsByLogins([employee.submitsTo ?? defaultApprover])[0];
}

function getSubmitToEmail(policy: OnyxEntry<Policy>, employeeAccountID: number): string {
const submitToAccountID = getSubmitToAccountID(policy, employeeAccountID);
return getLoginsByAccountIDs([submitToAccountID])[0] ?? '';
}

function getForwardsToAccount(policy: OnyxEntry<Policy>, employeeEmail: string, reportTotal: number): string {
rushatgabhane marked this conversation as resolved.
Show resolved Hide resolved
if (!hasAdvancedApprovalEnabled(policy)) {
return '';
}

const employee = policy?.employeeList?.[employeeEmail];
if (!employee) {
return '';
}

const positiveReportTotal = Math.abs(reportTotal);
if (employee.approvalLimit && employee.overLimitForwardsTo && positiveReportTotal > employee.approvalLimit) {
rushatgabhane marked this conversation as resolved.
Show resolved Hide resolved
return employee.overLimitForwardsTo;
}
return employee.forwardsTo ?? '';
}

function getApprovalChain(policy: OnyxEntry<Policy>, employeeAccountID: number, reportTotal: number): string[] {
rushatgabhane marked this conversation as resolved.
Show resolved Hide resolved
const approvalChain: string[] = [];
let nextApproverEmail = getSubmitToEmail(policy, employeeAccountID);

while (nextApproverEmail && !approvalChain.includes(nextApproverEmail)) {
approvalChain.push(nextApproverEmail);
nextApproverEmail = getForwardsToAccount(policy, nextApproverEmail, reportTotal);
}
return approvalChain;
}

function getPersonalPolicy() {
return Object.values(allPolicies ?? {}).find((policy) => policy?.type === CONST.POLICY.TYPE.PERSONAL);
}
Expand Down Expand Up @@ -682,6 +719,8 @@ export {
getIntegrationLastSuccessfulDate,
getCurrentConnectionName,
getCustomersOrJobsLabelNetSuite,
getApprovalChain,
hasAdvancedApprovalEnabled,
};

export type {MemberEmailsToAccountIDs};
Loading