diff --git a/client/src/components/bill-detail-edit/bill-detail-edit-component.jsx b/client/src/components/bill-detail-edit/bill-detail-edit-component.jsx index 17dac6a24..36b1111f1 100644 --- a/client/src/components/bill-detail-edit/bill-detail-edit-component.jsx +++ b/client/src/components/bill-detail-edit/bill-detail-edit-component.jsx @@ -2,20 +2,25 @@ import {useMutation, useQuery} from "@apollo/client"; import {Button, Form, Popconfirm, Space} from "antd"; import dayjs from "../../utils/day"; import queryString from "query-string"; -import React, {useState} from "react"; -import {useTranslation} from "react-i18next"; -import {connect} from "react-redux"; -import {useLocation} from "react-router-dom"; -import {createStructuredSelector} from "reselect"; -import {DELETE_BILL_LINE, INSERT_NEW_BILL_LINES, 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"; -import {setModalContext} from "../../redux/modals/modals.actions"; -import {selectBodyshop} from "../../redux/user/user.selectors"; +import React, { useState } from "react"; +import { useTranslation } from "react-i18next"; +import { connect } from "react-redux"; +import { useLocation } from "react-router-dom"; +import { createStructuredSelector } from "reselect"; +import { + DELETE_BILL_LINE, + INSERT_NEW_BILL_LINES, + 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"; +import { setModalContext } from "../../redux/modals/modals.actions"; +import { selectBodyshop } from "../../redux/user/user.selectors"; import AuditTrailMapping from "../../utils/AuditTrailMappings"; import AlertComponent from "../alert/alert.component"; import BillFormContainer from "../bill-form/bill-form.container"; import BillMarkExportedButton from "../bill-mark-exported-button/bill-mark-exported-button.component"; +import BillPrintButton from "../bill-print-button/bill-print-button.component"; import BillReeportButtonComponent from "../bill-reexport-button/bill-reexport-button.component"; import JobDocumentsGallery from "../jobs-documents-gallery/jobs-documents-gallery.container"; import JobsDocumentsLocalGallery from "../jobs-documents-local-gallery/jobs-documents-local-gallery.container"; @@ -158,49 +163,49 @@ export function BillDetailEditcontainer({setPartsOrderContext, insertAuditTrail, const exported = data && data.bills_by_pk && data.bills_by_pk.exported; - return ( + return ( + <> + {loading && } + {data && ( <> - {loading && } - {data && ( - <> - - - - form.submit()} - onCancel={() => setVisible(false)} - okButtonProps={{loading: updateLoading}} - title={t("bills.labels.editadjwarning")} - > - - - - - - } - /> -
- + + + + form.submit()} + onCancel={() => setVisible(false)} + okButtonProps={{ loading: updateLoading }} + title={t("bills.labels.editadjwarning")} + > + + + + + + } + /> + + {bodyshop.uselocalmediaserver ? ( { + setLoading(true); + try { + await GenerateDocument( + { + name: Templates.parts_invoice_label_single.key, + variables: { + id: billid, + }, + }, + {}, + "p" + ); + } catch (e) { + console.warn("Warning: Error generating a document."); + } + setLoading(false); + }; + + return ( + + + + ); +} diff --git a/client/src/components/contract-cars/contract-cars.component.jsx b/client/src/components/contract-cars/contract-cars.component.jsx index 541d6d7c3..6162ae7af 100644 --- a/client/src/components/contract-cars/contract-cars.component.jsx +++ b/client/src/components/contract-cars/contract-cars.component.jsx @@ -35,6 +35,15 @@ export default function ContractsCarsComponent({ state.sortedInfo.columnKey === "status" && state.sortedInfo.order, render: (text, record) =>
{t(record.status)}
, }, + { + title: t("courtesycars.fields.readiness"), + dataIndex: "readiness", + key: "readiness", + sorter: (a, b) => alphaSort(a.readiness, b.readiness), + sortOrder: + state.sortedInfo.columnKey === "readiness" && state.sortedInfo.order, + render: (text, record) => t(record.readiness), + }, { title: t("courtesycars.fields.year"), dataIndex: "year", diff --git a/client/src/components/courtesy-car-form/courtesy-car-form.component.jsx b/client/src/components/courtesy-car-form/courtesy-car-form.component.jsx index fbc163c32..1e95960a9 100644 --- a/client/src/components/courtesy-car-form/courtesy-car-form.component.jsx +++ b/client/src/components/courtesy-car-form/courtesy-car-form.component.jsx @@ -8,6 +8,7 @@ import { useTranslation } from "react-i18next"; import { CHECK_CC_FLEET_NUMBER } from "../../graphql/courtesy-car.queries"; import { DateFormatter } from "../../utils/DateFormatter"; import CourtesyCarFuelSlider from "../courtesy-car-fuel-select/courtesy-car-fuel-select.component"; +import CourtesyCarReadiness from "../courtesy-car-readiness-select/courtesy-car-readiness-select.component"; import CourtesyCarStatus from "../courtesy-car-status-select/courtesy-car-status-select.component"; import FormDatePicker from "../form-date-picker/form-date-picker.component"; //import FormFieldsChanged from "../form-fields-changed-alert/form-fields-changed-alert.component"; @@ -214,6 +215,12 @@ export default function CourtesyCarCreateFormComponent({ form, saveLoading }) { > + + +
{ step={null} style={{ marginLeft: "2rem", marginRight: "2rem" }} {...props} + tooltip={{ + formatter: (value) => { + switch (value) { + case 0: + return t("courtesycars.labels.fuel.empty"); + case 13: + return t("courtesycars.labels.fuel.18"); + case 25: + return t("courtesycars.labels.fuel.14"); + case 38: + return t("courtesycars.labels.fuel.38"); + case 50: + return t("courtesycars.labels.fuel.12"); + case 63: + return t("courtesycars.labels.fuel.58"); + case 75: + return t("courtesycars.labels.fuel.34"); + case 88: + return t("courtesycars.labels.fuel.78"); + case 100: + return t("courtesycars.labels.fuel.full"); + default: + return value; + } + }, + }} /> ); }; diff --git a/client/src/components/courtesy-car-readiness-select/courtesy-car-readiness-select.component.jsx b/client/src/components/courtesy-car-readiness-select/courtesy-car-readiness-select.component.jsx new file mode 100644 index 000000000..9dd1fd514 --- /dev/null +++ b/client/src/components/courtesy-car-readiness-select/courtesy-car-readiness-select.component.jsx @@ -0,0 +1,35 @@ +import { Select } from "antd"; +import React, { forwardRef, useEffect, useState } from "react"; +import { useTranslation } from "react-i18next"; +const { Option } = Select; + +const CourtesyCarReadinessComponent = ({ value, onChange }, ref) => { + const [option, setOption] = useState(value); + const { t } = useTranslation(); + + useEffect(() => { + if (value !== option && onChange) { + onChange(option); + } + }, [value, option, onChange]); + + return ( + + ); +}; +export default forwardRef(CourtesyCarReadinessComponent); diff --git a/client/src/components/courtesy-cars-list/courtesy-cars-list.component.jsx b/client/src/components/courtesy-cars-list/courtesy-cars-list.component.jsx index b833291e5..b11d57f5a 100644 --- a/client/src/components/courtesy-cars-list/courtesy-cars-list.component.jsx +++ b/client/src/components/courtesy-cars-list/courtesy-cars-list.component.jsx @@ -90,6 +90,26 @@ export default function CourtesyCarsList({ loading, courtesycars, refetch }) { ); }, }, + { + title: t("courtesycars.fields.readiness"), + dataIndex: "readiness", + key: "readiness", + sorter: (a, b) => alphaSort(a.readiness, b.readiness), + filters: [ + { + text: t("courtesycars.readiness.ready"), + value: "courtesycars.readiness.ready", + }, + { + text: t("courtesycars.readiness.notready"), + value: "courtesycars.readiness.notready", + }, + ], + onFilter: (value, record) => value.includes(record.readiness), + sortOrder: + state.sortedInfo.columnKey === "readiness" && state.sortedInfo.order, + render: (text, record) => t(record.readiness), + }, { title: t("courtesycars.fields.year"), dataIndex: "year", @@ -130,6 +150,36 @@ export default function CourtesyCarsList({ loading, courtesycars, refetch }) { sortOrder: state.sortedInfo.columnKey === "plate" && state.sortedInfo.order, }, + { + title: t("courtesycars.fields.fuel"), + dataIndex: "fuel", + key: "fuel", + sorter: (a, b) => alphaSort(a.fuel, b.fuel), + sortOrder: + state.sortedInfo.columnKey === "fuel" && state.sortedInfo.order, + render: (text, record) => { + switch (record.fuel) { + case 100: + return t("courtesycars.labels.fuel.full"); + case 88: + return t("courtesycars.labels.fuel.78"); + case 63: + return t("courtesycars.labels.fuel.58"); + case 50: + return t("courtesycars.labels.fuel.12"); + case 38: + return t("courtesycars.labels.fuel.34"); + case 25: + return t("courtesycars.labels.fuel.14"); + case 13: + return t("courtesycars.labels.fuel.18"); + case 0: + return t("courtesycars.labels.fuel.empty"); + default: + return record.fuel; + } + }, + }, { title: t("courtesycars.labels.outwith"), dataIndex: "outwith", diff --git a/client/src/components/jobs-detail-header/jobs-detail-header.component.jsx b/client/src/components/jobs-detail-header/jobs-detail-header.component.jsx index a5dd99f6f..30bb98560 100644 --- a/client/src/components/jobs-detail-header/jobs-detail-header.component.jsx +++ b/client/src/components/jobs-detail-header/jobs-detail-header.component.jsx @@ -1,8 +1,8 @@ import { + BranchesOutlined, ExclamationCircleFilled, PauseCircleOutlined, WarningFilled, - BranchesOutlined, } from "@ant-design/icons"; import { Card, Col, Row, Space, Tag, Tooltip } from "antd"; import React, { useState } from "react"; @@ -222,6 +222,9 @@ export function JobsDetailHeader({ job, bodyshop, disabled }) { {`${job.v_vin || t("general.labels.na")}`} + + {job.regie_number || t("general.labels.na")} + diff --git a/client/src/components/production-list-table/production-list-print.component.jsx b/client/src/components/production-list-table/production-list-print.component.jsx index b198fcf2a..a4ffea279 100644 --- a/client/src/components/production-list-table/production-list-print.component.jsx +++ b/client/src/components/production-list-table/production-list-print.component.jsx @@ -1,83 +1,126 @@ -import { Button, Dropdown } from "antd"; -import React, { useState } from "react"; -import { TemplateList } from "../../utils/TemplateConstants"; -import { useTranslation } from "react-i18next"; -import { GenerateDocument } from "../../utils/RenderTemplate"; +import {Button, Dropdown} from "antd"; +import React, {useState} from "react"; +import {TemplateList} from "../../utils/TemplateConstants"; +import {useTranslation} from "react-i18next"; +import {GenerateDocument} from "../../utils/RenderTemplate"; +import {connect} from "react-redux"; +import {createStructuredSelector} from "reselect"; +import {selectBodyshop} from "../../redux/user/user.selectors"; -import { connect } from "react-redux"; -import { createStructuredSelector } from "reselect"; -import { selectBodyshop } from "../../redux/user/user.selectors"; const ProdTemplates = TemplateList("production"); const { - production_by_technician_one, - production_by_category_one, - production_by_repair_status_one, + production_by_technician_one, + production_by_category_one, + production_by_repair_status_one, } = TemplateList("special"); const mapStateToProps = createStructuredSelector({ - bodyshop: selectBodyshop, + bodyshop: selectBodyshop, }); const mapDispatchToProps = (dispatch) => ({ - //setUserLanguage: language => dispatch(setUserLanguage(language)) + //setUserLanguage: language => dispatch(setUserLanguage(language)) }); export default connect( - mapStateToProps, - mapDispatchToProps + mapStateToProps, + mapDispatchToProps )(ProductionListPrint); -export function ProductionListPrint({ bodyshop }) { - const { t } = useTranslation(); - const [loading, setLoading] = useState(false); - const menu = { - items: [ - ...Object.keys(ProdTemplates).map((key) => ({ - key: key, - label: ProdTemplates[key].title, - })), - { - key: "production_by_technician_one", - label: t("reportcenter.templates.production_by_technician_one"), - children: bodyshop.employees - .filter((e) => e.active) - .map((e) => ({ - key: e.id, - label: `${e.first_name} ${e.last_name}`, - })), - }, - { - key: "production_by_category_one", - label: t("reportcenter.templates.production_by_category_one"), - children: bodyshop.md_categories.map((e) => ({ - key: e, - label: e, - })), - }, - { - key: "production_by_repair_status_one", - label: t("reportcenter.templates.production_by_repair_status_one"), - children: bodyshop.md_ro_statuses.production_statuses.map((e) => ({ - key: e, - label: e, - })), - }, - ], - onClick: async (e) => { - setLoading(true); - await GenerateDocument( - { - name: ProdTemplates[e.key].key, - // variables: { id: contract.id }, - }, - {}, - "p" - ); - setLoading(false); - }, - } - return ( - - - - ); +export function ProductionListPrint({bodyshop}) { + const {t} = useTranslation(); + const [loading, setLoading] = useState(false); + + const menu = { + items: [ + ...Object.keys(ProdTemplates).map((key) => { + return { + key: key, + label: ProdTemplates[key].title, + onClick: async () => { + setLoading(true); + await GenerateDocument( + { + name: ProdTemplates[key].key, + // variables: { id: contract.id }, + }, + {}, + "p" + ); + setLoading(false); + } + }; + }), + { + key: key, + label: t("reportcenter.templates.production_by_technician_one"), + children: bodyshop.employees + .filter((e) => e.active) + .map((e) => { + return { + key: e.id, + label: `${e.first_name} ${e.last_name}`, + onClick: async () => { + setLoading(true); + await GenerateDocument( + { + name: production_by_technician_one.key, + variables: {id: e.id}, + }, + {}, + "p" + ); + setLoading(false); + } + }; + }) + }, + { + label: t("reportcenter.templates.production_by_category_one"), + children: bodyshop.md_categories.map((e) => { + return { + key: e, + label: e, + onClick: async () => { + setLoading(true); + await GenerateDocument( + { + name: production_by_category_one.key, + variables: {category: e}, + }, + {}, + "p" + ); + setLoading(false); + } + }; + }) + }, + { + label: t("reportcenter.templates.production_by_repair_status_one"), + children: bodyshop.md_ro_statuses.production_statuses.map((e) => { + return { + key: e, + label: e, + onClick: async () => { + setLoading(true); + await GenerateDocument( + { + name: production_by_repair_status_one.key, + variables: {status: e}, + }, + {}, + "p" + ); + setLoading(false); + } + }; + }) + } + ] + }; + + return ( + + + ); } diff --git a/client/src/graphql/courtesy-car.queries.js b/client/src/graphql/courtesy-car.queries.js index a5bcbea55..4f7bcd0ca 100644 --- a/client/src/graphql/courtesy-car.queries.js +++ b/client/src/graphql/courtesy-car.queries.js @@ -30,15 +30,15 @@ export const QUERY_AVAILABLE_CC = gql` fuel id make - model - plate - status - year - dailycost mileage + model notes nextservicekm nextservicedate + plate + readiness + status + year } } `; @@ -68,19 +68,20 @@ export const QUERY_ALL_CC = gql` insuranceexpires leaseenddate make + mileage model nextservicedate nextservicekm notes plate purchasedate + readiness registrationexpires serviceenddate servicestartdate status vin year - mileage cccontracts( where: { status: { _eq: "contracts.status.out" } } order_by: { contract_date: desc } @@ -90,10 +91,10 @@ export const QUERY_ALL_CC = gql` scheduledreturn job { id - ro_number ownr_fn ownr_ln ownr_co_nm + ro_number } } } @@ -119,19 +120,20 @@ export const QUERY_CC_BY_PK = gql` insuranceexpires leaseenddate make + mileage model nextservicedate nextservicekm notes plate purchasedate + readiness registrationexpires serviceenddate servicestartdate status vin year - mileage cccontracts_aggregate { aggregate { count(distinct: true) @@ -139,21 +141,20 @@ export const QUERY_CC_BY_PK = gql` } cccontracts(offset: $offset, limit: $limit, order_by: $order) { agreementnumber + driver_fn + driver_ln id - status - start - scheduledreturn kmstart kmend - driver_ln - driver_fn + scheduledreturn + start + status job { - ro_number - + id ownr_ln ownr_fn ownr_co_nm - id + ro_number } } } diff --git a/client/src/pages/courtesy-car-detail/courtesy-car-detail.page.container.jsx b/client/src/pages/courtesy-car-detail/courtesy-car-detail.page.container.jsx index ba2bb5501..80d357616 100644 --- a/client/src/pages/courtesy-car-detail/courtesy-car-detail.page.container.jsx +++ b/client/src/pages/courtesy-car-detail/courtesy-car-detail.page.container.jsx @@ -1,6 +1,6 @@ import { useMutation, useQuery } from "@apollo/client"; import { Form, notification } from "antd"; -import dayjs from "../../utils/day"; +import dayjs from "dayjs"; import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; @@ -14,6 +14,7 @@ import { setSelectedHeader, } from "../../redux/application/application.actions"; import { CreateRecentItem } from "../../utils/create-recent-item"; +import UndefinedToNull from "./../../utils/undefinedtonull"; import CourtesyCarDetailPageComponent from "./courtesy-car-detail.page.component"; import NotFound from "../../components/not-found/not-found.component"; import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component"; @@ -112,7 +113,10 @@ export function CourtesyCarDetailPageContainer({ setSaveLoading(true); const result = await updateCourtesyCar({ - variables: { cc: { ...values }, ccId: ccId }, + variables: { + cc: { ...UndefinedToNull(values, ["readiness"]) }, + ccId: ccId, + }, refetchQueries: ["QUERY_CC_BY_PK"], awaitRefetchQueries: true, }); diff --git a/client/src/pages/jobs-create/jobs-create.container.jsx b/client/src/pages/jobs-create/jobs-create.container.jsx index 15af524ed..dfe83358c 100644 --- a/client/src/pages/jobs-create/jobs-create.container.jsx +++ b/client/src/pages/jobs-create/jobs-create.container.jsx @@ -1,6 +1,6 @@ -import _ from "lodash"; import { useLazyQuery, useMutation } from "@apollo/client"; import { Form, notification } from "antd"; +import _ from "lodash"; import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; @@ -90,6 +90,7 @@ function JobsCreateContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) { {}, values, { date_open: new Date() }, + { date_estimated: new Date() }, { vehicle: state.vehicle.selectedid || state.vehicle.none diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index b96b555db..09798f0a5 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -214,6 +214,7 @@ "new": "New Bill", "noneselected": "No bill selected.", "onlycmforinvoiced": "Only credit memos can be entered for any Job that has been invoiced, exported, or voided.", + "printlabels": "Print Labels", "retailtotal": "Bills Retail Total", "savewithdiscrepancy": "You are about to save this bill with a discrepancy. The system will continue to use the calculated amount using the bill lines. Press cancel to return to the bill.", "state_tax": "Provincial/State Tax", @@ -785,6 +786,7 @@ "notes": "Notes", "plate": "Plate Number", "purchasedate": "Purchase Date", + "readiness": "Readiness", "registrationexpires": "Registration Expires On", "serviceenddate": "Usage End Date", "servicestartdate": "Usage Start Date", @@ -821,6 +823,10 @@ }, "successes": { "saved": "Courtesy Car saved successfully." + }, + "readiness": { + "notready": "Not Ready", + "ready": "Ready" } }, "csi": { diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index f68cf4a41..da9f6b4e0 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -214,6 +214,7 @@ "new": "", "noneselected": "", "onlycmforinvoiced": "", + "printlabels": "", "retailtotal": "", "savewithdiscrepancy": "", "state_tax": "", @@ -785,6 +786,7 @@ "notes": "", "plate": "", "purchasedate": "", + "readiness": "", "registrationexpires": "", "serviceenddate": "", "servicestartdate": "", @@ -821,6 +823,10 @@ }, "successes": { "saved": "" + }, + "readiness": { + "notready": "", + "ready": "" } }, "csi": { diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index d0e44b704..a4c1dc686 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -214,6 +214,7 @@ "new": "", "noneselected": "", "onlycmforinvoiced": "", + "printlabels": "", "retailtotal": "", "savewithdiscrepancy": "", "state_tax": "", @@ -785,6 +786,7 @@ "notes": "", "plate": "", "purchasedate": "", + "readiness": "", "registrationexpires": "", "serviceenddate": "", "servicestartdate": "", @@ -821,6 +823,10 @@ }, "successes": { "saved": "" + }, + "readiness": { + "notready": "", + "ready": "" } }, "csi": { diff --git a/hasura/metadata/tables.yaml b/hasura/metadata/tables.yaml index d94a97af0..216ac8c48 100644 --- a/hasura/metadata/tables.yaml +++ b/hasura/metadata/tables.yaml @@ -1388,60 +1388,62 @@ - active: _eq: true columns: - - id - - created_at - - updated_at - bodyshopid - - make - - model - - year - - plate - color - - vin - - fleetnumber - - purchasedate - - servicestartdate - - serviceenddate - - leaseenddate - - status - - nextservicekm - - nextservicedate - - damage - - notes - - fuel - - registrationexpires - - insuranceexpires + - created_at - dailycost + - damage + - fleetnumber + - fuel + - id + - insuranceexpires + - leaseenddate + - make - mileage + - model + - nextservicedate + - nextservicekm + - notes + - plate + - purchasedate + - readiness + - registrationexpires + - serviceenddate + - servicestartdate + - status + - updated_at + - vin + - year select_permissions: - role: user permission: columns: + - bodyshopid + - color + - created_at + - dailycost + - damage + - fleetnumber + - fuel + - id - insuranceexpires - leaseenddate + - make + - mileage + - model - nextservicedate + - nextservicekm + - notes + - plate - purchasedate + - readiness - registrationexpires - serviceenddate - servicestartdate - - dailycost - - fuel - - mileage - - nextservicekm - - color - - damage - - fleetnumber - - make - - model - - notes - - plate - status + - updated_at - vin - year - - created_at - - updated_at - - bodyshopid - - id filter: bodyshop: associations: @@ -1456,31 +1458,32 @@ - role: user permission: columns: + - bodyshopid + - color + - created_at + - dailycost + - damage + - fleetnumber + - fuel + - id - insuranceexpires - leaseenddate + - make + - mileage + - model - nextservicedate + - nextservicekm + - notes + - plate - purchasedate + - readiness - registrationexpires - serviceenddate - servicestartdate - - dailycost - - fuel - - mileage - - nextservicekm - - color - - damage - - fleetnumber - - make - - model - - notes - - plate - status + - updated_at - vin - year - - created_at - - updated_at - - bodyshopid - - id filter: bodyshop: associations: diff --git a/hasura/migrations/1703706449547_alter_table_public_courtesycars_add_column_readiness/down.sql b/hasura/migrations/1703706449547_alter_table_public_courtesycars_add_column_readiness/down.sql new file mode 100644 index 000000000..5e741dcc7 --- /dev/null +++ b/hasura/migrations/1703706449547_alter_table_public_courtesycars_add_column_readiness/down.sql @@ -0,0 +1,4 @@ +-- Could not auto-generate a down migration. +-- Please write an appropriate down migration for the SQL below: +-- alter table "public"."courtesycars" add column "readiness" text +-- null; diff --git a/hasura/migrations/1703706449547_alter_table_public_courtesycars_add_column_readiness/up.sql b/hasura/migrations/1703706449547_alter_table_public_courtesycars_add_column_readiness/up.sql new file mode 100644 index 000000000..4f5339ede --- /dev/null +++ b/hasura/migrations/1703706449547_alter_table_public_courtesycars_add_column_readiness/up.sql @@ -0,0 +1,2 @@ +alter table "public"."courtesycars" add column "readiness" text + null;