diff --git a/client/src/components/schedule-calendar-wrapper/schedule-calendar-util.js b/client/src/components/schedule-calendar-wrapper/schedule-calendar-util.js new file mode 100644 index 000000000..e03b48ba0 --- /dev/null +++ b/client/src/components/schedule-calendar-wrapper/schedule-calendar-util.js @@ -0,0 +1,29 @@ +import moment from "moment"; + +export function getRange(dateParam, viewParam) { + let start, end; + let date = dateParam || new Date(); + let view = viewParam || "week"; + // if view is day: from moment(date).startOf('day') to moment(date).endOf('day'); + if (view === "day") { + start = moment(date).startOf("day"); + end = moment(date).endOf("day"); + } + // if view is week: from moment(date).startOf('isoWeek') to moment(date).endOf('isoWeek'); + else if (view === "week") { + start = moment(date).startOf("week"); + end = moment(date).endOf("week"); + } + //if view is month: from moment(date).startOf('month').subtract(7, 'days') to moment(date).endOf('month').add(7, 'days'); i do additional 7 days math because you can see adjacent weeks on month view (that is the way how i generate my recurrent events for the Big Calendar, but if you need only start-end of month - just remove that math); + else if (view === "month") { + start = moment(date).startOf("month").subtract(7, "days"); + end = moment(date).endOf("month").add(7, "days"); + } + // if view is agenda: from moment(date).startOf('day') to moment(date).endOf('day').add(1, 'month'); + else if (view === "agenda") { + start = moment(date).startOf("day"); + end = moment(date).endOf("day").add(1, "month"); + } + + return { start, end }; +} diff --git a/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx b/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx index 4e9bfd975..70b36d7ab 100644 --- a/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx +++ b/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx @@ -1,9 +1,9 @@ +import { Progress } from "antd"; import moment from "moment"; import queryString from "query-string"; import React from "react"; import { Calendar, momentLocalizer } from "react-big-calendar"; import { useHistory, useLocation } from "react-router-dom"; -import DateCellWrapper from "../schedule-datecellwrapper/schedule-datecellwrapper.component"; import Event from "../schedule-event/schedule-event.container"; //import "react-big-calendar/lib/css/react-big-calendar.css"; import "./schedule-calendar.styles.scss"; @@ -14,6 +14,7 @@ export default function ScheduleCalendarWrapperComponent({ data, refetch, defaultView, + setDateRangeCallback, ...otherProps }) { const search = queryString.parse(useLocation().search); @@ -22,12 +23,19 @@ export default function ScheduleCalendarWrapperComponent({ return ( { search.date = date.toISOString().substr(0, 10); history.push({ search: queryString.stringify(search) }); }} + onRangeChange={(start, end) => { + if (setDateRangeCallback) setDateRangeCallback({ start, end }); + }} + onView={(view) => { + search.view = view; + history.push({ search: queryString.stringify(search) }); + }} step={30} showMultiDayTimes localizer={localizer} @@ -35,7 +43,15 @@ export default function ScheduleCalendarWrapperComponent({ max={new Date("2020-01-01T20:00:00")} components={{ event: (e) => Event({ event: e.event, refetch: refetch }), - dateCellWrapper: DateCellWrapper, + header: (props) => { + return ( + +
{props.label}
+ +
+ ); + }, + //dateCellWrapper: DateCellWrapper, }} {...otherProps} /> diff --git a/client/src/components/schedule-calendar/schedule-calendar.component.jsx b/client/src/components/schedule-calendar/schedule-calendar.component.jsx index a1678a711..50127ae6d 100644 --- a/client/src/components/schedule-calendar/schedule-calendar.component.jsx +++ b/client/src/components/schedule-calendar/schedule-calendar.component.jsx @@ -8,16 +8,15 @@ import { setModalContext } from "../../redux/modals/modals.actions"; import ScheduleCalendarWrapperComponent from "../schedule-calendar-wrapper/scheduler-calendar-wrapper.component"; import ScheduleModal from "../schedule-job-modal/schedule-job-modal.container"; - -const mapDispatchToProps = dispatch => ({ - setScheduleContext: context => - dispatch(setModalContext({ context: context, modal: "schedule" })) +const mapDispatchToProps = (dispatch) => ({ + setScheduleContext: (context) => + dispatch(setModalContext({ context: context, modal: "schedule" })), }); export function ScheduleCalendarComponent({ data, refetch, - setScheduleContext + setScheduleContext, }) { const { t } = useTranslation(); @@ -36,8 +35,8 @@ export function ScheduleCalendarComponent({ setScheduleContext({ actions: { refetch: refetch }, context: { - jobId: null - } + jobId: null, + }, }); }} > @@ -46,11 +45,7 @@ export function ScheduleCalendarComponent({ - + ); } diff --git a/client/src/components/schedule-calendar/schedule-calendar.container.jsx b/client/src/components/schedule-calendar/schedule-calendar.container.jsx index a518dca98..9750d6ad7 100644 --- a/client/src/components/schedule-calendar/schedule-calendar.container.jsx +++ b/client/src/components/schedule-calendar/schedule-calendar.container.jsx @@ -1,13 +1,33 @@ import { useQuery } from "@apollo/react-hooks"; +import queryString from "query-string"; import React from "react"; +import { useLocation } from "react-router-dom"; import { QUERY_ALL_ACTIVE_APPOINTMENTS } from "../../graphql/appointments.queries"; import AlertComponent from "../alert/alert.component"; import LoadingSpinner from "../loading-spinner/loading-spinner.component"; +import { getRange } from "../schedule-calendar-wrapper/schedule-calendar-util"; import ScheduleCalendarComponent from "./schedule-calendar.component"; +import { calculateScheduleLoad } from "../../redux/application/application.actions"; +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +const mapStateToProps = createStructuredSelector({ + //currentUser: selectCurrentUser +}); +const mapDispatchToProps = (dispatch) => ({ + calculateScheduleLoad: (endDate) => dispatch(calculateScheduleLoad(endDate)), +}); -export default function ScheduleCalendarContainer() { +export function ScheduleCalendarContainer({ calculateScheduleLoad }) { + const search = queryString.parse(useLocation().search); + + const { date, view } = search; + const range = getRange(date, view); const { loading, error, data, refetch } = useQuery( - QUERY_ALL_ACTIVE_APPOINTMENTS + QUERY_ALL_ACTIVE_APPOINTMENTS, + { + variables: { start: range.start.toDate(), end: range.end.toDate() }, + skip: !!!range.start || !!!range.end, + } ); if (loading) return ; @@ -22,10 +42,32 @@ export default function ScheduleCalendarContainer() { ); }); + console.log("ScheduleCalendarContainer -> normalizedData", normalizedData); + normalizedData.push({ + id: 1, + title: "All day event", + allDay: true, + isintake: false, + start: new Date(), + end: new Date(), + }); return ( - + + + + ); } +export default connect( + mapStateToProps, + mapDispatchToProps +)(ScheduleCalendarContainer); diff --git a/client/src/components/schedule-datecellwrapper/schedule-datecellwrapper.component.jsx b/client/src/components/schedule-datecellwrapper/schedule-datecellwrapper.component.jsx index 69d9e2f5d..bdc31a4a2 100644 --- a/client/src/components/schedule-datecellwrapper/schedule-datecellwrapper.component.jsx +++ b/client/src/components/schedule-datecellwrapper/schedule-datecellwrapper.component.jsx @@ -7,7 +7,7 @@ export default function ScheduleDateCellWrapper(dateCellWrapperProps) { display: "flex", flex: 1, borderLeft: "1px solid #DDD", - backgroundColor: "#fff" + backgroundColor: "#fff", }; return (
diff --git a/client/src/components/schedule-event/schedule-event.component.jsx b/client/src/components/schedule-event/schedule-event.component.jsx index 54cf8bbbf..e9021f9b6 100644 --- a/client/src/components/schedule-event/schedule-event.component.jsx +++ b/client/src/components/schedule-event/schedule-event.component.jsx @@ -1,5 +1,5 @@ import React from "react"; -import { Popover, Button } from "antd"; +import { Popover, Button, Progress } from "antd"; import CurrencyFormatter from "../../utils/CurrencyFormatter"; import PhoneFormatter from "../../utils/PhoneFormatter"; import { Link } from "react-router-dom"; @@ -13,30 +13,30 @@ export default function ScheduleEventComponent({ event, handleCancel }) { {event.title} ) : (
- {`${(event.job && event.job.ownr_fn) || ""} ${(event.job && - event.job.ownr_ln) || - ""}`} + {`${(event.job && event.job.ownr_fn) || ""} ${ + (event.job && event.job.ownr_ln) || "" + }`} - {`${(event.job && event.job.v_model_yr) || - ""} ${(event.job && event.job.v_make_desc) || - ""} ${(event.job && event.job.v_model_desc) || ""}`} + {`${(event.job && event.job.v_model_yr) || ""} ${ + (event.job && event.job.v_make_desc) || "" + } ${(event.job && event.job.v_model_desc) || ""}`}
)} {event.job ? (
-
{`${t("jobs.fields.ro_number")}: ${(event.job && - event.job.ro_number) || - ""}`}
+
{`${t("jobs.fields.ro_number")}: ${ + (event.job && event.job.ro_number) || "" + }`}
{t("jobs.fields.clm_total")}: {(event.job && event.job.clm_total) || ""}
-
{`${t("jobs.fields.clm_no")}: ${(event.job && - event.job.clm_no) || - ""}`}
+
{`${t("jobs.fields.clm_no")}: ${ + (event.job && event.job.clm_no) || "" + }`}
{t("jobs.fields.ownr_ea")}:{(event.job && event.job.ownr_ea) || ""}
@@ -76,26 +76,31 @@ export default function ScheduleEventComponent({ event, handleCancel }) {
); + const RegularEvent = event.isintake ? ( +
+ {`${(event.job && event.job.ownr_fn) || ""} ${ + (event.job && event.job.ownr_ln) || "" + }`} + + {`${(event.job && event.job.v_model_yr) || ""} ${ + (event.job && event.job.v_make_desc) || "" + } ${(event.job && event.job.v_model_desc) || ""}`} + +
+ ) : ( +
+ {`${event.title || ""}`} +
+ ); + + const Load = ( +
+ +
+ ); return ( -
- {event.isintake ? ( -
- {`${(event.job && event.job.ownr_fn) || ""} ${(event.job && - event.job.ownr_ln) || - ""}`} - - {`${(event.job && event.job.v_model_yr) || - ""} ${(event.job && event.job.v_make_desc) || - ""} ${(event.job && event.job.v_model_desc) || ""}`} - -
- ) : ( -
- {`${event.title || ""}`} -
- )} -
+
{event.allDay ? Load : RegularEvent}
); } diff --git a/client/src/components/schedule-existing-appointments-list/schedule-existing-appointments-list.component.jsx b/client/src/components/schedule-existing-appointments-list/schedule-existing-appointments-list.component.jsx index 4435030d9..0d03b913d 100644 --- a/client/src/components/schedule-existing-appointments-list/schedule-existing-appointments-list.component.jsx +++ b/client/src/components/schedule-existing-appointments-list/schedule-existing-appointments-list.component.jsx @@ -6,7 +6,7 @@ import { useTranslation } from "react-i18next"; import { DateTimeFormatter } from "../../utils/DateFormatter"; export default function ScheduleExistingAppointmentsList({ - existingAppointments + existingAppointments, }) { const { t } = useTranslation(); if (existingAppointments.loading) return ; @@ -22,22 +22,26 @@ export default function ScheduleExistingAppointmentsList({
{t("appointments.labels.priorappointments")} - {existingAppointments.data.appointments.map(item => { - return ( - - {item.canceled - ? t("appointments.labels.cancelledappointment") - : item.arrived - ? t("appointments.labels.arrivedon") - : t("appointments.labels.scheduledfor")} + {existingAppointments.data + ? existingAppointments.data.appointments.map((item) => { + return ( + + {item.canceled + ? t("appointments.labels.cancelledappointment") + : item.arrived + ? t("appointments.labels.arrivedon") + : t("appointments.labels.scheduledfor")} - {item.start} - - ); - })} + {item.start} + + ); + }) + : null}
); diff --git a/client/src/components/schedule-job-modal/schedule-job-modal.container.jsx b/client/src/components/schedule-job-modal/schedule-job-modal.container.jsx index 0b8c008f1..3d59d9b7d 100644 --- a/client/src/components/schedule-job-modal/schedule-job-modal.container.jsx +++ b/client/src/components/schedule-job-modal/schedule-job-modal.container.jsx @@ -48,7 +48,7 @@ export function ScheduleJobModalContainer({ const existingAppointments = useQuery(QUERY_APPOINTMENTS_BY_JOBID, { variables: { jobid: jobId }, fetchPolicy: "network-only", - skip: !visible, + skip: !visible || !!!jobId, }); //TODO Customize the amount of minutes it will add. diff --git a/client/src/graphql/appointments.queries.js b/client/src/graphql/appointments.queries.js index 79aca8222..6d9afd2bc 100644 --- a/client/src/graphql/appointments.queries.js +++ b/client/src/graphql/appointments.queries.js @@ -1,8 +1,17 @@ import gql from "graphql-tag"; export const QUERY_ALL_ACTIVE_APPOINTMENTS = gql` - query QUERY_ALL_ACTIVE_APPOINTMENTS { - appointments(where: { canceled: { _eq: false } }) { + query QUERY_ALL_ACTIVE_APPOINTMENTS( + $start: timestamptz! + $end: timestamptz! + ) { + appointments( + where: { + canceled: { _eq: false } + end: { _lte: $end } + start: { _gte: $start } + } + ) { start id end @@ -11,18 +20,16 @@ export const QUERY_ALL_ACTIVE_APPOINTMENTS = gql` job { ro_number ownr_ln + ownr_co_nm ownr_fn ownr_ph1 ownr_ea clm_total id clm_no - vehicle { - id - v_model_yr - v_make_desc - v_model_desc - } + v_model_yr + v_make_desc + v_model_desc } } } @@ -94,3 +101,53 @@ export const QUERY_APPOINTMENTS_BY_JOBID = gql` } } `; +export const QUERY_SCHEDULE_LOAD_DATA = gql` + query QUERY_SCHEDULE_LOAD_DATA($start: timestamptz!, $end: timestamptz!) { + productionview_aggregate { + aggregate { + sum { + larhrs + labhrs + } + } + } + compJobs: jobs( + where: { scheduled_completion: { _gte: $start, _lte: $end } } + ) { + id + scheduled_completion + labhrs: joblines_aggregate(where: { mod_lbr_ty: { _eq: "LAB" } }) { + aggregate { + sum { + mod_lb_hrs + } + } + } + larhrs: joblines_aggregate(where: { mod_lbr_ty: { _eq: "LAR" } }) { + aggregate { + sum { + mod_lb_hrs + } + } + } + } + arrJobs: jobs(where: { scheduled_in: { _gte: $start, _lte: $end } }) { + id + scheduled_in + labhrs: joblines_aggregate(where: { mod_lbr_ty: { _eq: "LAB" } }) { + aggregate { + sum { + mod_lb_hrs + } + } + } + larhrs: joblines_aggregate(where: { mod_lbr_ty: { _eq: "LAR" } }) { + aggregate { + sum { + mod_lb_hrs + } + } + } + } + } +`; diff --git a/client/src/redux/application/application.actions.js b/client/src/redux/application/application.actions.js index bafacf052..958abcc77 100644 --- a/client/src/redux/application/application.actions.js +++ b/client/src/redux/application/application.actions.js @@ -12,4 +12,9 @@ export const endLoading = (options) => ({ export const setBreadcrumbs = (breadcrumbs) => ({ type: ApplicationActionTypes.SET_BREAD_CRUMBS, payload: breadcrumbs, -}); \ No newline at end of file +}); + +export const calculateScheduleLoad = (rangeEnd) => ({ + type: ApplicationActionTypes.CALCULATE_SCHEDULE_LOAD, + payload: rangeEnd, +}); diff --git a/client/src/redux/application/application.reducer.js b/client/src/redux/application/application.reducer.js index 9bb60326f..15753a113 100644 --- a/client/src/redux/application/application.reducer.js +++ b/client/src/redux/application/application.reducer.js @@ -3,10 +3,43 @@ import ApplicationActionTypes from "./application.types"; const INITIAL_STATE = { loading: false, breadcrumbs: [], + scheduleLoad: { + load: [], + calculating: false, + error: null, + }, }; const applicationReducer = (state = INITIAL_STATE, action) => { switch (action.type) { + case ApplicationActionTypes.SET_BREAD_CRUMBS: + return { + ...state, + breadcrumbs: action.payload, + }; + case ApplicationActionTypes.CALCULATE_SCHEDULE_LOAD: + return { + ...state, + scheduleLoad: { ...state.scheduleLoad, calculating: true, error: null }, + }; + case ApplicationActionTypes.CALCULATE_SCHEDULE_LOAD_SUCCESS: + return { + ...state, + scheduleLoad: { + ...state.scheduleLoad, + load: action.payload, + calculating: false, + }, + }; + case ApplicationActionTypes.CALCULATE_SCHEDULE_LOAD_FAILURE: + return { + ...state, + scheduleLoad: { + ...state.scheduleLoad, + calculating: false, + error: action.payload, + }, + }; case ApplicationActionTypes.START_LOADING: return { ...state, @@ -17,11 +50,7 @@ const applicationReducer = (state = INITIAL_STATE, action) => { ...state, loading: false, }; - case ApplicationActionTypes.SET_BREAD_CRUMBS: - return { - ...state, - breadcrumbs: action.payload, - }; + default: return state; } diff --git a/client/src/redux/application/application.sagas.js b/client/src/redux/application/application.sagas.js index 9deb690b2..b11e65448 100644 --- a/client/src/redux/application/application.sagas.js +++ b/client/src/redux/application/application.sagas.js @@ -1,47 +1,87 @@ -import { all } from "redux-saga/effects"; +import { all, takeLatest, call } from "redux-saga/effects"; +import ApplicationActionTypes from "./application.types"; +import { client } from "../../App/App.container"; +import { QUERY_SCHEDULE_LOAD_DATA } from "../../graphql/appointments.queries"; +import moment from "moment"; -// export function* onSendEmail() { -// yield takeLatest(EmailActionTypes.SEND_EMAIL, sendEmail); -// } -// export function* sendEmail(payload) { -// try { -// console.log("Sending thta email", payload); -// axios.post("/sendemail", payload).then(response => { -// console.log(JSON.stringify(response)); -// put(sendEmailSuccess()); -// }); -// } catch (error) { -// console.log("Error in sendEmail saga."); -// yield put(sendEmailFailure(error.message)); -// } -// } +export function* onCalculateScheduleLoad() { + yield takeLatest( + ApplicationActionTypes.CALCULATE_SCHEDULE_LOAD, + calculateScheduleLoad + ); +} +export function* calculateScheduleLoad({ payload: end }) { + const today = moment(new Date()).startOf("day"); + try { + const result = yield client.query({ + query: QUERY_SCHEDULE_LOAD_DATA, + variables: { + start: today, + end: end, + }, + }); -// export function* onSendEmailSuccess() { -// yield takeLatest(EmailActionTypes.SEND_EMAIL_SUCCESS, sendEmailSuccessSaga); -// } -// export function* sendEmailSuccessSaga() { -// try { -// console.log("Send email success."); -// } catch (error) { -// console.log("Error in sendEmailSuccess saga."); -// yield put(sendEmailFailure(error.message)); -// } -// } + const productionHoursTotal = + result.data.productionview_aggregate.aggregate.sum.larhrs + + result.data.productionview_aggregate.aggregate.sum.labhrs; -// export function* onRenderTemplate() { -// yield takeLatest(ApplicationActionTypes.RENDER_TEMPLATE, renderTemplate); -// } -// export function* renderTemplate({ payload: template }) { -// try { -// yield console.log("Render Template Saga => template", template); -// } catch (error) { -// console.log("Error in sendEmailFailure saga.", error.message); -// } -// } + const range = Math.round(moment.duration(end.diff(today)).asDays()); + let load = {}; + + //Start from today and go until the range. + // for (var day = 0; day < range; day++) { + // let workingDate = today.add(day, "days"); + // console.log( + // "function*calculateScheduleLoad -> workingDate", + // workingDate.toLocaleString() + // ); + // } + const { arrJobs, compJobs } = result.data; + + arrJobs.forEach((item) => { + const itemDate = moment(item.scheduled_in).toISOString().substr(0, 10); + if (!!load[itemDate]) { + load[itemDate].hoursIn = + (load[itemDate].hoursIn || 0) + + item.labhrs.aggregate.sum.mod_lb_hrs + + item.larhrs.aggregate.sum.mod_lb_hrs; + } else { + load[itemDate] = { + hoursIn: + item.labhrs.aggregate.sum.mod_lb_hrs + + item.larhrs.aggregate.sum.mod_lb_hrs, + }; + } + }); + + compJobs.forEach((item) => { + const itemDate = moment(item.scheduled_completion) + .toISOString() + .substr(0, 10); + if (!!load[itemDate]) { + load[itemDate].hoursOut = + (load[itemDate].hoursOut || 0) + + item.labhrs.aggregate.sum.mod_lb_hrs + + item.larhrs.aggregate.sum.mod_lb_hrs; + } else { + load[itemDate] = { + hoursOut: + item.labhrs.aggregate.sum.mod_lb_hrs + + item.larhrs.aggregate.sum.mod_lb_hrs, + }; + } + }); + + console.log("load", load); + } catch (error) { + //console.log("Error in sendEmailFailure saga.", error.message); + console.log("error", error); + } +} export function* applicationSagas() { yield all([ - // call(onSendEmail), + call(onCalculateScheduleLoad), // call(onSendEmailFailure), // call(onSendEmailSuccess) //call(onRenderTemplate), diff --git a/client/src/redux/application/application.selectors.js b/client/src/redux/application/application.selectors.js index 2b931b789..5558f2cc5 100644 --- a/client/src/redux/application/application.selectors.js +++ b/client/src/redux/application/application.selectors.js @@ -11,3 +11,13 @@ export const selectBreadcrumbs = createSelector( [selectApplication], (application) => application.breadcrumbs ); + +export const selectScheduleLoad = createSelector( + [selectApplication], + (application) => application.scheduleLoad.load +); + +export const selectScheduleLoadCalculating = createSelector( + [selectApplication], + (application) => application.scheduleLoad.calculating +); diff --git a/client/src/redux/application/application.types.js b/client/src/redux/application/application.types.js index 520db6749..be48e6101 100644 --- a/client/src/redux/application/application.types.js +++ b/client/src/redux/application/application.types.js @@ -2,5 +2,8 @@ const ApplicationActionTypes = { START_LOADING: "START_LOADING", END_LOADING: "END_LOADING", SET_BREAD_CRUMBS: "SET_BREAD_CRUMBS", + CALCULATE_SCHEDULE_LOAD: "CALCULATE_SCHEDULE_LOAD", + CALCULATE_SCHEDULE_LOAD_SUCCESS: "CALCULATE_SCHEDULE_LOAD_SUCCESS", + CALCULATE_SCHEDULE_LOAD_FAILURE: "CALCULATE_SCHEDULE_LOAD_FAILURE", }; export default ApplicationActionTypes; diff --git a/hasura/migrations/1588963534664_update_permission_user_public_table_productionview/down.yaml b/hasura/migrations/1588963534664_update_permission_user_public_table_productionview/down.yaml new file mode 100644 index 000000000..149d9a760 --- /dev/null +++ b/hasura/migrations/1588963534664_update_permission_user_public_table_productionview/down.yaml @@ -0,0 +1,49 @@ +- args: + role: user + table: + name: productionview + schema: public + type: drop_select_permission +- args: + permission: + allow_aggregations: false + columns: + - id + - status + - ro_number + - est_number + - ownr_fn + - ownr_ln + - v_model_yr + - v_model_desc + - clm_no + - v_make_desc + - v_color + - plate_no + - actual_in + - scheduled_completion + - scheduled_delivery + - ins_co_nm + - clm_total + - ownr_ph1 + - special_coverage_policy + - production_vars + - labhrs + - larhrs + - shopid + - partcount + computed_fields: [] + filter: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + role: user + table: + name: productionview + schema: public + type: create_select_permission diff --git a/hasura/migrations/1588963534664_update_permission_user_public_table_productionview/up.yaml b/hasura/migrations/1588963534664_update_permission_user_public_table_productionview/up.yaml new file mode 100644 index 000000000..846706108 --- /dev/null +++ b/hasura/migrations/1588963534664_update_permission_user_public_table_productionview/up.yaml @@ -0,0 +1,49 @@ +- args: + role: user + table: + name: productionview + schema: public + type: drop_select_permission +- args: + permission: + allow_aggregations: true + columns: + - id + - status + - ro_number + - est_number + - ownr_fn + - ownr_ln + - v_model_yr + - v_model_desc + - clm_no + - v_make_desc + - v_color + - plate_no + - actual_in + - scheduled_completion + - scheduled_delivery + - ins_co_nm + - clm_total + - ownr_ph1 + - special_coverage_policy + - production_vars + - labhrs + - larhrs + - shopid + - partcount + computed_fields: [] + filter: + bodyshop: + associations: + _and: + - user: + authid: + _eq: X-Hasura-User-Id + - active: + _eq: true + role: user + table: + name: productionview + schema: public + type: create_select_permission diff --git a/hasura/migrations/metadata.yaml b/hasura/migrations/metadata.yaml index 7a4963f80..03f57ab22 100644 --- a/hasura/migrations/metadata.yaml +++ b/hasura/migrations/metadata.yaml @@ -2978,6 +2978,7 @@ tables: _eq: X-Hasura-User-Id - active: _eq: true + allow_aggregations: true - table: schema: public name: templates