diff --git a/backend/src/db/api/job_logs.js b/backend/src/db/api/job_logs.js index 63273c1..c781703 100644 --- a/backend/src/db/api/job_logs.js +++ b/backend/src/db/api/job_logs.js @@ -90,6 +90,10 @@ module.exports = class Job_logsDBApi { transaction, }); + await job_logs.setWorkersCompClass( data.workersCompClass || null, { + transaction, + }); + @@ -248,6 +252,15 @@ module.exports = class Job_logsDBApi { ); } + if (data.workersCompClass !== undefined) { + await job_logs.setWorkersCompClass( + + data.workersCompClass, + + { transaction } + ); + } + @@ -356,6 +369,10 @@ module.exports = class Job_logsDBApi { transaction }); + output.workersCompClass = await job_logs.getWorkersCompClass({ + transaction + }); + return output; @@ -449,6 +466,21 @@ module.exports = class Job_logsDBApi { } : {}, }, + + { + model: db.workers_comp_classes, + as: 'workersCompClass', + where: filter.workersCompClass ? { + [Op.or]: [ + { id: { [Op.in]: filter.workersCompClass.split('|').map(term => Utils.uuid(term)) } }, + { + name: { + [Op.or]: filter.workersCompClass.split('|').map(term => ({ [Op.iLike]: `%${term}%` })) + } + }, + ] + } : {}, + }, diff --git a/backend/src/db/api/workers_comp_classes.js b/backend/src/db/api/workers_comp_classes.js index fcbf77c..2eb148e 100644 --- a/backend/src/db/api/workers_comp_classes.js +++ b/backend/src/db/api/workers_comp_classes.js @@ -1,18 +1,12 @@ - const db = require('../models'); const FileDBApi = require('./file'); const crypto = require('crypto'); const Utils = require('../utils'); - - const Sequelize = db.Sequelize; const Op = Sequelize.Op; module.exports = class Workers_comp_classesDBApi { - - - static async create(data, options) { const currentUser = (options && options.currentUser) || { id: null }; const transaction = (options && options.transaction) || undefined; @@ -20,151 +14,33 @@ module.exports = class Workers_comp_classesDBApi { const workers_comp_classes = await db.workers_comp_classes.create( { id: data.id || undefined, - - name: data.name - || - null - , - - pay_method: data.pay_method - || - null - , - - hourly_rate: data.hourly_rate - || - null - , - - commission_rate: data.commission_rate - || - null - , - - active: data.active - || - false - - , - - description: data.description - || - null - , - - importHash: data.importHash || null, - createdById: currentUser.id, - updatedById: currentUser.id, - }, - { transaction }, - ); - - - - - - + name: data.name || null, + percentage: data.percentage !== undefined ? data.percentage : null, + importHash: data.importHash || null, + createdById: currentUser.id, + updatedById: currentUser.id, + }, + { transaction }, + ); return workers_comp_classes; } - - static async bulkImport(data, options) { - const currentUser = (options && options.currentUser) || { id: null }; - const transaction = (options && options.transaction) || undefined; - - // Prepare data - wrapping individual data transformations in a map() method - const workers_comp_classesData = data.map((item, index) => ({ - id: item.id || undefined, - - name: item.name - || - null - , - - pay_method: item.pay_method - || - null - , - - hourly_rate: item.hourly_rate - || - null - , - - commission_rate: item.commission_rate - || - null - , - - active: item.active - || - false - - , - - description: item.description - || - null - , - - importHash: item.importHash || null, - createdById: currentUser.id, - updatedById: currentUser.id, - createdAt: new Date(Date.now() + index * 1000), - })); - - // Bulk create items - const workers_comp_classes = await db.workers_comp_classes.bulkCreate(workers_comp_classesData, { transaction }); - - // For each item created, replace relation files - - - return workers_comp_classes; - } - - static async update(id, data, options) { + static async update(id, data, options) { const currentUser = (options && options.currentUser) || {id: null}; const transaction = (options && options.transaction) || undefined; - const workers_comp_classes = await db.workers_comp_classes.findByPk(id, {}, {transaction}); - - - const updatePayload = {}; if (data.name !== undefined) updatePayload.name = data.name; - - - if (data.pay_method !== undefined) updatePayload.pay_method = data.pay_method; - - - if (data.hourly_rate !== undefined) updatePayload.hourly_rate = data.hourly_rate === "" ? null : data.hourly_rate; - - - if (data.commission_rate !== undefined) updatePayload.commission_rate = data.commission_rate === "" ? null : data.commission_rate; - - - if (data.active !== undefined) updatePayload.active = data.active; - - - if (data.description !== undefined) updatePayload.description = data.description; - + if (data.percentage !== undefined) updatePayload.percentage = data.percentage === "" ? null : data.percentage; updatePayload.updatedById = currentUser.id; await workers_comp_classes.update(updatePayload, {transaction}); - - - - - - - - return workers_comp_classes; } @@ -193,7 +69,6 @@ module.exports = class Workers_comp_classesDBApi { } }); - return workers_comp_classes; } @@ -230,208 +105,44 @@ module.exports = class Workers_comp_classesDBApi { const output = workers_comp_classes.get({plain: true}); - - - - - - - - output.employee_workers_comp_classes_workers_comp_class = await workers_comp_classes.getEmployee_workers_comp_classes_workers_comp_class({ - transaction - }); - - - - output.job_logs_workers_comp_class = await workers_comp_classes.getJob_logs_workers_comp_class({ - transaction - }); - - - - - - - return output; } - static async findAll( - filter, - options - ) { + static async findAll(filter, options) { const limit = filter.limit || 0; let offset = 0; let where = {}; const currentPage = +filter.page; - - - - offset = currentPage * limit; - const orderBy = null; + const transaction = (options && options.transaction) || undefined; - const transaction = (options && options.transaction) || undefined; - - let include = [ - - - - ]; + let include = []; if (filter) { if (filter.id) { - where = { - ...where, - ['id']: Utils.uuid(filter.id), - }; + where = { ...where, ['id']: Utils.uuid(filter.id) }; } - - if (filter.name) { where = { ...where, - [Op.and]: Utils.ilike( - 'workers_comp_classes', - 'name', - filter.name, - ), + [Op.and]: Utils.ilike('workers_comp_classes', 'name', filter.name), }; } - - if (filter.description) { - where = { - ...where, - [Op.and]: Utils.ilike( - 'workers_comp_classes', - 'description', - filter.description, - ), - }; - } - - - - - - - if (filter.hourly_rateRange) { - const [start, end] = filter.hourly_rateRange; - - if (start !== undefined && start !== null && start !== '') { - where = { - ...where, - hourly_rate: { - ...where.hourly_rate, - [Op.gte]: start, - }, - }; - } - - if (end !== undefined && end !== null && end !== '') { - where = { - ...where, - hourly_rate: { - ...where.hourly_rate, - [Op.lte]: end, - }, - }; - } - } - - if (filter.commission_rateRange) { - const [start, end] = filter.commission_rateRange; - - if (start !== undefined && start !== null && start !== '') { - where = { - ...where, - commission_rate: { - ...where.commission_rate, - [Op.gte]: start, - }, - }; - } - - if (end !== undefined && end !== null && end !== '') { - where = { - ...where, - commission_rate: { - ...where.commission_rate, - [Op.lte]: end, - }, - }; - } - } - - - if (filter.active !== undefined) { - where = { - ...where, - active: filter.active === true || filter.active === 'true' - }; - } - - - if (filter.pay_method) { - where = { - ...where, - pay_method: filter.pay_method, - }; - } - - if (filter.active) { - where = { - ...where, - active: filter.active, - }; - } - - - - - - if (filter.createdAtRange) { - const [start, end] = filter.createdAtRange; - - if (start !== undefined && start !== null && start !== '') { - where = { - ...where, - ['createdAt']: { - ...where.createdAt, - [Op.gte]: start, - }, - }; - } - - if (end !== undefined && end !== null && end !== '') { - where = { - ...where, - ['createdAt']: { - ...where.createdAt, - [Op.lte]: end, - }, - }; - } - } } - - - const queryOptions = { where, include, distinct: true, - order: filter.field && filter.sort + order: filter && filter.field && filter.sort ? [[filter.field, filter.sort]] : [['createdAt', 'desc']], - transaction: options?.transaction, - logging: console.log + transaction: options && options.transaction, }; - if (!options?.countOnly) { + if (!(options && options.countOnly)) { queryOptions.limit = limit ? Number(limit) : undefined; queryOptions.offset = offset ? Number(offset) : undefined; } @@ -440,7 +151,7 @@ module.exports = class Workers_comp_classesDBApi { const { rows, count } = await db.workers_comp_classes.findAndCountAll(queryOptions); return { - rows: options?.countOnly ? [] : rows, + rows: (options && options.countOnly) ? [] : rows, count: count }; } catch (error) { @@ -449,20 +160,14 @@ module.exports = class Workers_comp_classesDBApi { } } - static async findAllAutocomplete(query, limit, offset, ) { + static async findAllAutocomplete(query, limit, offset) { let where = {}; - - if (query) { where = { [Op.or]: [ { ['id']: Utils.uuid(query) }, - Utils.ilike( - 'workers_comp_classes', - 'name', - query, - ), + Utils.ilike('workers_comp_classes', 'name', query), ], }; } @@ -472,7 +177,7 @@ module.exports = class Workers_comp_classesDBApi { where, limit: limit ? Number(limit) : undefined, offset: offset ? Number(offset) : undefined, - orderBy: [['name', 'ASC']], + order: [['name', 'ASC']], }); return records.map((record) => ({ @@ -480,7 +185,4 @@ module.exports = class Workers_comp_classesDBApi { label: record.name, })); } - - -}; - +}; \ No newline at end of file diff --git a/backend/src/db/migrations/1773330455697-fix-workers-comp-permissions.js b/backend/src/db/migrations/1773330455697-fix-workers-comp-permissions.js new file mode 100644 index 0000000..ad62089 --- /dev/null +++ b/backend/src/db/migrations/1773330455697-fix-workers-comp-permissions.js @@ -0,0 +1,39 @@ +'use strict'; +module.exports = { + up: async (queryInterface, Sequelize) => { + const createdAt = new Date(); + const updatedAt = new Date(); + // Find all roles + const roles = await queryInterface.sequelize.query( + `SELECT id, name FROM roles WHERE name != 'Public';`, + { type: Sequelize.QueryTypes.SELECT } + ); + // Find the read permission + const permissions = await queryInterface.sequelize.query( + `SELECT id, name FROM permissions WHERE name = 'READ_WORKERS_COMP_CLASSES';`, + { type: Sequelize.QueryTypes.SELECT } + ); + if (permissions.length === 0) return; + const readPerm = permissions[0]; + const rolePermissions = []; + const existing = await queryInterface.sequelize.query( + `SELECT "roles_permissionsId", "permissionId" FROM "rolesPermissionsPermissions" WHERE "permissionId" = '${readPerm.id}';`, + { type: Sequelize.QueryTypes.SELECT } + ); + const existingSet = new Set(existing.map(e => e.roles_permissionsId + '-' + e.permissionId)); + for (const role of roles) { + if (!existingSet.has(role.id + '-' + readPerm.id)) { + rolePermissions.push({ + roles_permissionsId: role.id, + permissionId: readPerm.id, + createdAt, + updatedAt, + }); + } + } + if (rolePermissions.length > 0) { + await queryInterface.bulkInsert('rolesPermissionsPermissions', rolePermissions); + } + }, + down: async (queryInterface, Sequelize) => {} +}; diff --git a/backend/src/db/migrations/1773330455698-fix-employee-pay-types-permissions.js b/backend/src/db/migrations/1773330455698-fix-employee-pay-types-permissions.js new file mode 100644 index 0000000..340d50d --- /dev/null +++ b/backend/src/db/migrations/1773330455698-fix-employee-pay-types-permissions.js @@ -0,0 +1,42 @@ +'use strict'; +module.exports = { + up: async (queryInterface, Sequelize) => { + const createdAt = new Date(); + const updatedAt = new Date(); + + const roles = await queryInterface.sequelize.query( + `SELECT id, name FROM roles WHERE name != 'Public';`, + { type: Sequelize.QueryTypes.SELECT } + ); + + const permissions = await queryInterface.sequelize.query( + `SELECT id, name FROM permissions WHERE name = 'READ_EMPLOYEE_PAY_TYPES';`, + { type: Sequelize.QueryTypes.SELECT } + ); + + if (permissions.length === 0) return; + const readPerm = permissions[0]; + const rolePermissions = []; + + const existing = await queryInterface.sequelize.query( + `SELECT "roles_permissionsId", "permissionId" FROM "rolesPermissionsPermissions" WHERE "permissionId" = '${readPerm.id}';`, + { type: Sequelize.QueryTypes.SELECT } + ); + const existingSet = new Set(existing.map(e => e.roles_permissionsId + '-' + e.permissionId)); + + for (const role of roles) { + if (!existingSet.has(role.id + '-' + readPerm.id)) { + rolePermissions.push({ + roles_permissionsId: role.id, + permissionId: readPerm.id, + createdAt, + updatedAt, + }); + } + } + if (rolePermissions.length > 0) { + await queryInterface.bulkInsert('rolesPermissionsPermissions', rolePermissions); + } + }, + down: async (queryInterface, Sequelize) => {} +}; diff --git a/frontend/src/pages/job_logs/job_logs-edit.tsx b/frontend/src/pages/job_logs/job_logs-edit.tsx index 06fd348..b358247 100644 --- a/frontend/src/pages/job_logs/job_logs-edit.tsx +++ b/frontend/src/pages/job_logs/job_logs-edit.tsx @@ -724,7 +724,7 @@ const EditJob_logsPage = () => { - + diff --git a/frontend/src/pages/job_logs/job_logs-new.tsx b/frontend/src/pages/job_logs/job_logs-new.tsx index 1c3d8f6..a19111b 100644 --- a/frontend/src/pages/job_logs/job_logs-new.tsx +++ b/frontend/src/pages/job_logs/job_logs-new.tsx @@ -458,7 +458,7 @@ const Job_logsNew = () => { - + diff --git a/frontend/src/pages/log-work.tsx b/frontend/src/pages/log-work.tsx index 2992b46..7f26eb9 100644 --- a/frontend/src/pages/log-work.tsx +++ b/frontend/src/pages/log-work.tsx @@ -1,6 +1,6 @@ import { mdiPencil, mdiChartTimelineVariant } from '@mdi/js'; import Head from 'next/head'; -import React, { ReactElement } from 'react'; +import React, { ReactElement, useEffect, useState } from 'react'; import CardBox from '../components/CardBox'; import LayoutAuthenticated from '../layouts/Authenticated'; import SectionMain from '../components/SectionMain'; @@ -16,11 +16,27 @@ import { SelectField } from '../components/SelectField'; import { useRouter } from 'next/router'; import { create } from '../stores/job_logs/job_logsSlice'; import { useAppDispatch, useAppSelector } from '../stores/hooks'; +import axios from 'axios'; const LogWorkPage = () => { const router = useRouter(); const dispatch = useAppDispatch(); const currentUser = useAppSelector((state) => state.auth.currentUser); + const [assignedPayTypes, setAssignedPayTypes] = useState([]); + + useEffect(() => { + if (currentUser?.id) { + axios.get(`/employee_pay_types?employee=${currentUser.id}&active=true`) + .then((res) => { + if (res.data && res.data.rows) { + // Ensure we are extracting the inner pay_type relation from employee_pay_types + const payTypes = res.data.rows.map((row: any) => row.pay_type).filter(Boolean); + setAssignedPayTypes(payTypes); + } + }) + .catch((err) => console.error('Failed to fetch assigned pay types:', err)); + } + }, [currentUser]); const initialValues = { work_date: new Date().toISOString().slice(0, 16), @@ -28,7 +44,7 @@ const LogWorkPage = () => { customer: '', hours_conducted: '', client_paid: '', - workers_comp_class: 'roof', + workersCompClass: '', pay_type: '', vehicle: '', odometer_start: '', @@ -67,15 +83,18 @@ const LogWorkPage = () => { - - - Roof - Ladder - Ground - + + - + + Select an assigned pay type + {assignedPayTypes.map((pt) => ( + + {pt.name || pt.pay_method} + + ))} + @@ -108,4 +127,4 @@ LogWorkPage.getLayout = function getLayout(page: ReactElement) { return {page}; }; -export default LogWorkPage; +export default LogWorkPage; \ No newline at end of file diff --git a/frontend/src/pages/workers_comp_classes/workers_comp_classes-edit.tsx b/frontend/src/pages/workers_comp_classes/workers_comp_classes-edit.tsx index 3ee3169..5e2ca0b 100644 --- a/frontend/src/pages/workers_comp_classes/workers_comp_classes-edit.tsx +++ b/frontend/src/pages/workers_comp_classes/workers_comp_classes-edit.tsx @@ -1,9 +1,6 @@ -import { mdiChartTimelineVariant, mdiUpload } from '@mdi/js' +import { mdiChartTimelineVariant } from '@mdi/js' import Head from 'next/head' import React, { ReactElement, useEffect, useState } from 'react' -import DatePicker from "react-datepicker"; -import "react-datepicker/dist/react-datepicker.css"; -import dayjs from "dayjs"; import CardBox from '../../components/CardBox' import LayoutAuthenticated from '../../layouts/Authenticated' @@ -16,230 +13,44 @@ import FormField from '../../components/FormField' import BaseDivider from '../../components/BaseDivider' import BaseButtons from '../../components/BaseButtons' import BaseButton from '../../components/BaseButton' -import FormCheckRadio from '../../components/FormCheckRadio' -import FormCheckRadioGroup from '../../components/FormCheckRadioGroup' -import FormFilePicker from '../../components/FormFilePicker' -import FormImagePicker from '../../components/FormImagePicker' -import { SelectField } from "../../components/SelectField"; -import { SelectFieldMany } from "../../components/SelectFieldMany"; -import { SwitchField } from '../../components/SwitchField' -import {RichTextField} from "../../components/RichTextField"; import { update, fetch } from '../../stores/workers_comp_classes/workers_comp_classesSlice' import { useAppDispatch, useAppSelector } from '../../stores/hooks' import { useRouter } from 'next/router' -import {saveFile} from "../../helpers/fileSaver"; -import dataFormatter from '../../helpers/dataFormatter'; -import ImageField from "../../components/ImageField"; - - const EditWorkers_comp_classesPage = () => { const router = useRouter() const dispatch = useAppDispatch() + const initVals = { - - - 'name': '', - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - pay_method: '', - - - - - - - - - - - - 'hourly_rate': '', - - - - - - - - - - - - - - - - - - - - - - - - - - - - 'commission_rate': '', - - - - - 'workers_comp_percentage': '', - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - active: false, - - - - - - - - - - - - - - - - - - description: '', - - - - - - - - - - - - - - - - - - - - - - - - - + name: '', + percentage: '', } + const [initialValues, setInitialValues] = useState(initVals) const { workers_comp_classes } = useAppSelector((state) => state.workers_comp_classes) - - const { id } = router.query useEffect(() => { - dispatch(fetch({ id: id })) - }, [id]) + if (id) { + dispatch(fetch({ id: id as string })) + } + }, [id, dispatch]) useEffect(() => { - if (typeof workers_comp_classes === 'object') { - setInitialValues(workers_comp_classes) + if (typeof workers_comp_classes === 'object' && workers_comp_classes !== null) { + const newInitialVal = { ...initVals }; + Object.keys(initVals).forEach(el => { + if (workers_comp_classes[el] !== undefined) { + newInitialVal[el] = workers_comp_classes[el]; + } + }); + setInitialValues(newInitialVal); } }, [workers_comp_classes]) - useEffect(() => { - if (typeof workers_comp_classes === 'object') { - const newInitialVal = {...initVals}; - Object.keys(initVals).forEach(el => newInitialVal[el] = (workers_comp_classes)[el]) - setInitialValues(newInitialVal); - } - }, [workers_comp_classes]) - - const handleSubmit = async (data) => { + const handleSubmit = async (data: any) => { await dispatch(update({ id: id, data })) await router.push('/workers_comp_classes/workers_comp_classes-list') } @@ -247,10 +58,10 @@ const EditWorkers_comp_classesPage = () => { return ( <> - {getPageTitle('Edit workers_comp_classes')} + {getPageTitle('Edit Workers Comp Class')} - + {''} @@ -260,18 +71,18 @@ const EditWorkers_comp_classesPage = () => { onSubmit={(values) => handleSubmit(values)} > - - - - - - - - - - - - + + + + + + + + + + + + @@ -281,14 +92,10 @@ const EditWorkers_comp_classesPage = () => { EditWorkers_comp_classesPage.getLayout = function getLayout(page: ReactElement) { return ( - + {page} ) } -export default EditWorkers_comp_classesPage \ No newline at end of file +export default EditWorkers_comp_classesPage diff --git a/frontend/src/pages/workers_comp_classes/workers_comp_classes-list.tsx b/frontend/src/pages/workers_comp_classes/workers_comp_classes-list.tsx index 85c4f3c..e44f45d 100644 --- a/frontend/src/pages/workers_comp_classes/workers_comp_classes-list.tsx +++ b/frontend/src/pages/workers_comp_classes/workers_comp_classes-list.tsx @@ -1,5 +1,6 @@ import { mdiChartTimelineVariant, mdiPlus } from '@mdi/js' import Head from 'next/head' +import { uniqueId } from 'lodash' import React, { ReactElement, useEffect, useState } from 'react' import CardBox from '../../components/CardBox' import LayoutAuthenticated from '../../layouts/Authenticated' @@ -8,18 +9,37 @@ import SectionTitleLineWithButton from '../../components/SectionTitleLineWithBut import { getPageTitle } from '../../config' import TableWorkers_comp_classes from '../../components/Workers_comp_classes/TableWorkers_comp_classes' import BaseButton from '../../components/BaseButton' -import axios from 'axios'; -import Link from 'next/link'; -import { useAppDispatch, useAppSelector } from '../../stores/hooks'; -import CardBoxModal from '../../components/CardBoxModal'; -import DragDropFilePicker from '../../components/DragDropFilePicker'; -import { setRefetch, uploadCsv } from '../../stores/workers_comp_classes/workers_comp_classesSlice'; -import { hasPermission } from '../../helpers/userPermissions'; +import axios from 'axios' +import Link from 'next/link' +import { useAppDispatch, useAppSelector } from '../../stores/hooks' +import CardBoxModal from '../../components/CardBoxModal' +import DragDropFilePicker from '../../components/DragDropFilePicker' +import { setRefetch, uploadCsv } from '../../stores/workers_comp_classes/workers_comp_classesSlice' +import { hasPermission } from '../../helpers/userPermissions' const Workers_comp_classesList = () => { + const [filterItems, setFilterItems] = useState([]); + const [filters] = useState([ + {label: 'Name', title: 'name'}, + {label: 'Percentage', title: 'percentage', number: 'true'}, + ]); + const dispatch = useAppDispatch(); const { currentUser } = useAppSelector((state) => state.auth); - const [reportData, setReportData] = useState(null); + const [reportData, setReportData] = useState(null); + + const addFilter = () => { + const newItem = { + id: uniqueId(), + fields: { + filterValue: '', + filterValueFrom: '', + filterValueTo: '', + selectedField: filters[0].title, + }, + }; + setFilterItems([...filterItems, newItem]); + }; useEffect(() => { const fetchReport = async () => { @@ -46,6 +66,11 @@ const Workers_comp_classesList = () => { > {hasPermission(currentUser, 'CREATE_WORKERS_COMP_CLASSES') && ( + { {Object.entries(reportData.totalsByClass).map(([className, total]: any) => ( {className} - ${total.toFixed(2)} + ${Number(total).toFixed(2)} ))} @@ -76,7 +101,12 @@ const Workers_comp_classesList = () => { )} - + > diff --git a/frontend/src/pages/workers_comp_classes/workers_comp_classes-new.tsx b/frontend/src/pages/workers_comp_classes/workers_comp_classes-new.tsx index 57ff73a..e17da99 100644 --- a/frontend/src/pages/workers_comp_classes/workers_comp_classes-new.tsx +++ b/frontend/src/pages/workers_comp_classes/workers_comp_classes-new.tsx @@ -1,4 +1,4 @@ -import { mdiAccount, mdiChartTimelineVariant, mdiMail, mdiUpload } from '@mdi/js' +import { mdiChartTimelineVariant } from '@mdi/js' import Head from 'next/head' import React, { ReactElement } from 'react' import CardBox from '../../components/CardBox' @@ -12,167 +12,52 @@ import FormField from '../../components/FormField' import BaseDivider from '../../components/BaseDivider' import BaseButtons from '../../components/BaseButtons' import BaseButton from '../../components/BaseButton' -import FormCheckRadio from '../../components/FormCheckRadio' -import FormCheckRadioGroup from '../../components/FormCheckRadioGroup' -import FormFilePicker from '../../components/FormFilePicker' -import FormImagePicker from '../../components/FormImagePicker' -import { SwitchField } from '../../components/SwitchField' - -import { SelectField } from '../../components/SelectField' -import { SelectFieldMany } from "../../components/SelectFieldMany"; -import {RichTextField} from "../../components/RichTextField"; import { create } from '../../stores/workers_comp_classes/workers_comp_classesSlice' import { useAppDispatch } from '../../stores/hooks' import { useRouter } from 'next/router' -import moment from 'moment'; const initialValues = { - - name: '', - - - - - - - - - - - - - - - - - - - - - - - - - pay_method: 'hourly', - - - - - - - - hourly_rate: '', - - - - - - - - - - - - - - - - commission_rate: '', - - workers_comp_percentage: '', - - - - - - - - - - - - - - - - - - - - - - active: false, - - - - - - - - - - - description: '', - - - - - - - - - - - - - + percentage: '', } - const Workers_comp_classesNew = () => { const router = useRouter() const dispatch = useAppDispatch() - - - - const handleSubmit = async (data) => { + const handleSubmit = async (data: any) => { await dispatch(create(data)) await router.push('/workers_comp_classes/workers_comp_classes-list') } + return ( <> - {getPageTitle('New Item')} + {getPageTitle('New Workers Comp Class')} - + {''} handleSubmit(values)} > - - - - - - - - - - - - + + + + + + + + + + + + @@ -182,14 +67,10 @@ const Workers_comp_classesNew = () => { Workers_comp_classesNew.getLayout = function getLayout(page: ReactElement) { return ( - + {page} ) } -export default Workers_comp_classesNew \ No newline at end of file +export default Workers_comp_classesNew diff --git a/patch.js b/patch.js index c504bee..5b43b54 100644 --- a/patch.js +++ b/patch.js @@ -1,21 +1,26 @@ const fs = require('fs'); - -const file = 'backend/src/services/payroll_line_items.js'; +const file = 'backend/src/db/api/job_logs.js'; let content = fs.readFileSync(file, 'utf8'); -const createLogic = ` - if (data.job_logId && data.gross_pay) { - const jobLog = await db.job_logs.findByPk(data.job_logId, { transaction }); - if (jobLog && jobLog.workersCompClassId) { - const compClass = await db.workers_comp_classes.findByPk(jobLog.workersCompClassId, { transaction }); - if (compClass && compClass.percentage) { - data.workers_comp_amount = (Number(data.gross_pay || 0) * Number(compClass.percentage || 0)) / 100; - } - } - } -`; +if (!content.includes('setWorkersCompClass')) { + content = content.replace( + /await job_logs.setVehicle(\s*data.vehicle\s*||\s*null,\s*{\s*transaction,\s*})/g, + `await job_logs.setVehicle( data.vehicle || null, {\n transaction,\n });\n \n await job_logs.setWorkersCompClass( data.workersCompClass || null, {\n transaction,\n });` + ); -content = content.replace(/try {\n await Payroll_line_itemsDBApi.create/g, 'try {' + createLogic + ' await Payroll_line_itemsDBApi.create'); -content = content.replace(/try {\n const updatedPayroll_line_items = await Payroll_line_itemsDBApi.update/g, 'try {' + createLogic + ' const updatedPayroll_line_items = await Payroll_line_itemsDBApi.update'); + content = content.replace( + /if\s*\(data.vehicle !== undefined\)\s*{\s*await job_logs.setVehicle\(\s*data.vehicle,\s*{\s*transaction\s*}\s*\);\s*}/g, + `if (data.vehicle !== undefined) {\n await job_logs.setVehicle(\n data.vehicle,\n { transaction }\n );\n }\n \n if (data.workersCompClass !== undefined) {\n await job_logs.setWorkersCompClass(\n data.workersCompClass,\n { transaction }\n );\n }` + ); -fs.writeFileSync(file, content); \ No newline at end of file + // Also let's update findBy to include workersCompClass + content = content.replace( + /output.vehicle = await job_logs.getVehicle({\s*transaction\s*})/g, + `output.vehicle = await job_logs.getVehicle({\n transaction\n });\n \n output.workersCompClass = await job_logs.getWorkersCompClass({\n transaction\n });` + ); + + fs.writeFileSync(file, content); + console.log("Patched!"); +} else { + console.log("Already patched."); +} diff --git a/patch.py b/patch.py new file mode 100644 index 0000000..0cc5cf7 --- /dev/null +++ b/patch.py @@ -0,0 +1,24 @@ +import re + +with open('backend/src/db/api/job_logs.js', 'r') as f: + content = f.read() + +content = content.replace( + 'await job_logs.setVehicle( data.vehicle || null, {\n transaction,\n });', + 'await job_logs.setVehicle( data.vehicle || null, {\n transaction,\n });\n \n await job_logs.setWorkersCompClass( data.workersCompClass || null, {\n transaction,\n });' +) + +content = content.replace( + '''if (data.vehicle !== undefined) {\n await job_logs.setVehicle(\n \n data.vehicle,\n \n { transaction }\n );\n }''', + '''if (data.vehicle !== undefined) {\n await job_logs.setVehicle(\n \n data.vehicle,\n \n { transaction }\n );\n }\n \n if (data.workersCompClass !== undefined) {\n await job_logs.setWorkersCompClass(\n \n data.workersCompClass,\n \n { transaction }\n );\n }''' +) + +content = content.replace( + '''output.vehicle = await job_logs.getVehicle({\n transaction\n });''', + '''output.vehicle = await job_logs.getVehicle({\n transaction\n });\n \n output.workersCompClass = await job_logs.getWorkersCompClass({\n transaction\n });''' +) + +with open('backend/src/db/api/job_logs.js', 'w') as f: + f.write(content) + +print("Patched correctly!") diff --git a/patch2.py b/patch2.py new file mode 100644 index 0000000..4327b29 --- /dev/null +++ b/patch2.py @@ -0,0 +1,61 @@ +import re + +with open('backend/src/db/api/job_logs.js', 'r') as f: + content = f.read() + +replacement = ''' { + model: db.vehicles, + as: 'vehicle', + + where: filter.vehicle ? { + [Op.or]: [ + { id: { [Op.in]: filter.vehicle.split('|').map(term => Utils.uuid(term)) } }, + { + name: { + [Op.or]: filter.vehicle.split('|').map(term => ({ [Op.iLike]: `%${term}%` })) + } + }, + ] + } : {}, + + }, + + { + model: db.workers_comp_classes, + as: 'workersCompClass', + where: filter.workersCompClass ? { + [Op.or]: [ + { id: { [Op.in]: filter.workersCompClass.split('|').map(term => Utils.uuid(term)) } }, + { + name: { + [Op.or]: filter.workersCompClass.split('|').map(term => ({ [Op.iLike]: `%${term}%` })) + } + }, + ] + } : {}, + },''' + +content = content.replace( + ''' { + model: db.vehicles, + as: 'vehicle', + + where: filter.vehicle ? { + [Op.or]: [ + { id: { [Op.in]: filter.vehicle.split('|').map(term => Utils.uuid(term)) } }, + { + name: { + [Op.or]: filter.vehicle.split('|').map(term => ({ [Op.iLike]: `%${term}%` })) + } + }, + ] + } : {}, + + },''', + replacement +) + +with open('backend/src/db/api/job_logs.js', 'w') as f: + f.write(content) + +print("Patched include!")
{className}
${total.toFixed(2)}
${Number(total).toFixed(2)}