Files
bodyshop/client/cypress/e2e/posting-bills/posting-bills.cy.js
2023-08-14 08:40:13 +08:00

663 lines
20 KiB
JavaScript

import job from "../../fixtures/jobs/job-3.json";
import job2 from "../../fixtures/jobs/job-4.json";
import moment from "moment";
import Dinero from "dinero.js";
const uuid = () => Cypress._.random(0, 1e6);
describe(
"Billing job parts orders",
{
defaultCommandTimeout: 5000,
},
() => {
const today = moment(new Date()).format("YYYY-MM-DD");
beforeEach(() => {
cy.viewport(1280, 720);
cy.visit("/manage/jobs");
cy.intercept("POST", Cypress.env("graphql_dev_endpoint"), (req) => {
if (req.body.operationName === "SEARCH_VENDOR_AUTOCOMPLETE") {
req.alias = "vendors";
}
});
cy.get('[data-cy="active-jobs-table"]')
.find(".ant-table-tbody")
.find("> tr:not(.ant-table-measure-row)")
.as("active-jobs-table")
.should("not.have.class", "ant-table-placeholder");
cy.get("@active-jobs-table")
.contains(job.clm_no)
.first()
.parent()
.find('[data-cy="active-job-link"]')
.click();
// Go to repair data tab
cy.get('[data-cy="tab-partssublet"]').should("be.visible").click();
});
it("receives a part bill", () => {
// Find the first row in the parts order
cy.get('[data-cy="part-orders-table"]')
.find(".ant-table-tbody")
.find("> tr:not(.ant-table-measure-row)")
.as("orders-table")
.should("not.have.class", "ant-table-placeholder");
cy.get("@orders-table")
.first()
.should("be.visible")
.find('[data-cy="receive-bill-button"]')
.click();
// fill out form
// data-cy="bill-form-invoice"
cy.get('[data-cy="bill-form-invoice"]').type(uuid());
cy.get("#bill-form-date").click();
cy.get(`[title="${today}"]`).should("be.visible").click({ force: true });
cy.get('[data-cy="bill-line-table"]').each(($row) => {
// get retail amount
cy.wrap($row)
.find('[data-cy="bill-line-actual-price"]')
.click({ force: true, multiple: true });
cy.wrap($row)
.find('[data-cy="bill-line-actual-cost"]')
.click({ multiple: true });
});
cy.get('[data-cy="bill-line-actual-cost"]').then((cells) => {
const totals = cells.toArray().map((el) => Number(el.value));
const sum = Cypress._.sum(totals);
cy.get('[data-cy="bill-form-bill-total"]').type(sum);
});
// // Click save
cy.get('[data-cy="bill-form-save-button"]').click();
cy.get(".ant-notification-notice-message").contains(
"Invoice added successfully."
);
});
it("posts bill directly", () => {
cy.get('[data-cy="bills-post-button"]').should("be.visible").click();
// Add New Line
cy.get('[data-cy="bill-line-add-button"]')
.should("not.be.disabled")
.click();
// Select Vendor
cy.antdSelect("bill-vendor");
// Select Line
cy.antdSelect("bill-line", "-- Not On Estimate --");
// Fill the Form
cy.get('[data-cy="bill-form-invoice"]').type(uuid());
cy.get("#bill-form-date").click();
cy.get(`[title="${today}"]`).should("be.visible").click({ force: true });
cy.get('[data-cy="bill-line-table"]').each(($row) => {
// get retail amount
cy.wrap($row)
.find('[data-cy="bill-line-actual-price"]')
.click({ force: true, multiple: true });
cy.wrap($row)
.find('[data-cy="bill-line-actual-cost"]')
.click({ multiple: true });
});
cy.get('[data-cy="bill-line-actual-cost"]').then((cells) => {
const totals = cells.toArray().map((el) => Number(el.value));
const sum = Cypress._.sum(totals);
cy.get('[data-cy="bill-form-bill-total"]').type(sum);
});
cy.antdSelect("bill-cost-center");
// Click save
cy.get('[data-cy="bill-form-save-button"]').click();
cy.get(".ant-notification-notice-message").contains(
"Invoice added successfully."
);
});
it("posts a bill with save and new", () => {
cy.get('[data-cy="bills-post-button"]').should("be.visible").click();
// Add New Line
cy.get('[data-cy="bill-line-add-button"]')
.should("not.be.disabled")
.click();
// Select Vendor
cy.antdSelect("bill-vendor");
// Select Line
cy.antdSelect("bill-line", "-- Not On Estimate --");
// Fill the Form
cy.get('[data-cy="bill-form-invoice"]').type(uuid());
cy.get("#bill-form-date").click();
cy.get(`[title="${today}"]`).should("be.visible").click({ force: true });
cy.get('[data-cy="bill-line-table"]').each(($row) => {
// get retail amount
cy.wrap($row)
.find('[data-cy="bill-line-actual-price"]')
.click({ force: true, multiple: true });
cy.wrap($row)
.find('[data-cy="bill-line-actual-cost"]')
.click({ multiple: true });
});
cy.get('[data-cy="bill-line-actual-cost"]').then((cells) => {
const totals = cells.toArray().map((el) => Number(el.value));
const sum = Cypress._.sum(totals);
cy.get('[data-cy="bill-form-bill-total"]').type(sum);
});
cy.antdSelect("bill-cost-center");
// Click save
cy.get('[data-cy="bill-form-savenew-button"]')
.should("not.be.disabled")
.click();
cy.get(".ant-notification-notice-message").contains(
"Invoice added successfully."
);
});
it("uploads a document to a bill", () => {
cy.get('[data-cy="bills-table"]')
.find(".ant-table-tbody")
.find("> tr:not(.ant-table-measure-row)")
.as("bills-table")
.should("not.have.class", "ant-table-placeholder");
cy.get("@bills-table")
.first()
.should("be.visible")
.find('[data-cy="edit-bill-button"]')
.click();
cy.location("search").should("include", "billid");
cy.get('[data-cy="bill-edit-form"]')
.find(".ant-upload #bill-document-upload")
.selectFile("job.json", { force: true });
});
it("marks bill as exported", () => {
cy.get('[data-cy="bills-table"]')
.find(".ant-table-tbody")
.find("> tr:not(.ant-table-measure-row)")
.as("bills-table")
.should("not.have.class", "ant-table-placeholder");
cy.get("@bills-table")
.find('[data-cy="bill-exported-checkbox"]')
.not(":checked")
.first()
.as("export-status")
.parent()
.parent()
.parent()
.parent()
.find('[data-cy="edit-bill-button"]')
.click();
cy.location("search").should("include", "billid");
cy.get('[data-cy="bill-mark-export-button"]')
.as("mark-for-export")
.click();
cy.get("@mark-for-export").should("be.disabled");
});
it("marks bill for re-export", () => {
cy.get('[data-cy="bills-table"]')
.find(".ant-table-tbody")
.find("> tr:not(.ant-table-measure-row)")
.as("bills-table")
.should("not.have.class", "ant-table-placeholder");
cy.get("@bills-table")
.find('[data-cy="bill-exported-checkbox"]')
.filter(":checked")
.first()
.as("export-status")
.parent()
.parent()
.parent()
.parent()
.find('[data-cy="edit-bill-button"]')
.click();
cy.location("search").should("include", "billid");
cy.get('[data-cy="bill-mark-reexport-button"]')
.as("mark-for-reexport")
.click();
cy.get("@mark-for-reexport").should("be.disabled");
});
}
);
describe.only(
"Validating and calculating bills",
{
defaultCommandTimeout: 10000,
},
() => {
const today = moment(new Date()).format("YYYY-MM-DD");
const jobLines = job2.joblines.data.filter(
(line) => line.part_type === "PAS" || line.part_type === "PAE"
);
const linesTotal = jobLines.reduce(
(prev, line) => prev + line.act_price,
0
);
beforeEach(() => {
cy.viewport(1280, 720);
cy.visit("/manage/jobs");
cy.intercept("POST", Cypress.env("graphql_dev_endpoint"), (req) => {
if (req.body.operationName === "SEARCH_VENDOR_AUTOCOMPLETE") {
req.alias = "vendors";
}
});
cy.get('[data-cy="active-jobs-table"]')
.find(".ant-table-tbody")
.find("> tr:not(.ant-table-measure-row)")
.as("active-jobs-table")
.should("not.have.class", "ant-table-placeholder");
cy.get("@active-jobs-table")
.contains(job2.clm_no)
.first()
.parent()
.find('[data-cy="active-job-link"]')
.click();
// Go to repair data tab
cy.get('[data-cy="tab-partssublet"]').should("be.visible").click();
});
it("validates auto reconciliation through posting bill", () => {
// Find the first row in the parts order
cy.get('[data-cy="part-orders-table"]')
.find(".ant-table-tbody")
.find("> tr:not(.ant-table-measure-row)")
.as("orders-table")
.should("not.have.class", "ant-table-placeholder");
cy.get("@orders-table")
.first()
.should("be.visible")
.find('[data-cy="receive-bill-button"]')
.click();
// fill out form
cy.get('[data-cy="bill-form-invoice"]').type(uuid());
cy.get("#bill-form-date").click();
cy.get(`[title="${today}"]`).should("be.visible").click({ force: true });
cy.get('[data-cy="bill-line-table"]').each(($row) => {
// get retail amount
cy.wrap($row)
.find('[data-cy="bill-line-actual-price"]')
.as("retailPrice")
.click({ force: true, multiple: true });
cy.wrap($row)
.find('[data-cy="bill-line-actual-cost"]')
.click({ multiple: true });
});
cy.get('[data-cy="bill-line-actual-cost"]').then((cells) => {
const totals = cells.toArray().map((el) => Number(el.value));
const sum = Cypress._.sum(totals);
cy.get('[data-cy="bill-form-bill-total"]').type(sum);
// Get taxes add it to the sum
cy.get('[data-cy="bill-form-tax"]').then((taxes) => {
const subtotals = taxes
.toArray()
.map((el) => Number(el.innerText.substring(1)));
const totalTax = Cypress._.sum(subtotals);
const billAmount = sum + totalTax;
cy.get('[data-cy="bill-form-bill-total"]')
.find("input")
.clear()
.type(billAmount);
});
});
cy.get("#bill-form-discrepancy").should("have.text", "$0.00");
// Click save
cy.get('[data-cy="bill-form-save-button"]').click();
cy.get("@retailPrice")
.invoke("val")
.then((val) => {
const discrepancy = linesTotal - Number(val);
cy.get("#retailtotal").should("have.text", `$${val}`);
cy.get(".discrepancy").each(($statistic) => {
cy.wrap($statistic).should(
"have.text",
Dinero({
amount: discrepancy,
precision: 0,
}).toFormat()
);
});
});
});
it("returning item and validating statistics", () => {
cy.get('[data-cy="bills-table"]')
.find(".ant-table-tbody")
.find("> tr:not(.ant-table-measure-row)")
.as("bills-table")
.should("not.have.class", "ant-table-placeholder");
cy.get("@bills-table")
.find('[data-cy="credit-memo-checkbox"]')
.filter(":not(:checked)")
.first()
.should("not.be.disabled")
.parent()
.parent()
.parent()
.parent()
.find('[data-cy="return-items-button"]')
.click();
cy.get('[data-cy="billline-checkbox"]').check();
cy.get('[data-cy="billline-return-items-ok-button"]').click();
cy.get('[data-cy="billline-actual-price"]')
.find(".ant-form-item-control-input-content")
.then((prices) => {
const totals = prices
.toArray()
.map((el) => Number(el.innerText.substring(1)));
const sum = Cypress._.sum(totals);
const price = Dinero({
amount: sum * 100,
}).toFormat();
cy.get('[data-cy="order-quantity"]').each((input) => {
cy.wrap(input).type("1");
});
cy.get('[data-cy="part-order-select-none"]').click();
cy.get('[data-cy="order-part-submit"]').click();
cy.get("#totalReturns").should("have.text", price);
cy.get("#calculatedcreditsnotreceived").should("have.text", price);
cy.get("#creditsnotreceived").should("have.text", price);
});
});
it("receives credit memo without return part", () => {
// Find the first row in the parts order
cy.get('[data-cy="part-orders-table"]')
.find(".ant-table-tbody")
.find("> tr:not(.ant-table-measure-row)")
.as("orders-table")
.should("not.have.class", "ant-table-placeholder");
cy.get("@orders-table")
.find('[data-cy="part-order-return-checkbox"]')
.filter(":checked")
.first()
.parent()
.parent()
.parent()
.parent()
.find('[data-cy="receive-bill-button"]')
.click();
// fill out form
cy.get('[data-cy="bill-form-invoice"]').type(uuid());
cy.get("#bill-form-date").click();
cy.get(`[title="${today}"]`).should("be.visible").click({ force: true });
cy.get('[data-cy="bill-line-table"]').each(($row) => {
// get retail amount
cy.wrap($row)
.find('[data-cy="bill-line-actual-price"]')
.click({ force: true, multiple: true });
cy.wrap($row)
.find('[data-cy="bill-line-actual-cost"]')
.click({ multiple: true });
});
cy.get('[data-cy="is-credit-memo-switch"]').click();
cy.get('[data-cy="is-credit-memo-switch"]').should(
"have.attr",
"aria-checked",
"false"
);
cy.get('[data-cy="bill-line-actual-cost"]').then((cells) => {
cy.get('[data-cy="bill-line-actual-price"]').then((priceCells) => {
const totals = cells.toArray().map((el) => Number(el.value));
const priceTotals = priceCells
.toArray()
.map((el) => Number(el.value));
const sum = Cypress._.sum(totals);
const priceSum = Cypress._.sum(priceTotals);
cy.get('[data-cy="bill-form-bill-total"]').type(sum);
// Get taxes add it to the sum
cy.get('[data-cy="bill-form-tax"]').then((taxes) => {
const subtotals = taxes
.toArray()
.map((el) => Number(el.innerText.substring(1)));
const totalTax = Cypress._.sum(subtotals);
const billAmount = sum + totalTax;
cy.get('[data-cy="bill-form-bill-total"]')
.find("input")
.clear()
.type(billAmount);
});
cy.get("#bill-form-discrepancy").should("have.text", "$0.00");
cy.get(`.ant-select-bill-cost-center > .ant-select-selector`).each(
(select) => {
cy.wrap(select).click();
cy.wrap(select)
.find("input")
.invoke("attr", "id")
.then((id) => {
cy.get(`#${id}_list`)
.next()
.find(".ant-select-item-option-content")
.first()
.click({ force: true });
});
}
);
// cy.get('[data-cy="bill-form-save-button"]').click();
cy.get("#totalReturns")
.invoke("text")
.then((value) => {
const totalReturns =
Number(value.substring(1)) - priceSum < 0
? 0
: Number(value.substring(1)) - priceSum;
cy.get("#calculatedcreditsnotreceived").should(
"have.text",
Dinero({
amount: totalReturns,
precision: 0,
}).toFormat()
);
});
});
});
});
it("receives credit memo with return part", () => {
// Find the first row in the parts order
cy.get('[data-cy="part-orders-table"]')
.find(".ant-table-tbody")
.find("> tr:not(.ant-table-measure-row)")
.as("orders-table")
.should("not.have.class", "ant-table-placeholder");
cy.get("@orders-table")
.find('[data-cy="part-order-return-checkbox"]')
.filter(":checked")
.first()
.parent()
.parent()
.parent()
.parent()
.find('[data-cy="receive-bill-button"]')
.click();
// fill out form
cy.get('[data-cy="bill-form-invoice"]').type(uuid());
cy.get("#bill-form-date").click();
cy.get(`[title="${today}"]`).should("be.visible").click({ force: true });
cy.get('[data-cy="bill-line-table"]').each(($row) => {
// get retail amount
cy.wrap($row)
.find('[data-cy="bill-line-actual-price"]')
.click({ force: true, multiple: true });
cy.wrap($row)
.find('[data-cy="bill-line-actual-cost"]')
.click({ multiple: true });
});
cy.get('[data-cy="is-credit-memo-switch"]').should(
"have.attr",
"aria-checked",
"true"
);
cy.get('[data-cy="bill-line-actual-cost"]').then((cells) => {
cy.get('[data-cy="bill-line-actual-price"]').then((priceCells) => {
const totals = cells.toArray().map((el) => Number(el.value));
const priceTotals = priceCells
.toArray()
.map((el) => Number(el.value));
const sum = Cypress._.sum(totals);
const priceSum = Cypress._.sum(priceTotals);
cy.get('[data-cy="bill-form-bill-total"]').type(sum);
// Get taxes add it to the sum
cy.get('[data-cy="bill-form-tax"]').then((taxes) => {
const subtotals = taxes
.toArray()
.map((el) => Number(el.innerText.substring(1)));
const totalTax = Cypress._.sum(subtotals);
const billAmount = sum + totalTax;
cy.get('[data-cy="bill-form-bill-total"]')
.find("input")
.clear()
.type(billAmount);
});
cy.get("#bill-form-discrepancy").should("have.text", "$0.00");
cy.get(`.ant-select-bill-cost-center > .ant-select-selector`).each(
(select) => {
cy.wrap(select).click();
cy.wrap(select)
.find("input")
.invoke("attr", "id")
.then((id) => {
cy.get(`#${id}_list`)
.next()
.find(".ant-select-item-option-content")
.first()
.click({ force: true });
});
}
);
cy.get('[data-cy="mark-as-received-checkbox"]').check({
multiple: true,
});
cy.get('[data-cy="bill-form-save-button"]').click();
cy.get("#totalReturns")
.invoke("text")
.then((value) => {
const totalReturns =
Number(value.substring(1)) - priceSum < 0
? 0
: Number(value.substring(1)) - priceSum;
cy.get("#creditsnotreceived").should(
"have.text",
Dinero({
amount: totalReturns,
precision: 0,
}).toFormat()
);
});
});
});
});
// TODO add more assertions to the parts table
// location, status
it.only("views the row expander if it has the order and bill", () => {
cy.get('[data-cy="tab-repairdata"]').should("be.visible").click();
cy.get('[data-cy="filter-parts-button"]')
.should("not.be.disabled")
.click();
cy.get('[data-cy="repair-data-table"]')
.find(".ant-table-tbody")
.find("> tr:not(.ant-table-measure-row)")
.first()
.find("td")
.first()
.click();
cy.get('[data-cy="parts-bills-order"]')
.should("be.visible")
.find("li")
.first()
.should("not.have.text", "This part has not yet been ordered.");
});
}
);