diff --git a/client/src/components/header/header.component.jsx b/client/src/components/header/header.component.jsx index 6a5bec000..625fff46d 100644 --- a/client/src/components/header/header.component.jsx +++ b/client/src/components/header/header.component.jsx @@ -260,6 +260,11 @@ function Header({ {t("menus.header.accounting-payments")} + + + {t("menus.header.export-logs")} + + diff --git a/client/src/components/jobs-close-export-button/jobs-close-export-button.component.jsx b/client/src/components/jobs-close-export-button/jobs-close-export-button.component.jsx index c08d3e332..6e8d008b6 100644 --- a/client/src/components/jobs-close-export-button/jobs-close-export-button.component.jsx +++ b/client/src/components/jobs-close-export-button/jobs-close-export-button.component.jsx @@ -9,6 +9,7 @@ import { auth } from "../../firebase/firebase.utils"; import { UPDATE_JOB } from "../../graphql/jobs.queries"; import { selectBodyshop } from "../../redux/user/user.selectors"; import { logImEXEvent } from "../../firebase/firebase.utils"; +import { INSERT_EXPORT_LOG } from "../../graphql/accounting.queries"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, @@ -17,6 +18,7 @@ const mapStateToProps = createStructuredSelector({ export function JobsCloseExportButton({ bodyshop, jobId, disabled }) { const { t } = useTranslation(); const [updateJob] = useMutation(UPDATE_JOB); + const [insertExportLog] = useMutation(INSERT_EXPORT_LOG); const [loading, setLoading] = useState(false); const handleQbxml = async () => { logImEXEvent("jobs_close_export"); @@ -72,14 +74,43 @@ export function JobsCloseExportButton({ bodyshop, jobId, disabled }) { const failedTransactions = PartnerResponse.data.filter((r) => !r.success); if (failedTransactions.length > 0) { //Uh oh. At least one was no good. - failedTransactions.map((ft) => - notification["error"]({ + failedTransactions.forEach((ft) => { + //insert failed export log + notification.open({ + key: "failedexports", + type: "error", message: t("jobs.errors.exporting", { error: ft.errorMessage || "", }), - }) - ); + }); + //Call is not awaited as it is not critical to finish before proceeding. + insertExportLog({ + variables: { + logs: [ + { + bodyshopid: bodyshop.id, + jobid: jobId, + success: false, + message: JSON.stringify(ft.errorMessage), + }, + ], + }, + }); + }); } else { + //Insert success export log. + insertExportLog({ + variables: { + logs: [ + { + bodyshopid: bodyshop.id, + jobid: jobId, + success: true, + }, + ], + }, + }); + const jobUpdateResponse = await updateJob({ variables: { jobId: jobId, @@ -90,8 +121,10 @@ export function JobsCloseExportButton({ bodyshop, jobId, disabled }) { }, }); - if (!!!jobUpdateResponse.errors) { - notification["success"]({ + if (!jobUpdateResponse.errors) { + notification.open({ + type: "error", + key: "jobsuccessexport", message: t("jobs.successes.exported"), }); } else { diff --git a/client/src/components/rbac-wrapper/rbac-defaults.js b/client/src/components/rbac-wrapper/rbac-defaults.js index 0da32826f..c23816c80 100644 --- a/client/src/components/rbac-wrapper/rbac-defaults.js +++ b/client/src/components/rbac-wrapper/rbac-defaults.js @@ -2,6 +2,7 @@ const ret = { "accounting:payables": 1, "accounting:payments": 1, "accounting:receivables": 1, + "accounting:exportlogs": 3, "csi:page": 6, "csi:export": 5, diff --git a/client/src/components/shop-info/shop-info.rbac.component.jsx b/client/src/components/shop-info/shop-info.rbac.component.jsx index daa189843..8a97342b4 100644 --- a/client/src/components/shop-info/shop-info.rbac.component.jsx +++ b/client/src/components/shop-info/shop-info.rbac.component.jsx @@ -21,6 +21,18 @@ export default function ShopInfoRbacComponent({ form }) { > + + + ; + + const handleTableChange = (pagination, filters, sorter) => { + searchParams.page = pagination.current; + searchParams.sortcolumn = sorter.columnKey; + searchParams.sortorder = sorter.order; + if (filters.status) { + searchParams.statusFilters = JSON.stringify( + _.flattenDeep(filters.status) + ); + } else { + delete searchParams.statusFilters; + } + history.push({ search: queryString.stringify(searchParams) }); + }; + + const columns = [ + { + title: t("jobs.fields.ro_number"), + dataIndex: "ro_number", + key: "ro_number", + sorter: (a, b) => alphaSort(a.ro_number, b.ro_number), + sortOrder: sortcolumn === "ro_number" && sortorder, + + render: (text, record) => ( + + {(record.job && record.job.ro_number) || t("general.labels.na")} + + ), + }, + { + title: t("jobs.fields.owner"), + dataIndex: "owner", + key: "owner", + // sorter: (a, b) => alphaSort(a.ownr_ln, b.ownr_ln), + // sortOrder: sortcolumn === "owner" && sortorder, + render: (text, record) => { + return record.owner ? ( + + {`${record.ownr_fn || ""} ${record.ownr_ln || ""} ${ + record.ownr_co_nm || "" + }`} + + ) : ( + {`${record.ownr_fn || ""} ${record.ownr_ln || ""} ${ + record.ownr_co_nm || "" + }`} + ); + }, + }, + + { + title: t("jobs.fields.vehicle"), + dataIndex: "vehicle", + key: "vehicle", + ellipsis: true, + render: (text, record) => { + return record.vehicleid ? ( + + {`${record.v_model_yr || ""} ${record.v_make_desc || ""} ${ + record.v_model_desc || "" + }`} + + ) : ( + {`${record.v_model_yr || ""} ${record.v_make_desc || ""} ${ + record.v_model_desc || "" + }`} + ); + }, + }, + { + title: t("vehicles.fields.plate_no"), + dataIndex: "plate_no", + key: "plate_no", + sorter: (a, b) => alphaSort(a.plate_no, b.plate_no), + sortOrder: sortcolumn === "plate_no" && sortorder, + render: (text, record) => { + return record.plate_no ? record.plate_no : ""; + }, + }, + { + title: t("jobs.fields.clm_no"), + dataIndex: "clm_no", + key: "clm_no", + ellipsis: true, + sorter: (a, b) => alphaSort(a.clm_no, b.clm_no), + sortOrder: sortcolumn === "clm_no" && sortorder, + render: (text, record) => { + return record.clm_no ? ( + {record.clm_no} + ) : ( + t("general.labels.unknown") + ); + }, + }, + { + title: t("jobs.fields.clm_total"), + dataIndex: "clm_total", + key: "clm_total", + sorter: (a, b) => a.clm_total - b.clm_total, + sortOrder: sortcolumn === "clm_total" && sortorder, + render: (text, record) => { + return record.clm_total ? ( + {record.clm_total} + ) : ( + t("general.labels.unknown") + ); + }, + }, + { + title: t("jobs.fields.updated_at"), + dataIndex: "updated_at", + key: "updated_at", + render: (text, record) => ( + {record.updated_at} + ), + }, + { + title: t("general.labels.actions"), + dataIndex: "actions", + key: "actions", + render: (text, record) => ( + + ), + }, + ]; + + return ( + + {searchParams.search && ( + <> + + {t("general.labels.searchresults", { + search: searchParams.search, + })} + + + + )} + + { + searchParams.search = value; + history.push({ search: queryString.stringify(searchParams) }); + }} + /> + + } + > + + + ); +} + +export default connect(mapStateToProps, null)(PartsQueuePageComponent); diff --git a/client/src/pages/export-logs/export-logs.page.container.jsx b/client/src/pages/export-logs/export-logs.page.container.jsx new file mode 100644 index 000000000..350d9295b --- /dev/null +++ b/client/src/pages/export-logs/export-logs.page.container.jsx @@ -0,0 +1,36 @@ +import React, { useEffect } from "react"; +import { useTranslation } from "react-i18next"; +import { connect } from "react-redux"; +import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component"; +import { + setBreadcrumbs, + setSelectedHeader, +} from "../../redux/application/application.actions"; +import ExportLogsPage from "./export-logs.page.component"; + +const mapDispatchToProps = (dispatch) => ({ + setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)), + setSelectedHeader: (key) => dispatch(setSelectedHeader(key)), +}); + +export function ExportsLogPageContainer({ setBreadcrumbs, setSelectedHeader }) { + const { t } = useTranslation(); + + useEffect(() => { + document.title = t("titles.export-logs"); + setSelectedHeader("export-logs"); + setBreadcrumbs([ + { + link: "/manage/accounting/exportlogs", + label: t("titles.bc.export-logs"), + }, + ]); + }, [setBreadcrumbs, t, setSelectedHeader]); + + return ( + + + + ); +} +export default connect(null, mapDispatchToProps)(ExportsLogPageContainer); diff --git a/client/src/pages/manage/manage.page.component.jsx b/client/src/pages/manage/manage.page.component.jsx index 26bc8e504..130b0efc9 100644 --- a/client/src/pages/manage/manage.page.component.jsx +++ b/client/src/pages/manage/manage.page.component.jsx @@ -150,6 +150,9 @@ const Help = lazy(() => import("../help/help.page")); const PartsQueue = lazy(() => import("../parts-queue/parts-queue.page.container") ); +const ExportLogs = lazy(() => + import("../export-logs/export-logs.page.container") +); const EmailTest = lazy(() => import("../../components/email-test/email-test-component") ); @@ -307,7 +310,6 @@ export function Manage({ match, conflict, bodyshop }) { component={JobsAvailablePage} /> - { // } - + + diff --git a/hasura/migrations/1618965084777_create_table_public_exportlog/down.yaml b/hasura/migrations/1618965084777_create_table_public_exportlog/down.yaml new file mode 100644 index 000000000..b860fbfc2 --- /dev/null +++ b/hasura/migrations/1618965084777_create_table_public_exportlog/down.yaml @@ -0,0 +1,5 @@ +- args: + cascade: false + read_only: false + sql: DROP TABLE "public"."exportlog"; + type: run_sql diff --git a/hasura/migrations/1618965084777_create_table_public_exportlog/up.yaml b/hasura/migrations/1618965084777_create_table_public_exportlog/up.yaml new file mode 100644 index 000000000..6e862cf61 --- /dev/null +++ b/hasura/migrations/1618965084777_create_table_public_exportlog/up.yaml @@ -0,0 +1,27 @@ +- args: + cascade: false + read_only: false + sql: CREATE EXTENSION IF NOT EXISTS pgcrypto; + type: run_sql +- args: + cascade: false + read_only: false + sql: "CREATE TABLE \"public\".\"exportlog\"(\"id\" uuid NOT NULL DEFAULT gen_random_uuid(), + \"created_at\" timestamptz NOT NULL DEFAULT now(), \"updated_at\" timestamptz + NOT NULL DEFAULT now(), \"jobid\" uuid, \"billid\" uuid, \"paymentid\" uuid, + \"successful\" boolean NOT NULL DEFAULT false, \"message\" text NOT NULL, \"bodyshopid\" + uuid NOT NULL, PRIMARY KEY (\"id\") , FOREIGN KEY (\"jobid\") REFERENCES \"public\".\"jobs\"(\"id\") + ON UPDATE restrict ON DELETE restrict, FOREIGN KEY (\"paymentid\") REFERENCES + \"public\".\"payments\"(\"id\") ON UPDATE restrict ON DELETE restrict, FOREIGN + KEY (\"billid\") REFERENCES \"public\".\"bills\"(\"id\") ON UPDATE restrict + ON DELETE restrict);\nCREATE OR REPLACE FUNCTION \"public\".\"set_current_timestamp_updated_at\"()\nRETURNS + TRIGGER AS $$\nDECLARE\n _new record;\nBEGIN\n _new := NEW;\n _new.\"updated_at\" + = NOW();\n RETURN _new;\nEND;\n$$ LANGUAGE plpgsql;\nCREATE TRIGGER \"set_public_exportlog_updated_at\"\nBEFORE + UPDATE ON \"public\".\"exportlog\"\nFOR EACH ROW\nEXECUTE PROCEDURE \"public\".\"set_current_timestamp_updated_at\"();\nCOMMENT + ON TRIGGER \"set_public_exportlog_updated_at\" ON \"public\".\"exportlog\" \nIS + 'trigger to set value of column \"updated_at\" to current timestamp on row update';" + type: run_sql +- args: + name: exportlog + schema: public + type: add_existing_table_or_view diff --git a/hasura/migrations/1618965114806_alter_table_public_exportlog_add_column_useremail/down.yaml b/hasura/migrations/1618965114806_alter_table_public_exportlog_add_column_useremail/down.yaml new file mode 100644 index 000000000..ea6ea9be1 --- /dev/null +++ b/hasura/migrations/1618965114806_alter_table_public_exportlog_add_column_useremail/down.yaml @@ -0,0 +1,5 @@ +- args: + cascade: false + read_only: false + sql: ALTER TABLE "public"."exportlog" DROP COLUMN "useremail"; + type: run_sql diff --git a/hasura/migrations/1618965114806_alter_table_public_exportlog_add_column_useremail/up.yaml b/hasura/migrations/1618965114806_alter_table_public_exportlog_add_column_useremail/up.yaml new file mode 100644 index 000000000..0d5ac5c69 --- /dev/null +++ b/hasura/migrations/1618965114806_alter_table_public_exportlog_add_column_useremail/up.yaml @@ -0,0 +1,5 @@ +- args: + cascade: false + read_only: false + sql: ALTER TABLE "public"."exportlog" ADD COLUMN "useremail" text NOT NULL; + type: run_sql diff --git a/hasura/migrations/1618965166855_set_fk_public_exportlog_useremail/down.yaml b/hasura/migrations/1618965166855_set_fk_public_exportlog_useremail/down.yaml new file mode 100644 index 000000000..e208cb68d --- /dev/null +++ b/hasura/migrations/1618965166855_set_fk_public_exportlog_useremail/down.yaml @@ -0,0 +1,5 @@ +- args: + cascade: false + read_only: false + sql: alter table "public"."exportlog" drop constraint "exportlog_useremail_fkey"; + type: run_sql diff --git a/hasura/migrations/1618965166855_set_fk_public_exportlog_useremail/up.yaml b/hasura/migrations/1618965166855_set_fk_public_exportlog_useremail/up.yaml new file mode 100644 index 000000000..bdef6bda8 --- /dev/null +++ b/hasura/migrations/1618965166855_set_fk_public_exportlog_useremail/up.yaml @@ -0,0 +1,10 @@ +- args: + cascade: false + read_only: false + sql: |- + alter table "public"."exportlog" + add constraint "exportlog_useremail_fkey" + foreign key ("useremail") + references "public"."users" + ("email") on update restrict on delete restrict; + type: run_sql diff --git a/hasura/migrations/1618965201750_track_all_relationships/down.yaml b/hasura/migrations/1618965201750_track_all_relationships/down.yaml new file mode 100644 index 000000000..3b81bc705 --- /dev/null +++ b/hasura/migrations/1618965201750_track_all_relationships/down.yaml @@ -0,0 +1,48 @@ +- args: + relationship: exportlogs + table: + name: users + schema: public + type: drop_relationship +- args: + relationship: exportlogs + table: + name: jobs + schema: public + type: drop_relationship +- args: + relationship: exportlogs + table: + name: bills + schema: public + type: drop_relationship +- args: + relationship: exportlogs + table: + name: payments + schema: public + type: drop_relationship +- args: + relationship: payment + table: + name: exportlog + schema: public + type: drop_relationship +- args: + relationship: user + table: + name: exportlog + schema: public + type: drop_relationship +- args: + relationship: job + table: + name: exportlog + schema: public + type: drop_relationship +- args: + relationship: bill + table: + name: exportlog + schema: public + type: drop_relationship diff --git a/hasura/migrations/1618965201750_track_all_relationships/up.yaml b/hasura/migrations/1618965201750_track_all_relationships/up.yaml new file mode 100644 index 000000000..02c480ba8 --- /dev/null +++ b/hasura/migrations/1618965201750_track_all_relationships/up.yaml @@ -0,0 +1,80 @@ +- args: + name: exportlogs + table: + name: users + schema: public + using: + foreign_key_constraint_on: + column: useremail + table: + name: exportlog + schema: public + type: create_array_relationship +- args: + name: exportlogs + table: + name: jobs + schema: public + using: + foreign_key_constraint_on: + column: jobid + table: + name: exportlog + schema: public + type: create_array_relationship +- args: + name: exportlogs + table: + name: bills + schema: public + using: + foreign_key_constraint_on: + column: billid + table: + name: exportlog + schema: public + type: create_array_relationship +- args: + name: exportlogs + table: + name: payments + schema: public + using: + foreign_key_constraint_on: + column: paymentid + table: + name: exportlog + schema: public + type: create_array_relationship +- args: + name: payment + table: + name: exportlog + schema: public + using: + foreign_key_constraint_on: paymentid + type: create_object_relationship +- args: + name: user + table: + name: exportlog + schema: public + using: + foreign_key_constraint_on: useremail + type: create_object_relationship +- args: + name: job + table: + name: exportlog + schema: public + using: + foreign_key_constraint_on: jobid + type: create_object_relationship +- args: + name: bill + table: + name: exportlog + schema: public + using: + foreign_key_constraint_on: billid + type: create_object_relationship diff --git a/hasura/migrations/1618965243636_set_fk_public_exportlog_bodyshopid/down.yaml b/hasura/migrations/1618965243636_set_fk_public_exportlog_bodyshopid/down.yaml new file mode 100644 index 000000000..6bfdcbb6c --- /dev/null +++ b/hasura/migrations/1618965243636_set_fk_public_exportlog_bodyshopid/down.yaml @@ -0,0 +1,5 @@ +- args: + cascade: false + read_only: false + sql: alter table "public"."exportlog" drop constraint "exportlog_bodyshopid_fkey"; + type: run_sql diff --git a/hasura/migrations/1618965243636_set_fk_public_exportlog_bodyshopid/up.yaml b/hasura/migrations/1618965243636_set_fk_public_exportlog_bodyshopid/up.yaml new file mode 100644 index 000000000..3b8de1723 --- /dev/null +++ b/hasura/migrations/1618965243636_set_fk_public_exportlog_bodyshopid/up.yaml @@ -0,0 +1,10 @@ +- args: + cascade: false + read_only: false + sql: |- + alter table "public"."exportlog" + add constraint "exportlog_bodyshopid_fkey" + foreign key ("bodyshopid") + references "public"."bodyshops" + ("id") on update restrict on delete restrict; + type: run_sql diff --git a/hasura/migrations/1618965255172_track_all_relationships/down.yaml b/hasura/migrations/1618965255172_track_all_relationships/down.yaml new file mode 100644 index 000000000..4442ea08b --- /dev/null +++ b/hasura/migrations/1618965255172_track_all_relationships/down.yaml @@ -0,0 +1,12 @@ +- args: + relationship: exportlogs + table: + name: bodyshops + schema: public + type: drop_relationship +- args: + relationship: bodyshop + table: + name: exportlog + schema: public + type: drop_relationship diff --git a/hasura/migrations/1618965255172_track_all_relationships/up.yaml b/hasura/migrations/1618965255172_track_all_relationships/up.yaml new file mode 100644 index 000000000..9b3d9ccee --- /dev/null +++ b/hasura/migrations/1618965255172_track_all_relationships/up.yaml @@ -0,0 +1,20 @@ +- args: + name: exportlogs + table: + name: bodyshops + schema: public + using: + foreign_key_constraint_on: + column: bodyshopid + table: + name: exportlog + schema: public + type: create_array_relationship +- args: + name: bodyshop + table: + name: exportlog + schema: public + using: + foreign_key_constraint_on: bodyshopid + type: create_object_relationship diff --git a/hasura/migrations/1618965326359_update_permission_user_public_table_exportlog/down.yaml b/hasura/migrations/1618965326359_update_permission_user_public_table_exportlog/down.yaml new file mode 100644 index 000000000..c6801826d --- /dev/null +++ b/hasura/migrations/1618965326359_update_permission_user_public_table_exportlog/down.yaml @@ -0,0 +1,6 @@ +- args: + role: user + table: + name: exportlog + schema: public + type: drop_insert_permission diff --git a/hasura/migrations/1618965326359_update_permission_user_public_table_exportlog/up.yaml b/hasura/migrations/1618965326359_update_permission_user_public_table_exportlog/up.yaml new file mode 100644 index 000000000..e628656eb --- /dev/null +++ b/hasura/migrations/1618965326359_update_permission_user_public_table_exportlog/up.yaml @@ -0,0 +1,30 @@ +- args: + permission: + allow_upsert: true + backend_only: false + check: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + columns: + - id + - created_at + - updated_at + - jobid + - billid + - paymentid + - successful + - message + - bodyshopid + - useremail + set: {} + role: user + table: + name: exportlog + schema: public + type: create_insert_permission diff --git a/hasura/migrations/1618965339695_update_permission_user_public_table_exportlog/down.yaml b/hasura/migrations/1618965339695_update_permission_user_public_table_exportlog/down.yaml new file mode 100644 index 000000000..44be3351d --- /dev/null +++ b/hasura/migrations/1618965339695_update_permission_user_public_table_exportlog/down.yaml @@ -0,0 +1,6 @@ +- args: + role: user + table: + name: exportlog + schema: public + type: drop_select_permission diff --git a/hasura/migrations/1618965339695_update_permission_user_public_table_exportlog/up.yaml b/hasura/migrations/1618965339695_update_permission_user_public_table_exportlog/up.yaml new file mode 100644 index 000000000..be119622c --- /dev/null +++ b/hasura/migrations/1618965339695_update_permission_user_public_table_exportlog/up.yaml @@ -0,0 +1,31 @@ +- args: + permission: + allow_aggregations: true + backend_only: false + columns: + - successful + - message + - useremail + - created_at + - updated_at + - billid + - bodyshopid + - id + - jobid + - paymentid + computed_fields: [] + filter: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + limit: null + role: user + table: + name: exportlog + schema: public + type: create_select_permission diff --git a/hasura/migrations/metadata.yaml b/hasura/migrations/metadata.yaml index 4a06a6af7..5a9ea1da3 100644 --- a/hasura/migrations/metadata.yaml +++ b/hasura/migrations/metadata.yaml @@ -495,6 +495,13 @@ tables: table: schema: public name: documents + - name: exportlogs + using: + foreign_key_constraint_on: + column: billid + table: + schema: public + name: exportlog - name: parts_orders using: foreign_key_constraint_on: @@ -691,6 +698,13 @@ tables: table: schema: public name: employees + - name: exportlogs + using: + foreign_key_constraint_on: + column: bodyshopid + table: + schema: public + name: exportlog - name: jobs using: foreign_key_constraint_on: @@ -1733,6 +1747,73 @@ tables: _eq: X-Hasura-User-Id - active: _eq: true +- table: + schema: public + name: exportlog + object_relationships: + - name: bill + using: + foreign_key_constraint_on: billid + - name: bodyshop + using: + foreign_key_constraint_on: bodyshopid + - name: job + using: + foreign_key_constraint_on: jobid + - name: payment + using: + foreign_key_constraint_on: paymentid + - name: user + using: + foreign_key_constraint_on: useremail + insert_permissions: + - role: user + permission: + check: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + columns: + - id + - created_at + - updated_at + - jobid + - billid + - paymentid + - successful + - message + - bodyshopid + - useremail + backend_only: false + select_permissions: + - role: user + permission: + columns: + - successful + - message + - useremail + - created_at + - updated_at + - billid + - bodyshopid + - id + - jobid + - paymentid + filter: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + allow_aggregations: true - table: schema: public name: job_conversations @@ -2167,6 +2248,13 @@ tables: table: schema: public name: documents + - name: exportlogs + using: + foreign_key_constraint_on: + column: jobid + table: + schema: public + name: exportlog - name: job_conversations using: foreign_key_constraint_on: @@ -3582,6 +3670,14 @@ tables: - name: job using: foreign_key_constraint_on: jobid + array_relationships: + - name: exportlogs + using: + foreign_key_constraint_on: + column: paymentid + table: + schema: public + name: exportlog insert_permissions: - role: user permission: @@ -3895,6 +3991,13 @@ tables: table: schema: public name: audit_trail + - name: exportlogs + using: + foreign_key_constraint_on: + column: useremail + table: + schema: public + name: exportlog - name: messages using: foreign_key_constraint_on: