Autosave: 20260413-132151
This commit is contained in:
parent
c9732c5db8
commit
da86c68992
BIN
assets/pasted-20260413-130727-e67a0305.png
Normal file
BIN
assets/pasted-20260413-130727-e67a0305.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 122 KiB |
BIN
assets/pasted-20260413-131715-2c4e92ec.png
Normal file
BIN
assets/pasted-20260413-131715-2c4e92ec.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 176 KiB |
@ -240,9 +240,19 @@ module.exports = class Payroll_runsDBApi {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.payroll_line_items_payroll_run = await payroll_runs.getPayroll_line_items_payroll_run({
|
output.payroll_line_items_payroll_run = await Promise.all(
|
||||||
transaction
|
(await payroll_runs.getPayroll_line_items_payroll_run({
|
||||||
});
|
transaction
|
||||||
|
})).map(async (payrollLineItem) => {
|
||||||
|
const payrollLineItemOutput = payrollLineItem.get({ plain: true });
|
||||||
|
|
||||||
|
payrollLineItemOutput.employee = await payrollLineItem.getEmployee({
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
return payrollLineItemOutput;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,11 @@ const db = require('../db/models');
|
|||||||
const { wrapAsync } = require('../helpers');
|
const { wrapAsync } = require('../helpers');
|
||||||
const { Op } = require('sequelize');
|
const { Op } = require('sequelize');
|
||||||
|
|
||||||
|
const getInclusiveDateRange = (startDate, endDate) => ({
|
||||||
|
start: new Date(`${startDate}T00:00:00.000Z`),
|
||||||
|
end: new Date(`${endDate}T23:59:59.999Z`),
|
||||||
|
});
|
||||||
|
|
||||||
router.post('/preview', passport.authenticate('jwt', { session: false }), wrapAsync(async (req, res) => {
|
router.post('/preview', passport.authenticate('jwt', { session: false }), wrapAsync(async (req, res) => {
|
||||||
const { startDate, endDate } = req.body;
|
const { startDate, endDate } = req.body;
|
||||||
|
|
||||||
@ -12,11 +17,13 @@ router.post('/preview', passport.authenticate('jwt', { session: false }), wrapAs
|
|||||||
return res.status(400).send('startDate and endDate are required');
|
return res.status(400).send('startDate and endDate are required');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { start, end } = getInclusiveDateRange(startDate, endDate);
|
||||||
|
|
||||||
// Find job logs in range that are not paid
|
// Find job logs in range that are not paid
|
||||||
const jobLogs = await db.job_logs.findAll({
|
const jobLogs = await db.job_logs.findAll({
|
||||||
where: {
|
where: {
|
||||||
work_date: {
|
work_date: {
|
||||||
[Op.between]: [new Date(startDate), new Date(endDate)]
|
[Op.between]: [start, end]
|
||||||
},
|
},
|
||||||
status: {
|
status: {
|
||||||
[Op.ne]: 'paid'
|
[Op.ne]: 'paid'
|
||||||
@ -85,11 +92,13 @@ router.post('/generate', passport.authenticate('jwt', { session: false }), wrapA
|
|||||||
return res.status(400).send('startDate and endDate are required');
|
return res.status(400).send('startDate and endDate are required');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { start, end } = getInclusiveDateRange(startDate, endDate);
|
||||||
|
|
||||||
// Find job logs
|
// Find job logs
|
||||||
const jobLogs = await db.job_logs.findAll({
|
const jobLogs = await db.job_logs.findAll({
|
||||||
where: {
|
where: {
|
||||||
work_date: {
|
work_date: {
|
||||||
[Op.between]: [new Date(startDate), new Date(endDate)]
|
[Op.between]: [start, end]
|
||||||
},
|
},
|
||||||
status: {
|
status: {
|
||||||
[Op.ne]: 'paid'
|
[Op.ne]: 'paid'
|
||||||
|
|||||||
BIN
frontend/public/assets/vm-shot-2026-04-13T13-17-17-604Z.jpg
Normal file
BIN
frontend/public/assets/vm-shot-2026-04-13T13-17-17-604Z.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
@ -218,53 +218,8 @@ export const loadColumns = async (
|
|||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
|
||||||
field: 'odometer_start',
|
|
||||||
headerName: 'OdometerStart',
|
|
||||||
flex: 1,
|
|
||||||
minWidth: 120,
|
|
||||||
filterable: false,
|
|
||||||
headerClassName: 'datagrid--header',
|
|
||||||
cellClassName: 'datagrid--cell',
|
|
||||||
|
|
||||||
|
|
||||||
editable: hasUpdatePermission,
|
|
||||||
|
|
||||||
type: 'number',
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
field: 'odometer_end',
|
|
||||||
headerName: 'OdometerEnd',
|
|
||||||
flex: 1,
|
|
||||||
minWidth: 120,
|
|
||||||
filterable: false,
|
|
||||||
headerClassName: 'datagrid--header',
|
|
||||||
cellClassName: 'datagrid--cell',
|
|
||||||
|
|
||||||
|
|
||||||
editable: hasUpdatePermission,
|
|
||||||
|
|
||||||
type: 'number',
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
field: 'job_address',
|
|
||||||
headerName: 'JobAddress',
|
|
||||||
flex: 1,
|
|
||||||
minWidth: 120,
|
|
||||||
filterable: false,
|
|
||||||
headerClassName: 'datagrid--header',
|
|
||||||
cellClassName: 'datagrid--cell',
|
|
||||||
|
|
||||||
|
|
||||||
editable: hasUpdatePermission,
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
{
|
||||||
field: 'status',
|
field: 'status',
|
||||||
headerName: 'Status',
|
headerName: 'Status',
|
||||||
|
|||||||
@ -84,28 +84,12 @@ const menuAside: MenuAsideItem[] = [
|
|||||||
icon: 'mdiLinkVariant' in icon ? icon['mdiLinkVariant' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
|
icon: 'mdiLinkVariant' in icon ? icon['mdiLinkVariant' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
|
||||||
permissions: 'UPDATE_USERS'
|
permissions: 'UPDATE_USERS'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
href: '/chemical_products/chemical_products-list',
|
|
||||||
label: 'Chemical products',
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore
|
|
||||||
icon: 'mdiFlask' in icon ? icon['mdiFlask' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
|
|
||||||
permissions: 'UPDATE_USERS'
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
href: '/job_logs/job_logs-list',
|
href: '/job_logs/job_logs-list',
|
||||||
label: 'All Job Logs',
|
label: 'All Job Logs',
|
||||||
icon: 'mdiClipboardTextClock' in icon ? icon['mdiClipboardTextClock' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
|
icon: 'mdiClipboardTextClock' in icon ? icon['mdiClipboardTextClock' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
|
||||||
permissions: 'UPDATE_USERS'
|
permissions: 'UPDATE_USERS'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
href: '/job_chemical_usages/job_chemical_usages-list',
|
|
||||||
label: 'Job chemical usages',
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore
|
|
||||||
icon: 'mdiFlaskOutline' in icon ? icon['mdiFlaskOutline' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
|
|
||||||
permissions: 'UPDATE_USERS'
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
href: '/payroll_runs/payroll_runs-list',
|
href: '/payroll_runs/payroll_runs-list',
|
||||||
label: 'Payroll runs',
|
label: 'Payroll runs',
|
||||||
|
|||||||
@ -32,9 +32,7 @@ const Dashboard = () => {
|
|||||||
const [vehicles, setVehicles] = React.useState(loadingMessage);
|
const [vehicles, setVehicles] = React.useState(loadingMessage);
|
||||||
const [pay_types, setPay_types] = React.useState(loadingMessage);
|
const [pay_types, setPay_types] = React.useState(loadingMessage);
|
||||||
const [employee_pay_types, setEmployee_pay_types] = React.useState(loadingMessage);
|
const [employee_pay_types, setEmployee_pay_types] = React.useState(loadingMessage);
|
||||||
const [chemical_products, setChemical_products] = React.useState(loadingMessage);
|
|
||||||
const [job_logs, setJob_logs] = React.useState(loadingMessage);
|
const [job_logs, setJob_logs] = React.useState(loadingMessage);
|
||||||
const [job_chemical_usages, setJob_chemical_usages] = React.useState(loadingMessage);
|
|
||||||
const [payroll_runs, setPayroll_runs] = React.useState(loadingMessage);
|
const [payroll_runs, setPayroll_runs] = React.useState(loadingMessage);
|
||||||
const [payroll_line_items, setPayroll_line_items] = React.useState(loadingMessage);
|
const [payroll_line_items, setPayroll_line_items] = React.useState(loadingMessage);
|
||||||
|
|
||||||
@ -58,8 +56,8 @@ const Dashboard = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const entities = ['users','roles','permissions','customers','vehicles','pay_types','employee_pay_types','chemical_products','job_logs','job_chemical_usages','payroll_runs','payroll_line_items',];
|
const entities = ['users','roles','permissions','customers','vehicles','pay_types','employee_pay_types','job_logs','payroll_runs','payroll_line_items',];
|
||||||
const fns = [setUsers,setRoles,setPermissions,setCustomers,setVehicles,setPay_types,setEmployee_pay_types,setChemical_products,setJob_logs,setJob_chemical_usages,setPayroll_runs,setPayroll_line_items,];
|
const fns = [setUsers,setRoles,setPermissions,setCustomers,setVehicles,setPay_types,setEmployee_pay_types,setJob_logs,setPayroll_runs,setPayroll_line_items,];
|
||||||
|
|
||||||
const requests = entities.map((entity, index) => {
|
const requests = entities.map((entity, index) => {
|
||||||
|
|
||||||
@ -355,34 +353,6 @@ const Dashboard = () => {
|
|||||||
</div>
|
</div>
|
||||||
</Link>}
|
</Link>}
|
||||||
|
|
||||||
{hasPermission(currentUser, 'READ_CHEMICAL_PRODUCTS') && <Link href={'/chemical_products/chemical_products-list'}>
|
|
||||||
<div
|
|
||||||
className={`${corners !== 'rounded-full'? corners : 'rounded-3xl'} dark:bg-dark-900 ${cardsStyle} dark:border-dark-700 p-6`}
|
|
||||||
>
|
|
||||||
<div className="flex justify-between align-center">
|
|
||||||
<div>
|
|
||||||
<div className="text-lg leading-tight text-gray-500 dark:text-gray-400">
|
|
||||||
Chemical products
|
|
||||||
</div>
|
|
||||||
<div className="text-3xl leading-tight font-semibold">
|
|
||||||
{chemical_products}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<BaseIcon
|
|
||||||
className={`${iconsColor}`}
|
|
||||||
w="w-16"
|
|
||||||
h="h-16"
|
|
||||||
size={48}
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore
|
|
||||||
path={'mdiFlask' in icon ? icon['mdiFlask' as keyof typeof icon] : icon.mdiTable || icon.mdiTable}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Link>}
|
|
||||||
|
|
||||||
{hasPermission(currentUser, 'READ_JOB_LOGS') && <Link href={'/job_logs/job_logs-list'}>
|
{hasPermission(currentUser, 'READ_JOB_LOGS') && <Link href={'/job_logs/job_logs-list'}>
|
||||||
<div
|
<div
|
||||||
className={`${corners !== 'rounded-full'? corners : 'rounded-3xl'} dark:bg-dark-900 ${cardsStyle} dark:border-dark-700 p-6`}
|
className={`${corners !== 'rounded-full'? corners : 'rounded-3xl'} dark:bg-dark-900 ${cardsStyle} dark:border-dark-700 p-6`}
|
||||||
@ -411,34 +381,6 @@ const Dashboard = () => {
|
|||||||
</div>
|
</div>
|
||||||
</Link>}
|
</Link>}
|
||||||
|
|
||||||
{hasPermission(currentUser, 'READ_JOB_CHEMICAL_USAGES') && <Link href={'/job_chemical_usages/job_chemical_usages-list'}>
|
|
||||||
<div
|
|
||||||
className={`${corners !== 'rounded-full'? corners : 'rounded-3xl'} dark:bg-dark-900 ${cardsStyle} dark:border-dark-700 p-6`}
|
|
||||||
>
|
|
||||||
<div className="flex justify-between align-center">
|
|
||||||
<div>
|
|
||||||
<div className="text-lg leading-tight text-gray-500 dark:text-gray-400">
|
|
||||||
Job chemical usages
|
|
||||||
</div>
|
|
||||||
<div className="text-3xl leading-tight font-semibold">
|
|
||||||
{job_chemical_usages}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<BaseIcon
|
|
||||||
className={`${iconsColor}`}
|
|
||||||
w="w-16"
|
|
||||||
h="h-16"
|
|
||||||
size={48}
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore
|
|
||||||
path={'mdiFlaskOutline' in icon ? icon['mdiFlaskOutline' as keyof typeof icon] : icon.mdiTable || icon.mdiTable}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Link>}
|
|
||||||
|
|
||||||
{hasPermission(currentUser, 'READ_PAYROLL_RUNS') && <Link href={'/payroll_runs/payroll_runs-list'}>
|
{hasPermission(currentUser, 'READ_PAYROLL_RUNS') && <Link href={'/payroll_runs/payroll_runs-list'}>
|
||||||
<div
|
<div
|
||||||
className={`${corners !== 'rounded-full'? corners : 'rounded-3xl'} dark:bg-dark-900 ${cardsStyle} dark:border-dark-700 p-6`}
|
className={`${corners !== 'rounded-full'? corners : 'rounded-3xl'} dark:bg-dark-900 ${cardsStyle} dark:border-dark-700 p-6`}
|
||||||
|
|||||||
@ -270,7 +270,6 @@ const EditJob_logs = () => {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
odometer_start: '',
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -298,7 +297,6 @@ const EditJob_logs = () => {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
odometer_end: '',
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -320,7 +318,6 @@ const EditJob_logs = () => {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
'job_address': '',
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -875,146 +872,6 @@ const EditJob_logs = () => {
|
|||||||
|
|
||||||
></Field>
|
></Field>
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<FormField
|
|
||||||
label="OdometerStart"
|
|
||||||
>
|
|
||||||
<Field
|
|
||||||
type="number"
|
|
||||||
name="odometer_start"
|
|
||||||
placeholder="OdometerStart"
|
|
||||||
/>
|
|
||||||
</FormField>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<FormField
|
|
||||||
label="OdometerEnd"
|
|
||||||
>
|
|
||||||
<Field
|
|
||||||
type="number"
|
|
||||||
name="odometer_end"
|
|
||||||
placeholder="OdometerEnd"
|
|
||||||
/>
|
|
||||||
</FormField>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<FormField
|
|
||||||
label="JobAddress"
|
|
||||||
>
|
|
||||||
<Field
|
|
||||||
name="job_address"
|
|
||||||
placeholder="JobAddress"
|
|
||||||
/>
|
|
||||||
</FormField>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<FormField label="Status" labelFor="status">
|
<FormField label="Status" labelFor="status">
|
||||||
<Field name="status" id="status" component="select">
|
<Field name="status" id="status" component="select">
|
||||||
|
|
||||||
|
|||||||
@ -271,7 +271,6 @@ const EditJob_logsPage = () => {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
odometer_start: '',
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -299,7 +298,6 @@ const EditJob_logsPage = () => {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
odometer_end: '',
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -321,7 +319,6 @@ const EditJob_logsPage = () => {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
'job_address': '',
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -867,146 +864,6 @@ const EditJob_logsPage = () => {
|
|||||||
|
|
||||||
></Field>
|
></Field>
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<FormField
|
|
||||||
label="OdometerStart"
|
|
||||||
>
|
|
||||||
<Field
|
|
||||||
type="number"
|
|
||||||
name="odometer_start"
|
|
||||||
placeholder="OdometerStart"
|
|
||||||
/>
|
|
||||||
</FormField>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<FormField
|
|
||||||
label="OdometerEnd"
|
|
||||||
>
|
|
||||||
<Field
|
|
||||||
type="number"
|
|
||||||
name="odometer_end"
|
|
||||||
placeholder="OdometerEnd"
|
|
||||||
/>
|
|
||||||
</FormField>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<FormField
|
|
||||||
label="JobAddress"
|
|
||||||
>
|
|
||||||
<Field
|
|
||||||
name="job_address"
|
|
||||||
placeholder="JobAddress"
|
|
||||||
/>
|
|
||||||
</FormField>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<FormField label="Status" labelFor="status">
|
<FormField label="Status" labelFor="status">
|
||||||
<Field name="status" id="status" component="select">
|
<Field name="status" id="status" component="select">
|
||||||
|
|
||||||
|
|||||||
@ -34,8 +34,7 @@ const Job_logsTablesPage = () => {
|
|||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
|
|
||||||
const [filters] = useState([{label: 'JobAddress', title: 'job_address'},{label: 'NotesToAdmin', title: 'notes_to_admin'},
|
const [filters] = useState([{label: 'NotesToAdmin', title: 'notes_to_admin'},
|
||||||
{label: 'OdometerStart', title: 'odometer_start', number: 'true'},{label: 'OdometerEnd', title: 'odometer_end', number: 'true'},
|
|
||||||
{label: 'HoursConducted', title: 'hours_conducted', number: 'true'},{label: 'ClientPaid', title: 'client_paid', number: 'true'},
|
{label: 'HoursConducted', title: 'hours_conducted', number: 'true'},{label: 'ClientPaid', title: 'client_paid', number: 'true'},
|
||||||
{label: 'WorkDate', title: 'work_date', date: 'true'},
|
{label: 'WorkDate', title: 'work_date', date: 'true'},
|
||||||
|
|
||||||
|
|||||||
@ -163,7 +163,6 @@ const initialValues = {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
odometer_start: '',
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -179,7 +178,6 @@ const initialValues = {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
odometer_end: '',
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -192,7 +190,6 @@ const initialValues = {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
job_address: '',
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -527,136 +524,6 @@ const Job_logsNew = () => {
|
|||||||
<FormField label="Vehicle" labelFor="vehicle">
|
<FormField label="Vehicle" labelFor="vehicle">
|
||||||
<Field name="vehicle" id="vehicle" component={SelectField} options={[]} itemRef={'vehicles'}></Field>
|
<Field name="vehicle" id="vehicle" component={SelectField} options={[]} itemRef={'vehicles'}></Field>
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<FormField
|
|
||||||
label="OdometerStart"
|
|
||||||
>
|
|
||||||
<Field
|
|
||||||
type="number"
|
|
||||||
name="odometer_start"
|
|
||||||
placeholder="OdometerStart"
|
|
||||||
/>
|
|
||||||
</FormField>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<FormField
|
|
||||||
label="OdometerEnd"
|
|
||||||
>
|
|
||||||
<Field
|
|
||||||
type="number"
|
|
||||||
name="odometer_end"
|
|
||||||
placeholder="OdometerEnd"
|
|
||||||
/>
|
|
||||||
</FormField>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<FormField
|
|
||||||
label="JobAddress"
|
|
||||||
>
|
|
||||||
<Field
|
|
||||||
name="job_address"
|
|
||||||
placeholder="JobAddress"
|
|
||||||
/>
|
|
||||||
</FormField>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<FormField label="Status" labelFor="status">
|
<FormField label="Status" labelFor="status">
|
||||||
<Field name="status" id="status" component="select">
|
<Field name="status" id="status" component="select">
|
||||||
|
|
||||||
|
|||||||
@ -34,8 +34,7 @@ const Job_logsTablesPage = () => {
|
|||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
|
|
||||||
const [filters] = useState([{label: 'JobAddress', title: 'job_address'},{label: 'NotesToAdmin', title: 'notes_to_admin'},
|
const [filters] = useState([{label: 'NotesToAdmin', title: 'notes_to_admin'},
|
||||||
{label: 'OdometerStart', title: 'odometer_start', number: 'true'},{label: 'OdometerEnd', title: 'odometer_end', number: 'true'},
|
|
||||||
{label: 'HoursConducted', title: 'hours_conducted', number: 'true'},{label: 'ClientPaid', title: 'client_paid', number: 'true'},
|
{label: 'HoursConducted', title: 'hours_conducted', number: 'true'},{label: 'ClientPaid', title: 'client_paid', number: 'true'},
|
||||||
{label: 'WorkDate', title: 'work_date', date: 'true'},
|
{label: 'WorkDate', title: 'work_date', date: 'true'},
|
||||||
|
|
||||||
|
|||||||
@ -421,127 +421,6 @@ const Job_logsView = () => {
|
|||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className={'mb-4'}>
|
|
||||||
<p className={'block font-bold mb-2'}>OdometerStart</p>
|
|
||||||
<p>{job_logs?.odometer_start || 'No data'}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className={'mb-4'}>
|
|
||||||
<p className={'block font-bold mb-2'}>OdometerEnd</p>
|
|
||||||
<p>{job_logs?.odometer_end || 'No data'}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className={'mb-4'}>
|
|
||||||
<p className={'block font-bold mb-2'}>JobAddress</p>
|
|
||||||
<p>{job_logs?.job_address}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className={'mb-4'}>
|
<div className={'mb-4'}>
|
||||||
<p className={'block font-bold mb-2'}>Status</p>
|
<p className={'block font-bold mb-2'}>Status</p>
|
||||||
<p>{job_logs?.status ?? 'No data'}</p>
|
<p>{job_logs?.status ?? 'No data'}</p>
|
||||||
@ -595,65 +474,6 @@ const Job_logsView = () => {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<>
|
|
||||||
<p className={'block font-bold mb-2'}>Job_chemical_usages JobLog</p>
|
|
||||||
<CardBox
|
|
||||||
className='mb-6 border border-gray-300 rounded overflow-hidden'
|
|
||||||
hasTable
|
|
||||||
>
|
|
||||||
<div className='overflow-x-auto'>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>QuantityUsed</th>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>Notes</th>
|
|
||||||
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{job_logs.job_chemical_usages_job_log && Array.isArray(job_logs.job_chemical_usages_job_log) &&
|
|
||||||
job_logs.job_chemical_usages_job_log.map((item: any) => (
|
|
||||||
<tr key={item.id} onClick={() => router.push(`/job_chemical_usages/job_chemical_usages-view/?id=${item.id}`)}>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td data-label="quantity_used">
|
|
||||||
{ item.quantity_used }
|
|
||||||
</td>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td data-label="notes">
|
|
||||||
{ item.notes }
|
|
||||||
</td>
|
|
||||||
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
{!job_logs?.job_chemical_usages_job_log?.length && <div className={'text-center py-4'}>No data</div>}
|
|
||||||
</CardBox>
|
|
||||||
</>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { mdiPencil, mdiPlus, mdiTrashCan } from '@mdi/js';
|
import { mdiPencil } from '@mdi/js';
|
||||||
import Head from 'next/head';
|
import Head from 'next/head';
|
||||||
import React, { ReactElement, useEffect, useState } from 'react';
|
import React, { ReactElement, useEffect, useState } from 'react';
|
||||||
import CardBox from '../components/CardBox';
|
import CardBox from '../components/CardBox';
|
||||||
@ -8,7 +8,7 @@ import SectionTitleLineWithButton from '../components/SectionTitleLineWithButton
|
|||||||
import JobLogPayPreview from '../components/JobLogPayPreview';
|
import JobLogPayPreview from '../components/JobLogPayPreview';
|
||||||
import { getPageTitle } from '../config';
|
import { getPageTitle } from '../config';
|
||||||
|
|
||||||
import { Field, Form, Formik, FieldArray } from 'formik';
|
import { Field, Form, Formik } from 'formik';
|
||||||
import FormField from '../components/FormField';
|
import FormField from '../components/FormField';
|
||||||
import BaseDivider from '../components/BaseDivider';
|
import BaseDivider from '../components/BaseDivider';
|
||||||
import BaseButtons from '../components/BaseButtons';
|
import BaseButtons from '../components/BaseButtons';
|
||||||
@ -27,11 +27,13 @@ const LogWorkPage = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (currentUser?.id) {
|
if (currentUser?.id) {
|
||||||
axios.get(`/employee_pay_types?employee=${currentUser.id}&active=true`)
|
axios
|
||||||
|
.get(`/employee_pay_types?employee=${currentUser.id}&active=true`)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.data && res.data.rows) {
|
if (res.data && res.data.rows) {
|
||||||
// Ensure we are extracting the inner pay_type relation from employee_pay_types
|
const payTypes = res.data.rows
|
||||||
const payTypes = res.data.rows.map((row: any) => row.pay_type).filter(Boolean);
|
.map((row: any) => row.pay_type)
|
||||||
|
.filter(Boolean);
|
||||||
setAssignedPayTypes(payTypes);
|
setAssignedPayTypes(payTypes);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -40,7 +42,7 @@ const LogWorkPage = () => {
|
|||||||
}, [currentUser]);
|
}, [currentUser]);
|
||||||
|
|
||||||
const initialValues = {
|
const initialValues = {
|
||||||
work_date: new Date().toISOString().slice(0, 16),
|
work_date: new Date().toISOString().slice(0, 10),
|
||||||
employee: currentUser?.id || '',
|
employee: currentUser?.id || '',
|
||||||
customer: '',
|
customer: '',
|
||||||
hours_conducted: '',
|
hours_conducted: '',
|
||||||
@ -48,12 +50,8 @@ const LogWorkPage = () => {
|
|||||||
workersCompClass: '',
|
workersCompClass: '',
|
||||||
pay_type: '',
|
pay_type: '',
|
||||||
vehicle: '',
|
vehicle: '',
|
||||||
odometer_start: '',
|
|
||||||
odometer_end: '',
|
|
||||||
job_address: '',
|
|
||||||
status: 'submitted',
|
status: 'submitted',
|
||||||
notes_to_admin: '',
|
notes_to_admin: '',
|
||||||
chemical_usages: [],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmit = async (data: any) => {
|
const handleSubmit = async (data: any) => {
|
||||||
@ -72,10 +70,10 @@ const LogWorkPage = () => {
|
|||||||
</SectionTitleLineWithButton>
|
</SectionTitleLineWithButton>
|
||||||
<CardBox>
|
<CardBox>
|
||||||
<Formik initialValues={initialValues} onSubmit={(values) => handleSubmit(values)}>
|
<Formik initialValues={initialValues} onSubmit={(values) => handleSubmit(values)}>
|
||||||
{({ values }) => (
|
{() => (
|
||||||
<Form>
|
<Form>
|
||||||
<FormField label="Work Date">
|
<FormField label="Work Date">
|
||||||
<Field type="datetime-local" name="work_date" />
|
<Field type="date" name="work_date" />
|
||||||
</FormField>
|
</FormField>
|
||||||
<FormField label="Customer" labelFor="customer">
|
<FormField label="Customer" labelFor="customer">
|
||||||
<Field name="customer" id="customer" placeholder="Enter customer name" />
|
<Field name="customer" id="customer" placeholder="Enter customer name" />
|
||||||
@ -87,7 +85,14 @@ const LogWorkPage = () => {
|
|||||||
<Field type="number" name="client_paid" placeholder="Amount" />
|
<Field type="number" name="client_paid" placeholder="Amount" />
|
||||||
</FormField>
|
</FormField>
|
||||||
<FormField label="Worker's Comp Class" labelFor="workersCompClass">
|
<FormField label="Worker's Comp Class" labelFor="workersCompClass">
|
||||||
<Field name="workersCompClass" id="workersCompClass" component={SelectField} options={[]} itemRef={"workers_comp_classes"} showField={"name"} />
|
<Field
|
||||||
|
name="workersCompClass"
|
||||||
|
id="workersCompClass"
|
||||||
|
component={SelectField}
|
||||||
|
options={[]}
|
||||||
|
itemRef={'workers_comp_classes'}
|
||||||
|
showField={'name'}
|
||||||
|
/>
|
||||||
</FormField>
|
</FormField>
|
||||||
<FormField label="Pay Type" labelFor="pay_type">
|
<FormField label="Pay Type" labelFor="pay_type">
|
||||||
<Field name="pay_type" id="pay_type" as="select">
|
<Field name="pay_type" id="pay_type" as="select">
|
||||||
@ -101,68 +106,18 @@ const LogWorkPage = () => {
|
|||||||
</FormField>
|
</FormField>
|
||||||
<JobLogPayPreview payTypeOptions={assignedPayTypes} />
|
<JobLogPayPreview payTypeOptions={assignedPayTypes} />
|
||||||
<FormField label="Vehicle" labelFor="vehicle">
|
<FormField label="Vehicle" labelFor="vehicle">
|
||||||
<Field name="vehicle" id="vehicle" component={SelectField} options={[]} itemRef={'vehicles'} />
|
<Field
|
||||||
</FormField>
|
name="vehicle"
|
||||||
<FormField label="Odometer Start">
|
id="vehicle"
|
||||||
<Field type="number" name="odometer_start" placeholder="Start" />
|
component={SelectField}
|
||||||
</FormField>
|
options={[]}
|
||||||
<FormField label="Odometer End">
|
itemRef={'vehicles'}
|
||||||
<Field type="number" name="odometer_end" placeholder="End" />
|
/>
|
||||||
</FormField>
|
|
||||||
<FormField label="Job Address">
|
|
||||||
<Field name="job_address" placeholder="Address" />
|
|
||||||
</FormField>
|
</FormField>
|
||||||
<FormField label="Notes to Admin" hasTextareaHeight>
|
<FormField label="Notes to Admin" hasTextareaHeight>
|
||||||
<Field name="notes_to_admin" as="textarea" placeholder="Notes..." />
|
<Field name="notes_to_admin" as="textarea" placeholder="Notes..." />
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
<BaseDivider />
|
|
||||||
<h3 className="text-lg font-bold mb-4">Chemical Usage (Optional)</h3>
|
|
||||||
<FieldArray name="chemical_usages">
|
|
||||||
{({ push, remove }) => (
|
|
||||||
<div>
|
|
||||||
{values.chemical_usages.map((usage, index) => (
|
|
||||||
<div key={index} className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-4 items-end border p-4 rounded-lg bg-gray-50 dark:bg-slate-800">
|
|
||||||
<FormField label="Chemical Product" labelFor={`chemical_usages.${index}.chemical_product`}>
|
|
||||||
<Field
|
|
||||||
name={`chemical_usages.${index}.chemical_product`}
|
|
||||||
id={`chemical_usages.${index}.chemical_product`}
|
|
||||||
component={SelectField}
|
|
||||||
itemRef="chemical_products"
|
|
||||||
showField="name"
|
|
||||||
/>
|
|
||||||
</FormField>
|
|
||||||
<FormField label="Quantity Used" labelFor={`chemical_usages.${index}.quantity_used`}>
|
|
||||||
<Field
|
|
||||||
type="number"
|
|
||||||
name={`chemical_usages.${index}.quantity_used`}
|
|
||||||
id={`chemical_usages.${index}.quantity_used`}
|
|
||||||
placeholder="e.g. 5.5"
|
|
||||||
step="0.01"
|
|
||||||
/>
|
|
||||||
</FormField>
|
|
||||||
<div className="mb-4">
|
|
||||||
<BaseButton
|
|
||||||
type="button"
|
|
||||||
color="danger"
|
|
||||||
label="Remove"
|
|
||||||
icon={mdiTrashCan}
|
|
||||||
onClick={() => remove(index)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
<BaseButton
|
|
||||||
type="button"
|
|
||||||
color="success"
|
|
||||||
label="Add Chemical"
|
|
||||||
icon={mdiPlus}
|
|
||||||
onClick={() => push({ chemical_product: '', quantity_used: '' })}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</FieldArray>
|
|
||||||
|
|
||||||
<BaseDivider />
|
<BaseDivider />
|
||||||
<BaseButtons>
|
<BaseButtons>
|
||||||
<BaseButton type="submit" color="info" label="Submit Work Log" />
|
<BaseButton type="submit" color="info" label="Submit Work Log" />
|
||||||
|
|||||||
@ -30,10 +30,20 @@ const Payroll_runsView = () => {
|
|||||||
const { id } = router.query;
|
const { id } = router.query;
|
||||||
|
|
||||||
function removeLastCharacter(str) {
|
function removeLastCharacter(str) {
|
||||||
console.log(str,`str`)
|
|
||||||
return str.slice(0, -1);
|
return str.slice(0, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatEmployeeName(employee) {
|
||||||
|
if (!employee) return 'No data';
|
||||||
|
|
||||||
|
const fullName = [employee.firstName, employee.lastName]
|
||||||
|
.filter(Boolean)
|
||||||
|
.join(' ')
|
||||||
|
.trim();
|
||||||
|
|
||||||
|
return fullName || employee.email || 'No data';
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch(fetch({ id }));
|
dispatch(fetch({ id }));
|
||||||
}, [dispatch, id]);
|
}, [dispatch, id]);
|
||||||
@ -292,72 +302,28 @@ const Payroll_runsView = () => {
|
|||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
<th>Employee</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>TotalHours</th>
|
<th>TotalHours</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>GrossPay</th>
|
<th>GrossPay</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>TotalCommissionBase</th>
|
<th>TotalCommissionBase</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>TotalClientPaid</th>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<th>Summary</th>
|
|
||||||
|
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{payroll_runs.payroll_line_items_payroll_run && Array.isArray(payroll_runs.payroll_line_items_payroll_run) &&
|
{payroll_runs.payroll_line_items_payroll_run && Array.isArray(payroll_runs.payroll_line_items_payroll_run) &&
|
||||||
payroll_runs.payroll_line_items_payroll_run.map((item: any) => (
|
payroll_runs.payroll_line_items_payroll_run.map((item: any) => (
|
||||||
<tr key={item.id} onClick={() => router.push(`/payroll_line_items/payroll_line_items-view/?id=${item.id}`)}>
|
<tr key={item.id} onClick={() => router.push(`/payroll_line_items/payroll_line_items-view/?id=${item.id}`)}>
|
||||||
|
<td data-label="employee">
|
||||||
|
{formatEmployeeName(item.employee)}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td data-label="total_hours">
|
<td data-label="total_hours">
|
||||||
{ item.total_hours }
|
{ item.total_hours }
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td data-label="gross_pay">
|
<td data-label="gross_pay">
|
||||||
{ item.gross_pay }
|
{ item.gross_pay }
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td data-label="total_commission_base">
|
<td data-label="total_commission_base">
|
||||||
{ item.total_commission_base }
|
{ item.total_commission_base }
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td data-label="total_client_paid">
|
|
||||||
{ item.total_client_paid }
|
|
||||||
</td>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td data-label="summary">
|
|
||||||
{ item.summary }
|
|
||||||
</td>
|
|
||||||
|
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user