diff --git a/bodyshop_translations.babel b/bodyshop_translations.babel index 42450291a..bf46a425b 100644 --- a/bodyshop_translations.babel +++ b/bodyshop_translations.babel @@ -1541,6 +1541,27 @@ + + deleting + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + exporting false @@ -2312,6 +2333,27 @@ + + deleted + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + diff --git a/client/src/components/bill-delete-button/bill-delete-button.component.jsx b/client/src/components/bill-delete-button/bill-delete-button.component.jsx new file mode 100644 index 000000000..729eff9ed --- /dev/null +++ b/client/src/components/bill-delete-button/bill-delete-button.component.jsx @@ -0,0 +1,52 @@ +import { useMutation } from "@apollo/react-hooks"; +import { Button, notification } from "antd"; +import React, { useState } from "react"; +import { useTranslation } from "react-i18next"; +import { DELETE_BILL } from "../../graphql/bills.queries"; + +export default function BillDeleteButton({ bill }) { + const [loading, setLoading] = useState(false); + const { t } = useTranslation(); + const [deleteBill] = useMutation(DELETE_BILL); + + const handleDelete = async () => { + setLoading(true); + const result = await deleteBill({ + variables: { billId: bill.id }, + update(cache) { + cache.modify({ + fields: { + bills(existingBills, { readField }) { + return existingBills.filter( + (billref) => bill.id !== readField("id", billref) + ); + }, + search_bills(existingBills, { readField }) { + return existingBills.filter( + (billref) => bill.id !== readField("id", billref) + ); + }, + }, + }); + }, + }); + + if (!!!result.errors) { + notification["success"]({ message: t("bills.successes.deleted") }); + } else { + notification["error"]({ + message: t("bills.errors.deleting", { + error: JSON.stringify(result.errors), + }), + }); + } + + setLoading(false); + }; + + return ( + + ); +} diff --git a/client/src/components/bills-list-table/bills-list-table.component.jsx b/client/src/components/bills-list-table/bills-list-table.component.jsx index a1ebff9d4..506f1c4a7 100644 --- a/client/src/components/bills-list-table/bills-list-table.component.jsx +++ b/client/src/components/bills-list-table/bills-list-table.component.jsx @@ -1,5 +1,13 @@ import { SyncOutlined } from "@ant-design/icons"; -import { Button, Checkbox, Descriptions, Input, Table, Typography } from "antd"; +import { + Button, + Checkbox, + Descriptions, + Input, + Space, + Table, + Typography, +} from "antd"; import queryString from "query-string"; import React, { useState } from "react"; import { useTranslation } from "react-i18next"; @@ -10,6 +18,7 @@ import { setModalContext } from "../../redux/modals/modals.actions"; import CurrencyFormatter from "../../utils/CurrencyFormatter"; import { DateFormatter } from "../../utils/DateFormatter"; import { alphaSort } from "../../utils/sorters"; +import BillDeleteButton from "../bill-delete-button/bill-delete-button.component"; const mapStateToProps = createStructuredSelector({ //jobRO: selectJobReadOnly, @@ -106,7 +115,7 @@ export function BillsListTableComponent({ dataIndex: "actions", key: "actions", render: (text, record) => ( -
+ {record.exported ? ( ) : ( @@ -116,7 +125,8 @@ export function BillsListTableComponent({ )} -
+ + ), }, ]; diff --git a/client/src/graphql/bills.queries.js b/client/src/graphql/bills.queries.js index 247005449..a92ce8691 100644 --- a/client/src/graphql/bills.queries.js +++ b/client/src/graphql/bills.queries.js @@ -10,6 +10,14 @@ export const INSERT_NEW_BILL = gql` } `; +export const DELETE_BILL = gql` + mutation DELETE_BILL($billId: uuid!) { + delete_bills_by_pk(id: $billId) { + id + } + } +`; + export const QUERY_ALL_BILLS_PAGINATED = gql` query QUERY_ALL_BILLS_PAGINATED( $search: String diff --git a/client/src/pages/bills/bills.page.component.jsx b/client/src/pages/bills/bills.page.component.jsx index 0728cf806..be151ba2a 100644 --- a/client/src/pages/bills/bills.page.component.jsx +++ b/client/src/pages/bills/bills.page.component.jsx @@ -1,10 +1,11 @@ import { SyncOutlined } from "@ant-design/icons"; -import { Button, Checkbox, Input, Table, Typography } from "antd"; +import { Button, Checkbox, Input, Space, Table, Typography } from "antd"; import queryString from "query-string"; import React, { useState } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { Link, useHistory, useLocation } from "react-router-dom"; +import BillDeleteButton from "../../components/bill-delete-button/bill-delete-button.component"; import { setModalContext } from "../../redux/modals/modals.actions"; import CurrencyFormatter from "../../utils/CurrencyFormatter"; import { DateFormatter } from "../../utils/DateFormatter"; @@ -98,7 +99,7 @@ export function BillsListPage({ dataIndex: "actions", key: "actions", render: (text, record) => ( -
+ @@ -128,7 +129,8 @@ export function BillsListPage({ > {t("bills.actions.return")} -
+ + ), }, ]; diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index b4d652e11..b9d9746a6 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -112,7 +112,8 @@ "return": "Return Items" }, "errors": { - "creating": "Error adding bill.", + "creating": "Error adding bill. {{error}}", + "deleting": "Error deleting bill. {{error}}", "exporting": "Error exporting payable(s). {{error}}", "exporting-partner": "Unable to connect to ImEX Partner. Please ensure it is running and logged in.", "invalidro": "Not a valid RO.", @@ -154,7 +155,8 @@ "subtotal": "Subtotal" }, "successes": { - "created": "Invoice added successfully." + "created": "Invoice added successfully.", + "deleted": "Bill deleted successfully." }, "validation": { "unique_invoice_number": "This invoice number has already been entered for this vendor." diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index 61f9f7afe..db73a6b2c 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -113,6 +113,7 @@ }, "errors": { "creating": "", + "deleting": "", "exporting": "", "exporting-partner": "", "invalidro": "", @@ -154,7 +155,8 @@ "subtotal": "" }, "successes": { - "created": "" + "created": "", + "deleted": "" }, "validation": { "unique_invoice_number": "" diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index ae6896832..f7c7096ca 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -113,6 +113,7 @@ }, "errors": { "creating": "", + "deleting": "", "exporting": "", "exporting-partner": "", "invalidro": "", @@ -154,7 +155,8 @@ "subtotal": "" }, "successes": { - "created": "" + "created": "", + "deleted": "" }, "validation": { "unique_invoice_number": "" diff --git a/hasura/migrations/1611272576261_update_permission_user_public_table_bills/down.yaml b/hasura/migrations/1611272576261_update_permission_user_public_table_bills/down.yaml new file mode 100644 index 000000000..e6a9c5c2a --- /dev/null +++ b/hasura/migrations/1611272576261_update_permission_user_public_table_bills/down.yaml @@ -0,0 +1,6 @@ +- args: + role: user + table: + name: bills + schema: public + type: drop_delete_permission diff --git a/hasura/migrations/1611272576261_update_permission_user_public_table_bills/up.yaml b/hasura/migrations/1611272576261_update_permission_user_public_table_bills/up.yaml new file mode 100644 index 000000000..858e53df4 --- /dev/null +++ b/hasura/migrations/1611272576261_update_permission_user_public_table_bills/up.yaml @@ -0,0 +1,21 @@ +- args: + permission: + backend_only: false + filter: + _and: + - job: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + - exported: + _eq: false + role: user + table: + name: bills + schema: public + type: create_delete_permission diff --git a/hasura/migrations/1611272645898_set_fk_public_documents_billid/down.yaml b/hasura/migrations/1611272645898_set_fk_public_documents_billid/down.yaml new file mode 100644 index 000000000..bd8a427a6 --- /dev/null +++ b/hasura/migrations/1611272645898_set_fk_public_documents_billid/down.yaml @@ -0,0 +1,12 @@ +- args: + cascade: false + read_only: false + sql: |- + alter table "public"."documents" drop constraint "documents_billid_fkey", + add constraint "documents_invoiceid_fkey" + foreign key ("billid") + references "public"."bills" + ("id") + on update restrict + on delete restrict; + type: run_sql diff --git a/hasura/migrations/1611272645898_set_fk_public_documents_billid/up.yaml b/hasura/migrations/1611272645898_set_fk_public_documents_billid/up.yaml new file mode 100644 index 000000000..478200f55 --- /dev/null +++ b/hasura/migrations/1611272645898_set_fk_public_documents_billid/up.yaml @@ -0,0 +1,10 @@ +- args: + cascade: false + read_only: false + sql: |- + alter table "public"."documents" drop constraint "documents_invoiceid_fkey", + add constraint "documents_billid_fkey" + foreign key ("billid") + references "public"."bills" + ("id") on update restrict on delete set null; + type: run_sql diff --git a/hasura/migrations/metadata.yaml b/hasura/migrations/metadata.yaml index 418f4b87f..687bcfc13 100644 --- a/hasura/migrations/metadata.yaml +++ b/hasura/migrations/metadata.yaml @@ -587,6 +587,22 @@ tables: - active: _eq: true check: null + delete_permissions: + - role: user + permission: + filter: + _and: + - job: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + - exported: + _eq: false - table: schema: public name: bodyshops