IO-2327 posting bills test caes

This commit is contained in:
swtmply
2023-06-26 10:34:33 +08:00
parent 12d07f8318
commit 39f7a3c870
12 changed files with 6155 additions and 12 deletions

View File

@@ -0,0 +1,194 @@
import uniqueId from "lodash/uniqueId";
describe(
"Billing job parts orders",
{
defaultCommandTimeout: 5000,
},
() => {
beforeEach(() => {
cy.visit("/manage");
cy.get("body").then(($body) => {
if ($body.text().includes("Login")) {
// Log in
cy.get('[data-cy="username"]').type("john@imex.dev");
cy.get('[data-cy="password"]').type("john123");
cy.get('[data-cy="sign-in-button"]').click();
}
cy.get(".ant-table-tbody")
.should("be.visible")
.find("tr")
.should("not.have.class", "ant-table-placeholder");
cy.get(".ant-table-row")
.not(':contains("Open")')
.first()
.find("a")
.first()
.click();
cy.url().should("include", "/manage/jobs");
// 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(uniqueId());
cy.get("#bill-form-date").click();
cy.get('[title="2023-06-22"]').should("be.visible").click();
// get table
cy.get('[data-cy="bill-line-table"]').each(($row) => {
// get retail amount
cy.wrap($row)
.find('[data-cy="bill-line-actual-price"]')
.invoke("val")
.then((p) => {
const vendorPercentOff = 0.2;
// get cost - vendor's percent off
const cost = p - p * vendorPercentOff;
cy.get('[data-cy="bill-form-bill-total"]').type(p);
cy.wrap($row).find('[data-cy="bill-line-actual-cost"]').type(cost);
});
});
// Click save
cy.get('[data-cy="bill-form-save-button"]')
.should("not.be.disabled")
.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(uniqueId("DBP"));
cy.get("#bill-form-date").click();
cy.get('[title="2023-06-22"]').should("be.visible").click();
// get table
cy.get('[data-cy="bill-line-table"]').each(($row) => {
// get retail amount
cy.wrap($row)
.find('[data-cy="bill-line-actual-price"]')
.invoke("val")
.then((p) => {
const vendorPercentOff = 0.2;
// get cost - vendor's percent off
const cost = p - p * vendorPercentOff;
cy.get('[data-cy="bill-form-bill-total"]').type(p);
cy.wrap($row).find('[data-cy="bill-line-actual-cost"]').type(cost);
});
});
// Click save
cy.get('[data-cy="bill-form-save-button"]')
.should("not.be.disabled")
.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(uniqueId("DBP"));
cy.get("#bill-form-date").click();
cy.get('[title="2023-06-22"]').should("be.visible").click();
// get table
cy.get('[data-cy="bill-line-table"]').each(($row) => {
// get retail amount
cy.wrap($row)
.find('[data-cy="bill-line-actual-price"]')
.invoke("val")
.then((p) => {
const vendorPercentOff = 0.2;
// get cost - vendor's percent off
const cost = p - p * vendorPercentOff;
cy.get('[data-cy="bill-form-bill-total"]').type(p);
cy.wrap($row).find('[data-cy="bill-line-actual-cost"]').type(cost);
});
});
// 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 });
});
}
);

View File

@@ -50,7 +50,7 @@ Cypress.on("uncaught:exception", (err, runnable) => {
return false;
});
Cypress.Commands.add("antdSelect", (selector) => {
Cypress.Commands.add("antdSelect", (selector, filter) => {
cy.get(`.ant-select-${selector} > .ant-select-selector`).click();
cy.get(`.ant-select-${selector} .ant-select-selection-search input`)
.invoke("attr", "id")
@@ -59,6 +59,7 @@ Cypress.Commands.add("antdSelect", (selector) => {
cy.get(dropDownSelector)
.next()
.find(".ant-select-item-option-content")
.not(`:contains("${filter}")`)
.first()
.click();
});

5912
client/job.json Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -10,7 +10,7 @@ import { createStructuredSelector } from "reselect";
import {
DELETE_BILL_LINE,
INSERT_NEW_BILL_LINES,
UPDATE_BILL_LINE
UPDATE_BILL_LINE,
} from "../../graphql/bill-lines.queries";
import { QUERY_BILL_BY_PK, UPDATE_BILL } from "../../graphql/bills.queries";
import { insertAuditTrail } from "../../redux/application/application.actions";
@@ -200,6 +200,7 @@ export function BillDetailEditcontainer({
}
/>
<Form
data-cy="bill-edit-form"
form={form}
onFinish={handleFinish}
initialValues={transformData(data)}

View File

@@ -362,11 +362,16 @@ function BillEnterModalContainer({
{t("bills.labels.generatepartslabel")}
</Checkbox>
<Button onClick={handleCancel}>{t("general.actions.cancel")}</Button>
<Button loading={loading} onClick={() => form.submit()}>
<Button
data-cy="bill-form-save-button"
loading={loading}
onClick={() => form.submit()}
>
{t("general.actions.save")}
</Button>
{billEnterModal.context && billEnterModal.context.id ? null : (
<Button
data-cy="bill-form-savenew-button"
type="primary"
loading={loading}
onClick={() => {

View File

@@ -177,6 +177,7 @@ export function BillFormComponent({
]}
>
<VendorSearchSelect
className="ant-select-bill-vendor"
disabled={disabled}
options={vendorAutoCompleteOptions}
onSelect={handleVendorSelect}
@@ -249,7 +250,10 @@ export function BillFormComponent({
}),
]}
>
<Input disabled={disabled || disableInvNumber} />
<Input
data-cy="bill-form-invoice"
disabled={disabled || disableInvNumber}
/>
</Form.Item>
<Form.Item
label={t("bills.fields.date")}
@@ -261,7 +265,7 @@ export function BillFormComponent({
},
]}
>
<FormDatePicker disabled={disabled} />
<FormDatePicker id="bill-form-date" disabled={disabled} />
</Form.Item>
<Form.Item
label={t("bills.fields.is_credit_memo")}
@@ -303,6 +307,7 @@ export function BillFormComponent({
<Switch />
</Form.Item>
<Form.Item
data-cy="bill-form-bill-total"
label={t("bills.fields.total")}
name="total"
rules={[
@@ -456,19 +461,20 @@ export function BillFormComponent({
}}
>
<Upload.Dragger
id="bill-image-upload"
multiple={true}
name="logo"
beforeUpload={() => false}
listType="picture"
>
<>
<div>
<p className="ant-upload-drag-icon">
<UploadOutlined />
</p>
<p className="ant-upload-text">
Click or drag files to this area to upload.
</p>
</>
</div>
</Upload.Dragger>
</Form.Item>
</div>

View File

@@ -1,14 +1,15 @@
import { DeleteFilled, DollarCircleFilled } from "@ant-design/icons";
import { useTreatments } from "@splitsoftware/splitio-react";
import {
Button, Form,
Button,
Form,
Input,
InputNumber,
Select,
Space,
Switch,
Table,
Tooltip
Tooltip,
} from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
@@ -79,6 +80,7 @@ export function BillEnterModalLinesComponent({
),
formInput: (record, index) => (
<BillLineSearchSelect
className="ant-select-bill-line"
disabled={disabled}
options={lineData}
style={{ width: "100%", minWidth: "10rem" }}
@@ -194,6 +196,7 @@ export function BillEnterModalLinesComponent({
},
formInput: (record, index) => (
<CurrencyInput
data-cy="bill-line-actual-price"
min={0}
disabled={disabled}
onBlur={(e) => {
@@ -241,6 +244,7 @@ export function BillEnterModalLinesComponent({
},
formInput: (record, index) => (
<CurrencyInput
data-cy="bill-line-actual-cost"
min={0}
disabled={disabled}
controls={false}
@@ -572,6 +576,7 @@ export function BillEnterModalLinesComponent({
return (
<>
<Table
data-cy="bill-line-table"
components={{
body: {
cell: EditableCell,
@@ -587,6 +592,7 @@ export function BillEnterModalLinesComponent({
/>
<Form.Item>
<Button
data-cy="bill-line-add-button"
disabled={disabled}
onClick={() => {
add();

View File

@@ -54,7 +54,10 @@ export function BillsListTableComponent({
const recordActions = (record, showView = false) => (
<Space wrap>
{showView && (
<Button onClick={() => handleOnRowClick(record)}>
<Button
onClick={() => handleOnRowClick(record)}
data-cy="edit-bill-button"
>
<EditFilled />
</Button>
)}
@@ -178,6 +181,7 @@ export function BillsListTableComponent({
{job && job.converted ? (
<>
<Button
data-cy="bills-post-button"
onClick={() => {
setBillEnterContext({
actions: { refetch: billsQuery.refetch },
@@ -217,6 +221,7 @@ export function BillsListTableComponent({
}
>
<Table
data-cy="bills-table"
loading={billsQuery.loading}
scroll={{
x: true, // y: "50rem"

View File

@@ -35,6 +35,7 @@ export function DocumentsLocalUploadComponent({
return (
<Upload.Dragger
id="bill-document-upload"
multiple={true}
fileList={fileList}
onChange={(f) => {

View File

@@ -148,6 +148,7 @@ export function PartsOrderListTableComponent({
</Button>
</Popconfirm>
<Button
data-cy="receive-bill-button"
disabled={
(jobRO ? !record.return : jobRO) ||
record.vendor.id === bodyshop.inhousevendorid
@@ -478,6 +479,7 @@ export function PartsOrderListTableComponent({
{selectedPartsOrderRecord && rowExpander(selectedPartsOrderRecord)}
</Drawer>
<Table
data-cy="part-orders-table"
loading={billsQuery.loading}
scroll={{
x: true,

View File

@@ -7,7 +7,16 @@ const { Option } = Select;
//To be used as a form element only.
const VendorSearchSelect = (
{ value, onChange, options, onSelect, disabled, preferredMake, showPhone },
{
value,
onChange,
options,
onSelect,
disabled,
preferredMake,
showPhone,
...rest
},
ref
) => {
const [option, setOption] = useState(value);
@@ -43,6 +52,7 @@ const VendorSearchSelect = (
optionFilterProp="name"
onSelect={onSelect}
disabled={disabled || false}
{...rest}
>
{favorites
? favorites.map((o) => (

View File

@@ -312,7 +312,7 @@ export function JobsDetailPage({
</Tabs.TabPane>
<Tabs.TabPane
tab={
<span>
<span data-cy="tab-partssublet">
<ToolFilled />
{t("menus.jobsdetail.partssublet")}
</span>