Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
import { Permissions } from '../../../support/dictionary';
import { APPLICATION_NAMES } from '../../../support/constants';
import { ExpenseClasses } from '../../../support/fragments/settings/finance';
import {
Budgets,
FundDetails,
FinanceHelper,
Funds,
GroupDetails,
Groups,
} from '../../../support/fragments/finance';
import { NewOrganization, Organizations } from '../../../support/fragments/organizations';
import { BasicOrderLine, NewOrder, Orders } from '../../../support/fragments/orders';
import { Invoices } from '../../../support/fragments/invoices';
import TopMenu from '../../../support/fragments/topMenu';
import TopMenuNavigation from '../../../support/fragments/topMenuNavigation';
import Users from '../../../support/fragments/users/users';

describe('Finance', () => {
describe('Funds', () => {
const testData = {
expenseClass: ExpenseClasses.getDefaultExpenseClass(),
organization: NewOrganization.getDefaultOrganization(),
user: {},
};

before('Create test data', () => {
cy.getAdminToken().then(() => {
ExpenseClasses.createExpenseClassViaApi(testData.expenseClass);

const group = Groups.getDefaultGroup();
Groups.createViaApi(group).then((groupResponse) => {
testData.group = groupResponse;

const { fiscalYear, fund, budget } = Budgets.createBudgetWithFundLedgerAndFYViaApi({
budget: {
allocated: 1000,
statusExpenseClasses: [
{
status: 'Active',
Comment thread
NadiaIvashko marked this conversation as resolved.
Outdated
expenseClassId: testData.expenseClass.id,
},
],
},
});

testData.fiscalYear = fiscalYear;
testData.fund = fund;
testData.budget = budget;

Funds.getFundsViaApi({ query: `id=="${fund.id}"` }).then(({ funds }) => {
Funds.updateFundViaApi(funds[0], [group.id]);
});

Organizations.createOrganizationViaApi(testData.organization);

// Order #1 with expense class, linked to Fund A
const order1 = {
...NewOrder.getDefaultOrder({ vendorId: testData.organization.id }),
reEncumber: true,
};
const orderLine1 = BasicOrderLine.getDefaultOrderLine({
listUnitPrice: 10,
fundDistribution: [
{
code: fund.code,
fundId: fund.id,
expenseClassId: testData.expenseClass.id,
distributionType: 'percentage',
Comment thread
NadiaIvashko marked this conversation as resolved.
Outdated
value: 100,
},
],
});

Orders.createOrderWithOrderLineViaApi(order1, orderLine1).then((createdOrder1) => {
testData.order1 = createdOrder1;
testData.orderLine1 = orderLine1;
Orders.updateOrderViaApi({ ...createdOrder1, workflowStatus: 'Open' });
Comment thread
NadiaIvashko marked this conversation as resolved.
Outdated
});

// Invoice #1 linked to Order #1
cy.then(() => {
Invoices.createInvoiceWithInvoiceLineViaApi({
vendorId: testData.organization.id,
poLineId: testData.orderLine1.id,
exportToAccounting: false,
fundDistributions: [
{
code: fund.code,
fundId: fund.id,
expenseClassId: testData.expenseClass.id,
distributionType: 'percentage',
Comment thread
NadiaIvashko marked this conversation as resolved.
Outdated
value: 100,
},
],
subTotal: 10,
releaseEncumbrance: true,
}).then((invoice1) => {
testData.invoice1 = invoice1;
});
});

// Approve and Pay Invoice #1
cy.then(() => {
Invoices.changeInvoiceStatusViaApi({ invoice: testData.invoice1, status: 'Approved' });
});
cy.then(() => {
Invoices.changeInvoiceStatusViaApi({ invoice: testData.invoice1, status: 'Paid' });
});
Comment thread
NadiaIvashko marked this conversation as resolved.
Outdated

// Set expense class to Inactive on the budget
cy.then(() => {
Budgets.getBudgetByIdViaApi(testData.budget.id).then((budgetResp) => {
Budgets.updateBudgetViaApi({
...budgetResp,
statusExpenseClasses: budgetResp.statusExpenseClasses.map((ec) => ({
...ec,
status: 'Inactive',
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, use EXPENSE_CLASS_STATUSES constant

Comment thread
NadiaIvashko marked this conversation as resolved.
Outdated
})),
});
});
});

// Order #2 without expense class, linked to Fund A
const order2 = {
...NewOrder.getDefaultOrder({ vendorId: testData.organization.id }),
reEncumber: true,
};
const orderLine2 = BasicOrderLine.getDefaultOrderLine({
listUnitPrice: 20,
fundDistribution: [
{
code: fund.code,
fundId: fund.id,
distributionType: 'percentage',
value: 100,
},
],
});

cy.then(() => {
Orders.createOrderWithOrderLineViaApi(order2, orderLine2).then((createdOrder2) => {
testData.order2 = createdOrder2;
testData.orderLine2 = orderLine2;
Orders.updateOrderViaApi({ ...createdOrder2, workflowStatus: 'Open' });
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, use ORDER_STATUSES.OPEN

});
});

// Invoice #2 linked to Order #2
cy.then(() => {
Invoices.createInvoiceWithInvoiceLineViaApi({
vendorId: testData.organization.id,
poLineId: testData.orderLine2.id,
exportToAccounting: false,
fundDistributions: [
{
code: fund.code,
fundId: fund.id,
distributionType: 'percentage',
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, use FUND_DISTRIBUTION_TYPES.PERCENTAGE

value: 100,
},
],
subTotal: 20,
releaseEncumbrance: true,
}).then((invoice2) => {
testData.invoice2 = invoice2;
});
});

// Approve and Pay Invoice #2
cy.then(() => {
Invoices.changeInvoiceStatusViaApi({ invoice: testData.invoice2, status: 'Approved' });
});
cy.then(() => {
Invoices.changeInvoiceStatusViaApi({ invoice: testData.invoice2, status: 'Paid' });
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, use INVOICE_STATUSES

});
});

cy.createTempUser([
Permissions.uiFinanceViewFundAndBudget.gui,
Permissions.uiFinanceViewFiscalYear.gui,
Permissions.uiFinanceViewGroups.gui,
]).then((userProperties) => {
testData.user = userProperties;

cy.login(testData.user.username, testData.user.password, {
path: TopMenu.fundPath,
waiter: Funds.waitLoading,
});
});
});

after('Delete test data', () => {
cy.getAdminToken().then(() => {
Users.deleteViaApi(testData.user.userId);
Organizations.deleteOrganizationViaApi(testData.organization.id);
});
});

it(
'C805786 Totals for transactions created after expense class was set to inactive are displayed correctly in the expense class summary (thunderjet)',
{ tags: ['extendedPath', 'thunderjet', 'C805786'] },
Comment thread
NadiaIvashko marked this conversation as resolved.
Outdated
() => {
Funds.searchByName(testData.fund.name);
Funds.selectFund(testData.fund.name);
FundDetails.checkFundDetails({
currentExpenseClasses: [
{
name: 'Unassigned',
encumbered: '$0.00',
awaitingPayment: '$0.00',
expended: '$20.00',
percentExpended: '66.67%',
},
{
name: testData.expenseClass.name,
encumbered: '$0.00',
awaitingPayment: '$0.00',
expended: '$10.00',
percentExpended: '33.33%',
status: 'Inactive',
Comment thread
NadiaIvashko marked this conversation as resolved.
Outdated
},
],
});

const BudgetDetails = FundDetails.openCurrentBudgetDetails();
BudgetDetails.checkBudgetDetails({
expenseClasses: [
{
name: 'Unassigned',
encumbered: '$0.00',
awaitingPayment: '$0.00',
expended: '$20.00',
percentExpended: '66.67%',
},
{
name: testData.expenseClass.name,
encumbered: '$0.00',
awaitingPayment: '$0.00',
expended: '$10.00',
percentExpended: '33.33%',
status: 'Inactive',
Comment thread
NadiaIvashko marked this conversation as resolved.
Outdated
},
],
});

BudgetDetails.closeBudgetDetails();
TopMenuNavigation.navigateToApp(APPLICATION_NAMES.FINANCE);
FinanceHelper.selectGroupsNavigation();
Groups.waitLoading();
Groups.searchByName(testData.group.name);
Groups.selectGroupByName(testData.group.name);
Groups.checkFYInGroup(testData.fiscalYear.code);
GroupDetails.checkGroupDetails({
expenseClasses: [
{
name: 'Unassigned',
encumbered: '$0.00',
awaitingPayment: '$0.00',
expended: '$20.00',
percentExpended: '66.67%',
},
{
name: testData.expenseClass.name,
encumbered: '$0.00',
awaitingPayment: '$0.00',
expended: '$10.00',
percentExpended: '33.33%',
},
],
});
Comment thread
NadiaIvashko marked this conversation as resolved.
},
);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import { APPLICATION_NAMES, FUNDING_INFORMATION_NAMES } from '../../../support/constants';
import Permissions from '../../../support/dictionary/permissions';
import {
Budgets,
FinanceHelper,
FiscalYears,
Funds,
Ledgers,
} from '../../../support/fragments/finance';
import BudgetDetails from '../../../support/fragments/finance/budgets/budgetDetails';
import TopMenuNavigation from '../../../support/fragments/topMenuNavigation';
import Users from '../../../support/fragments/users/users';
import getRandomPostfix from '../../../support/utils/stringTools';

describe('Finance', () => {
describe('Funds', () => {
const firstFiscalYear = { ...FiscalYears.defaultUiFiscalYear };
const defaultLedger = { ...Ledgers.defaultUiLedger };
const fundA = { ...Funds.defaultUiFund };
const fundB = {
name: `autotest_fund2_${getRandomPostfix()}`,
code: getRandomPostfix(),
externalAccountNo: getRandomPostfix(),
fundStatus: 'Active',
Comment thread
NadiaIvashko marked this conversation as resolved.
Outdated
description: `This is fund created by E2E test automation script_${getRandomPostfix()}`,
};

const budgetA = {
...Budgets.getDefaultBudget(),
allocated: 200,
};
const budgetB = {
...Budgets.getDefaultBudget(),
allocated: 100,
};
let user;

before('Create test data', () => {
cy.getAdminToken().then(() => {
FiscalYears.createViaApi(firstFiscalYear).then((firstFiscalYearResponse) => {
firstFiscalYear.id = firstFiscalYearResponse.id;
budgetA.fiscalYearId = firstFiscalYearResponse.id;
budgetB.fiscalYearId = firstFiscalYearResponse.id;
defaultLedger.fiscalYearOneId = firstFiscalYear.id;
Ledgers.createViaApi(defaultLedger).then((ledgerResponse) => {
defaultLedger.id = ledgerResponse.id;
fundA.ledgerId = defaultLedger.id;
fundB.ledgerId = defaultLedger.id;

Funds.createViaApi(fundB).then((fundBResponse) => {
fundB.id = fundBResponse.fund.id;
budgetB.fundId = fundBResponse.fund.id;
Budgets.createViaApi(budgetB);
fundA.allocatedToIds = [fundBResponse.fund.id];
Funds.createViaApi(fundA).then((fundAResponse) => {
fundA.id = fundAResponse.fund.id;
budgetA.fundId = fundAResponse.fund.id;
Budgets.createViaApi(budgetA);
});
});
});
});
});

cy.createTempUser([
Permissions.uiFinanceCreateAllocations.gui,
Permissions.uiFinanceViewFundAndBudget.gui,
]).then((userProperties) => {
user = userProperties;

cy.login(userProperties.username, userProperties.password);
TopMenuNavigation.navigateToApp(APPLICATION_NAMES.FINANCE);
Funds.waitLoading();
});
});

after('Delete test data', () => {
cy.getAdminToken();
Users.deleteViaApi(user.userId);
});

it(
'C825298 Validation in the "Move allocation" modal for allocation transaction exceeding total allocated (thunderjet) (TaaS)',
{ tags: ['criticalPath', 'thunderjet', 'C825298'] },
() => {
FinanceHelper.searchByName(fundA.name);
Funds.selectFund(fundA.name);
Funds.checkBudgetDetails([{ ...budgetA, available: budgetA.allocated }]);
Funds.selectBudgetDetails();

const addTransferModal = BudgetDetails.clickMoveAllocationButton();
addTransferModal.verifyFromFieldValue('');
addTransferModal.verifyToFieldValue(fundA.name);

addTransferModal.fillTransferDetails({ fromFund: fundB.name, amount: '200' });
addTransferModal.expectErrorPresent('Total allocation cannot be less than zero');
addTransferModal.verifyConfirmButtonDisabled(true);
addTransferModal.verifyCancelButtonDisabled(false);

addTransferModal.clickSwapButton();
addTransferModal.verifyFromFieldValue(fundA.name);
addTransferModal.verifyToFieldValue(fundB.name);
addTransferModal.verifyConfirmButtonDisabled(false);

addTransferModal.clickSwapButton();
addTransferModal.verifyFromFieldValue(fundB.name);
addTransferModal.verifyToFieldValue(fundA.name);
addTransferModal.expectErrorPresent('Total allocation cannot be less than zero');
addTransferModal.verifyConfirmButtonDisabled(true);

addTransferModal.fillTransferDetails({ amount: '100' });
addTransferModal.clickConfirmButton({ ammountAllocated: true, transferCreated: false });
BudgetDetails.checkBudgetDetails({
summary: [{ key: FUNDING_INFORMATION_NAMES.TOTAL_ALLOCATED, value: '$300.00' }],
});
},
);
});
});
Loading
Loading