diff --git a/.env.example b/.env.example deleted file mode 100644 index 1ad83b1..0000000 --- a/.env.example +++ /dev/null @@ -1,9 +0,0 @@ -// .env -GOOGLE_MAPS_KEY=sdfsfd -DEBUG=true - -PLAID_PUBLIC_KEY=asdasd -PLAID_ENVIRONMENT=production - -APPSTORE=sdfsdf -ANDROID=sdfsdf \ No newline at end of file diff --git a/src/js/actions.js b/src/js/actions.js index 958d12d..5913bdc 100644 --- a/src/js/actions.js +++ b/src/js/actions.js @@ -299,6 +299,7 @@ export const searchMe = (entity, queryString, mergeResults = false) => new Promi if (mergeResults) { const previous = store.getState(entity.slug || entity); if (Array.isArray(previous)) list = previous.concat(list.results || list); + } Flux.dispatchEvent(entity.slug || entity, list); accept(list); @@ -320,7 +321,7 @@ export const create = (entity, data, status = WEngine.modes.LIVE) => new Promise let entities = store.getState(entity.slug || entity); if (!entities || !Array.isArray(entities)) entities = []; - //if the response from the server is not a list + //if the response from the server is not a list if (!Array.isArray(incoming)) { // if the response is not a list, I will add the new object into that list Flux.dispatchEvent(entity.slug || entity, entities.concat([{ ...data, id: incoming.id }])); @@ -658,9 +659,9 @@ export const createPayment = async (payment, period) => { * @param {string} employee_bank_account_id employee bank account id */ export const makeEmployeePayment = ( - employeePaymentId, - paymentType, - employer_bank_account_id, + employeePaymentId, + paymentType, + employer_bank_account_id, employee_bank_account_id ) => new Promise((resolve, reject) => { const data = { @@ -831,13 +832,14 @@ class _Store extends Flux.DashStore { }); // Payroll related data - this.addEvent('payroll-periods', (period) => { - return (!period || (Object.keys(period).length === 0 && period.constructor === Object)) ? [{ label: "Loading payment periods...", value: null }] : period.map(p => { - p.label = `From ${moment(p.starting_at).format('MM-D-YY h:mm A')} to ${moment(p.ending_at).format('MM-D-YY h:mm A')}`; - if(!Array.isArray(p.payments)) p.payments = []; - return p; - }); - }); + // this.addEvent('payroll-periods', (period) => { + // return (!period || (Object.keys(period).length === 0 && period.constructor === Object)) ? [{ label: "Loading payment periods...", value: null }] : period.map(p => { + // p.label = `From ${moment(p.starting_at).format('MM-D-YY h:mm A')} to ${moment(p.ending_at).format('MM-D-YY h:mm A')}`; + // if(!Array.isArray(p.payments)) p.payments = []; + // return p; + // }); + // }); + this.addEvent('payroll-periods'); this.addEvent("employee-expired-shifts"); //temporal, just used on the payroll report //temporal storage (for temporal views, information that is read only) diff --git a/src/js/views/calendar.js b/src/js/views/calendar.js index 4b83ec3..abd6e53 100644 --- a/src/js/views/calendar.js +++ b/src/js/views/calendar.js @@ -25,15 +25,15 @@ export const getURLFilters = () => { const gf = { positions: { - grouping: (s) => s.position.title, - label: (s) => {s.venue.title} + grouping: (s) => s.position.title || s.position.label, + label: (s) => {s.venue.title || s.position.label} }, venues: { grouping: (s) => s.venue.title, - label: (s) => {s.position.title} + label: (s) => {s.position.title || s.position.label} }, employees: { - label: (s) => {s.position.title} + label: (s) => {s.position.title || s.position.label} } }; diff --git a/src/js/views/dashboard.js b/src/js/views/dashboard.js index e129f29..6b803b4 100644 --- a/src/js/views/dashboard.js +++ b/src/js/views/dashboard.js @@ -56,9 +56,8 @@ export default class Home extends Flux.DashView { this.subscribe(store, 'shifts', (_shifts) => { this.setState({ shifts: _shifts}); }); - if (shifts) this.setState({ shifts: shifts}); - else searchMe(`shifts`, `?limit=10000&end=${this.state.end.format('YYYY-MM-DD')}&start=${this.state.start.format('YYYY-MM-DD')}`).then((shifts) => this.setState({ shifts })); - + + searchMe(`shifts`, `?limit=10000&end=${this.state.end.format('YYYY-MM-DD')}&start=${this.state.start.format('YYYY-MM-DD')}`); } render() { diff --git a/src/js/views/payroll.js b/src/js/views/payroll.js index c764fe1..2b795c1 100644 --- a/src/js/views/payroll.js +++ b/src/js/views/payroll.js @@ -1737,7 +1737,7 @@ export class PayrollReport extends Flux.DashView { this.updatePayrollPeriod(_payrollPeriods); //if(!this.state.singlePayrollPeriod) this.getSinglePeriod(this.props.match.params.period_id, payrollPeriods); }); - if (!payrollPeriods) { + if (!payrollPeriods || payrollPeriods.length == 0 ) { if(this.props.match.params.period_id !== undefined) fetchSingle("payroll-periods", this.props.match.params.period_id).then(_period => { this.setState({singlePayrollPeriod:_period, payments: this.groupPayments(_period).filter(p => p.payments.length != 0)}); }); @@ -1775,7 +1775,7 @@ export class PayrollReport extends Flux.DashView { if (!payrollPeriods) fetchSingle("payroll-periods", periodId); else { const singlePayrollPeriod = payrollPeriods.find(pp => pp.id == periodId); - this.setState({ singlePayrollPeriod, payments: this.groupPayments(singlePayrollPeriod).filter(p => p.payments.length != 0) }); + this.setState({ singlePayrollPeriod, payments: this.groupPayments(singlePayrollPeriod) }); } } } @@ -1794,6 +1794,7 @@ export class PayrollReport extends Flux.DashView { render() { + console.log(this.state.singlePayrollPeriod); const taxesMagicNumber = 0; if (!this.state.employer) return "Loading..."; else if (!this.state.employer.payroll_configured || !moment.isMoment(this.state.employer.payroll_period_starting_time)) { @@ -1813,11 +1814,21 @@ export class PayrollReport extends Flux.DashView {

Payments for {this.state.singlePayrollPeriod.label ? this.state.singlePayrollPeriod.label : `From ${moment(this.state.singlePayrollPeriod.starting_at).format('MM-D-YY h:mm A')} to ${moment(this.state.singlePayrollPeriod.ending_at).format('MM-D-YY h:mm A')}`}

+
+ +
+
- } fileName={"JobCore " + this.state.singlePayrollPeriod.label + ".pdf"}> + } fileName={"JobCore" + ".pdf"}> {({ blob, url, loading, error }) => (loading ? 'Loading...' : (
@@ -1825,7 +1836,7 @@ export class PayrollReport extends Flux.DashView { ) )} - +
@@ -1852,7 +1863,8 @@ export class PayrollReport extends Flux.DashView { const total_hours = pay.payments.filter(p => p.status === "APPROVED").reduce((total, { regular_hours, over_time }) => total + Number(regular_hours) + Number(over_time), 0); const total_amount = pay.payments.filter(p => p.status === "APPROVED").reduce((total, { regular_hours, over_time, hourly_rate }) => total + (Number(regular_hours) + Number(over_time))*Number(hourly_rate) , 0); - + const total_reg = total_hours > 40 ? 40 * Number(pay.payments[0]['hourly_rate']) : 0; + const total_ot = total_hours > 40 ? (total_hours - 40) * Number(pay.payments[0]['hourly_rate']*1.5) : 0; const total = pay.payments.filter(p => p.status === 'APPROVED').reduce((incoming, current) => { return { overtime: parseFloat(current.regular_hours) + parseFloat(incoming.regular_hours) > 40 ? parseFloat(current.regular_hours) + parseFloat(incoming.regular_hours) - 40 : 0, diff --git a/src/js/views/reports/payroll-period.js b/src/js/views/reports/payroll-period.js index cdec326..ff71257 100644 --- a/src/js/views/reports/payroll-period.js +++ b/src/js/views/reports/payroll-period.js @@ -1,1901 +1,205 @@ -import React, { useState, useEffect, useContext } from "react"; -import Flux from "@4geeksacademy/react-flux-dash"; -import PropTypes from 'prop-types'; -import { store, search, update, fetchSingle, searchMe, processPendingPayrollPeriods, updatePayments, createPayment, fetchAllMe, fetchTemporal, remove, create } from '../../actions.js'; -import { GET } from '../../utils/api_wrapper'; - - -import DateTime from 'react-datetime'; -import moment from 'moment'; -import { DATETIME_FORMAT, TIME_FORMAT, NOW, TODAY, haversineDistance } from '../../components/utils.js'; -import Select from 'react-select'; - -import { Notify } from 'bc-react-notifier'; - -import { Shift, EditOrAddShift } from '../shifts.js'; -import { Employer } from '../profile.js'; -import { ManageLocations, AddOrEditLocation, Location } from '../locations.js'; -import { EmployeeExtendedCard, ShiftOption, ShiftCard, DeductionExtendedCard, Theme, Button, ShiftOptionSelected, GenericCard, SearchCatalogSelect, Avatar, Toggle, Wizard, StarRating, ListCard } from '../../components/index'; -import queryString from 'query-string'; - -import TimePicker from 'rc-time-picker'; -import 'rc-time-picker/assets/index.css'; - -import Tooltip from 'rc-tooltip'; -import 'rc-tooltip/assets/bootstrap_white.css'; - -import GoogleMapReact from 'google-map-react'; - -import { PDFDownloadLink } from '@react-pdf/renderer'; - -import TextareaAutosize from 'react-textarea-autosize'; -import {PayrollPeriodReport} from "../reports/index.js"; - -import { Redirect } from 'react-router-dom'; - -const ENTITIY_NAME = 'payroll'; - -//gets the querystring and creats a formData object to be used when opening the rightbar -export const getPayrollInitialFilters = (catalog) => { - let query = queryString.parse(window.location.search); - if (typeof query == 'undefined') return { - starting_at: TODAY(), - ending_at: new Date().setDate(TODAY().getDate() - 7) - }; - return { - starting_at: query.starting_at, - ending_at: query.ending_at - }; -}; - -export const Clockin = (data) => { - - const _defaults = { - author: null, - employee: null, - shift: null, - created_at: null, - updated_at: null, - started_at: TODAY(), - ended_at: TODAY(), - distance_in_miles: 0, - distance_out_miles: 0, - latitude: [], - longitude: [], - status: 'PENDING', - serialize: function () { - - const newObj = { - shift: (!this.shift || typeof this.shift.id === 'undefined') ? this.shift : this.shift.id, - employee: (!this.employee || typeof this.employee.id === 'undefined') ? this.employee : this.employee.id - }; - - return Object.assign(this, newObj); - }, - unserialize: function () { - const dataType = typeof this.started_at; - //if its already serialized - if ((typeof this.shift == 'object') && ['number', 'string'].indexOf(dataType) == -1) return this; - - const newObject = { - shift: (typeof this.shift != 'object') ? store.get('shift', this.shift) : Shift(this.shift).defaults().unserialize(), - employee: (typeof this.employee != 'object') ? store.get('employees', this.employee) : this.employee, - started_at: this.started_at && !moment.isMoment(this.started_at) ? moment(this.started_at) : this.started_at, - ended_at: this.ended_at && !moment.isMoment(this.ended_at) ? moment(this.ended_at) : this.ended_at, - latitude_in: parseFloat(this.latitude_in), - longitude_in: parseFloat(this.longitude_in), - latitude_out: parseFloat(this.latitude_out), - longitude_out: parseFloat(this.longitude_out), - distance_in_miles: parseFloat(this.distance_in_miles), - distance_out_miles: parseFloat(this.distance_out_miles) - }; - - return Object.assign(this, newObject); - } - - }; - - let _checkin = Object.assign(_defaults, data); - return { - get: () => { - return _checkin; - }, - validate: () => { - const start = _checkin.stared_at; - const finish = _checkin.ended_at; - - //if(SHIFT_POSSIBLE_STATUS.indexOf(_shift.status) == -1) throw new Error('Invalid status "'+_shift.status+'" for shift'); - - return _checkin; - }, - defaults: () => { - return _defaults; - }, - getFormData: () => { - const _formCheckin = { - id: _checkin.id.toString() - }; - return _formCheckin; - } - }; -}; - -export const PayrollPeriod = (data) => { - - const _defaults = { - employer: null, - id: null, - length: 0, - length_type: "DAYS", - payments: [], - starting_at: null, - status: null, - serialize: function () { - - const newObj = { - employer: (!this.employer || typeof this.employer.id === 'undefined') ? this.employer : this.employer.id - }; - - return Object.assign(this, newObj); - }, - unserialize: function () { - const newObject = { - //shift: (typeof this.shift != 'object') ? store.get('shift', this.shift) : Shift(this.shift).defaults().unserialize(), - }; - - return Object.assign(this, newObject); - } - - }; - - let _payment = Object.assign(_defaults, data); - return { - get: () => { - return _payment; - }, - validate: () => { - const start = _payment.starting_at; - const finish = _payment.ending_at; - - //if(SHIFT_POSSIBLE_STATUS.indexOf(_shift.status) == -1) throw new Error('Invalid status "'+_shift.status+'" for shift'); - - return _payment; - }, - defaults: () => { - return _defaults; - }, - getFormData: () => { - const _formCheckin = { - id: _payment.id.toString() - }; - return _formCheckin; - } - }; -}; - -export const Payment = (data) => { - - const _defaults = { - //employer: null, - //id: null, - serialize: function () { - - const newObj = { - id: this.id, - regular_hours: this.regular_hours, - over_time: this.over_time, - hourly_rate: this.hourly_rate, - total_amount: this.total_amount, - breaktime_minutes: 0, - status: this.status, - splited_payment: this.splited_payment, - payroll_period: (!this.employer || typeof this.employer.id === 'undefined') ? this.employer : this.employer.id, - employer: (!this.employer || typeof this.employer.id === 'undefined') ? this.employer : this.employer.id, - employee: (!this.employee || typeof this.employee.id === 'undefined') ? this.employee : this.employee.id, - shift: (!this.shift || typeof this.shift.id === 'undefined') ? this.shift : this.shift.id, - clockin: (!this.clockin || typeof this.clockin.id === 'undefined') ? this.clockin : this.clockin.id - }; - - return Object.assign(this, newObj); - }, - unserialize: function () { - const newObject = { - //shift: (typeof this.shift != 'object') ? store.get('shift', this.shift) : Shift(this.shift).defaults().unserialize(), - created_at: this.created_at && !moment.isMoment(this.created_at) ? moment(this.created_at) : this.created_at, - updated_at: this.updated_at && !moment.isMoment(this.updated_at) ? moment(this.updated_at) : this.updated_at - }; - - - return Object.assign(this, newObject); - } - - }; - - let _payment = Object.assign(_defaults, data); - return { - get: () => { - return _payment; - }, - validate: () => { - //if(SHIFT_POSSIBLE_STATUS.indexOf(_shift.status) == -1) throw new Error('Invalid status "'+_shift.status+'" for shift'); - return _payment; - }, - defaults: () => { - return _defaults; - }, - getFormData: () => { - const _form = { - id: _payment.id.toString() - }; - return _form; - } - }; -}; - -export class PayrollSettings extends Flux.DashView { - - constructor() { - super(); - this.state = { - employer: Employer().defaults(), - deductions: [] - }; - } - - setEmployer(newEmployer) { - const employer = Object.assign(this.state.employer, newEmployer); - this.setState({ employer }); - } - - componentDidMount() { - - const deductions = store.getState('deduction'); - if (!deductions) { - searchMe('deduction'); - } else { - this.setState({ deductions }); - } - fetchTemporal('employers/me', 'current_employer'); - this.subscribe(store, 'current_employer', (employer) => { - this.setState({ employer }); - }); - this.subscribe(store, 'deduction', (deductions) => { - this.setState({ deductions }); - }); - - } - - render() { - - const autoClockout = this.state.employer.maximum_clockout_delay_minutes == null ? false : true; - const weekday = this.state.employer.payroll_period_starting_time.isoWeekday(); - let nextDate = this.state.employer.payroll_period_starting_time.clone(); - while (nextDate.isBefore(NOW())) nextDate = nextDate.add(7, 'days'); - - return ( - {({ bar }) => -
-

Your Payroll Settings

-
-
-

Next payroll will run on {nextDate.format("dddd, MMMM Do YYYY, h:mm a")}

-
-
-
-
-
- - Every - - starting - - at - { - const { value, ...rest } = properties; - return ; - }} - onChange={(value) => { - const starting = moment(this.state.employer.payroll_period_starting_time.format("MM-DD-YYYY") + " " + value.format("hh:mm a"), "MM-DD-YYYY hh:mm a"); - this.setEmployer({ payroll_period_starting_time: starting }); - }} - /> -
-
-
-
- - - before or after the starting time of the shift -
-
-
-
- - - {!autoClockout ? '' : ( - - , wait - this.setEmployer({ maximum_clockout_delay_minutes: e.target.value, timeclock_warning: true })} - /> - min to auto checkout - - - ) - } -
-
- {this.state.employer.timeclock_warning && -
- Apply time clock settings to: - -
- } -
-
- -
- {this.state.deductions.length > 0 - ? - - - - - - - - - - - {this.state.deductions.map((deduction, i) => ( - bar.show({ - slug: "update_deduction", - data: deduction - })} - onDelete={() => { - const noti = Notify.info("Are you sure you want to delete this deduction?", (answer) => { - if (answer) remove('deduction', deduction); - noti.remove(); - }); - }} - > - - ))} - -
NameDeductionStatusDescription
- :

No deductions yet

- } -
- -
-
-
- -
-
-
} -
); - } -} - -/** - * EditOrAddExpiredShift - */ -export const EditOrAddExpiredShift = ({ onSave, onCancel, onChange, catalog, formData, error, oldShift }) => { - - const { bar } = useContext(Theme.Context); - - useEffect(() => { - const venues = store.getState('venues'); - const favlists = store.getState('favlists'); - if (!venues || !favlists) fetchAllMe(['venues', 'favlists']); - }, []); - const expired = moment(formData.starting_at).isBefore(NOW()) || moment(formData.ending_at).isBefore(NOW()); - - const validating_minimum = moment(formData.starting_at).isBefore(formData.period_starting); - const validating_maximum = moment(formData.ending_at).isAfter(formData.period_ending); - - return ( -
-
-
- {formData.hide_warnings === true ? null : (formData.status == 'DRAFT' && !error) ? -
This shift is a draft
- : (formData.status != 'UNDEFINED' && !error) ? -
This shift is published, therefore it needs to be unpublished before it can be updated
- : '' - } -
-
-
-
- - { - if (parseInt(e.target.value, 10) > 0) { - if (oldShift && oldShift.employees.length > parseInt(e.target.value, 10)) Notify.error(`${oldShift.employees.length} talents are scheduled to work on this shift already, delete scheduled employees first.`); - else onChange({ maximum_allowed_employees: e.target.value }); - } - }} - /> -
-
- - onChange({ - minimum_hourly_rate: e.target.value, - has_sensitive_updates: true - })} - /> -
-
-
-
- -
- { - return current.isSameOrAfter(moment(formData.period_starting).startOf('day')) && current.isSameOrBefore(moment(formData.period_ending).startOf('day')); - }} - renderInput={(properties) => { - const { value, ...rest } = properties; - return ; - }} - onChange={(value) => { - - - const getRealDate = (start, end) => { - if (typeof start == 'string') value = moment(start); - - const starting = moment(start.format("MM-DD-YYYY") + " " + start.format("hh:mm a"), "MM-DD-YYYY hh:mm a"); - var ending = moment(start.format("MM-DD-YYYY") + " " + end.format("hh:mm a"), "MM-DD-YYYY hh:mm a"); - - if (typeof starting !== 'undefined' && starting.isValid()) { - if (ending.isBefore(starting)) { - ending = ending.add(1, 'days'); - } - - return { starting_at: starting, ending_at: ending }; - } - return null; - }; - - const mainDate = getRealDate(value, formData.ending_at); - const multipleDates = !Array.isArray(formData.multiple_dates) ? [] : formData.multiple_dates.map(d => getRealDate(d.starting_at, d.ending_at)); - onChange({ ...mainDate, multiple_dates: multipleDates, has_sensitive_updates: true }); - - - }} - - - /> -
-
-
-
-
- - { - const { value, ...rest } = properties; - return ; - }} - onChange={(value) => { - if (typeof value == 'string') value = moment(value); - - const getRealDate = (start, end) => { - const starting = moment(start.format("MM-DD-YYYY") + " " + value.format("hh:mm a"), "MM-DD-YYYY hh:mm a"); - var ending = moment(end); - if (typeof starting !== 'undefined' && starting.isValid()) { - if (ending.isBefore(starting)) { - ending = ending.add(1, 'days'); - } - - return { starting_at: starting, ending_at: ending }; - } - return null; +import React from "react"; +import moment from "moment"; +import PropTypes from "prop-types"; +import JobCoreLogo from '../../../img/logo.png'; +import { Page, Image, Text, View, Document, StyleSheet, PDFDownloadLink } from '@react-pdf/renderer'; + +const BORDER_COLOR = '#000000'; +const BORDER_STYLE = 'solid'; +const COL1_WIDTH = 20; +const COLN_WIDTH = (100 - COL1_WIDTH) / 8; + +const styles = StyleSheet.create({ + body: { + padding: 10 + }, + + image: { + width: "100px", + height: "20px", + float: "right" + }, + image_company: { + width: "40px", + height: "25px", + marginTop: 20 + }, + header: { + fontSize: "30px", + fontWeight: "bold" + }, + table: { + display: "table", + width: "auto", + borderStyle: BORDER_STYLE, + borderColor: BORDER_COLOR, + borderWidth: 1, + borderRightWidth: 0, + borderBottomWidth: 0 + }, + tableRow: { + margin: "auto", + flexDirection: "row" + }, + tableCol1Header: { + width: COL1_WIDTH + '%', + borderStyle: BORDER_STYLE, + borderColor: BORDER_COLOR, + borderBottomColor: '#000', + borderWidth: 1, + borderLeftWidth: 0, + borderTopWidth: 0 + }, + tableColHeader: { + width: COLN_WIDTH + "%", + borderStyle: BORDER_STYLE, + fontWeight: 'bold', + borderColor: BORDER_COLOR, + borderBottomColor: '#000', + borderWidth: 1, + borderLeftWidth: 0, + borderTopWidth: 0 + }, + tableCol1: { + width: COL1_WIDTH + '%', + borderStyle: BORDER_STYLE, + borderColor: BORDER_COLOR, + borderWidth: 1, + borderLeftWidth: 0, + borderTopWidth: 0 + }, + tableCol: { + width: COLN_WIDTH + "%", + borderStyle: BORDER_STYLE, + borderColor: BORDER_COLOR, + borderWidth: 1, + borderLeftWidth: 0, + borderTopWidth: 0 + }, + tableCellHeader: { + margin: 5, + fontSize: 9, + fontWeight: 'bold' + }, + tableCell: { + margin: 5, + fontSize: 9 + } +}); + +const PayrollPeriodReport = ({ period, employer, payments }) => { + console.log(period); + const taxesMagicNumber = 0; + return + {/* */} + + + + + {employer.picture ? ( + + + + ) : null} + + + + {moment(period.starting_at).format('MMMM D') + " - " + moment(period.ending_at).format('LL')} + + + + + STAFF + + + REGULAR HRS + + + OT HRS + + + TOTAL HRS + + + REG + + + OT + + + TOTAL + + + TAXES + + + CHECK AMOUNT + + + + {payments.sort((a, b) => + a.employee.user.last_name.toLowerCase() > b.employee.user.last_name.toLowerCase() ? 1 : -1 + ).map(pay => { + const total_hours = pay.payments.filter(p => p.status === "APPROVED").reduce((total, { regular_hours, over_time }) => total + Number(regular_hours) + Number(over_time), 0); + + const total_amount = pay.payments.filter(p => p.status === "APPROVED").reduce((total, { regular_hours, over_time, hourly_rate }) => total + (Number(regular_hours) + Number(over_time))*Number(hourly_rate) , 0); + const total_reg = total_hours > 40 ? 40 * Number(pay.payments[0]['hourly_rate']) : 0; + const total_ot = total_hours > 40 ? (total_hours - 40) * (Number(pay.payments[0]['hourly_rate'])*1.5): 0; + + const total = pay.payments.filter(p => p.status === 'APPROVED').reduce((incoming, current) => { + return { + overtime: parseFloat(current.regular_hours) + parseFloat(incoming.regular_hours) > 40 ? parseFloat(current.regular_hours) + parseFloat(incoming.regular_hours) - 40 : 0, + over_time: parseFloat(current.over_time) + parseFloat(incoming.over_time), + regular_hours: parseFloat(current.regular_hours) + parseFloat(incoming.regular_hours), + taxes: taxesMagicNumber, + total_ot: total_ot, + total_reg: total_reg, + total_amount: parseFloat(current.regular_hours) + parseFloat(incoming.regular_hours) > 40 ?( + ((((Math.round(total_amount * 100) / 100)/(Math.round(total_hours * 100) / 100))*0.5)*Math.round((total_hours - 40) * 100) / 100 + Math.round(total_amount * 100) / 100).toFixed(2) + ): (Math.round(total_amount * 100) / 100), + status: current.status == 'PAID' && incoming.status == 'PAID' ? 'PAID' : 'UNPAID' }; - - const mainDate = getRealDate(formData.starting_at, formData.ending_at); - const multipleDates = !Array.isArray(formData.multiple_dates) ? [] : formData.multiple_dates.map(d => getRealDate(d.starting_at, d.ending_at)); - onChange({ ...mainDate, multiple_dates: multipleDates, has_sensitive_updates: true }); - - - }} - /> -
-
- - { - const { value, ...rest } = properties; - return ; - }} - onChange={(value) => { - if (typeof value == 'string') value = moment(value); - - const getRealDate = (start, end) => { - - const starting = start; - var ending = moment(start.format("MM-DD-YYYY") + " " + value.format("hh:mm a"), "MM-DD-YYYY hh:mm a"); - - if (typeof starting !== 'undefined' && starting.isValid()) { - if (ending.isBefore(starting)) { - ending = ending.add(1, 'days'); - } - - return { starting_at: starting, ending_at: ending }; - } - return null; - }; - - const mainDate = getRealDate(formData.starting_at, formData.ending_at); - const multipleDates = !Array.isArray(formData.multiple_dates) ? [] : formData.multiple_dates.map(d => getRealDate(d.starting_at, d.ending_at)); - onChange({ ...mainDate, multiple_dates: multipleDates, has_sensitive_updates: true }); - - }} - /> -
-
-
-
- - { - const _shift = selectedOption.value; - if (_shift) { - if (_shift == 'new_shift') bar.show({ - slug: "create_expired_shift", data: { - employeesToAdd: [{ label: employee.user.first_name + " " + employee.user.last_name, value: employee.id }], - // Dates are in utc so I decided to change it to local time - starting_at: moment(period.starting_at), - ending_at: moment(period.starting_at).add(2, "hours"), - period_starting: moment(period.starting_at), - period_ending: moment(period.ending_at), - shift: _shift, - application_restriction: 'SPECIFIC_PEOPLE' - } - }); - - else { - setShift(_shift); - setBreaktime(0); - } - } - }} - options={possibleShifts ? [{ label: "Add a shift", value: 'new_shift', component: EditOrAddExpiredShift }].concat(possibleShifts) : [{ label: "Add a shift", value: 'new_shift', component: EditOrAddExpiredShift }]} - - > - - - : - -
-

- {shift.starting_at.format('ddd, ll')} -

- {shift.position.title || shift.position.label} @ - {shift.venue.title} -
- {
- { - (typeof shift.price == 'string') ? - (shift.price === '0.0') ? '' : ${shift.price} - : - {shift.price.currencySymbol || '$'}{shift.price.amount || shift.minimum_hourly_rate} - }{" "} - {clockin &&
- {clockin.latitude_in > 0 && - - 0.2 ? "text-danger" : ""}`}> - In - - - - } - {clockin.latitude_out > 0 && - - 0.2 ? "text-danger" : ""}`}> - Out - - - } - {clockin.author != employee.user.profile.id ? - Clocked in by a supervisor}> - - - : !moment(payment.created_at).isSame(moment(payment.updated_at)) && payment.status === "PENDING" ? - Previously updated by supervisor}> - - - : - null - } -
} -
} - - } - - {readOnly ? -

{(approvedTimes.in !== undefined) && approvedTimes.in.format('LT')}

- : - { - if (value && value!==undefined) { - let ended_at = approvedTimes.out; - if (value.isAfter(ended_at)) ended_at = moment(ended_at).add(1, 'days'); - if(value && value !== undefined) setApprovedTimes({ ...approvedTimes, in: value, out: ended_at }); - } - }} - value={approvedTimes.in} - use12Hours - /> - } - ({shiftStartTime}) - - - {readOnly ? -

{(approvedTimes.out !== undefined) && approvedTimes.out.format('LT')}

- : - { - if (d1) { - const starting = approvedTimes.in; - let ended_at = moment(clockin.started_at).set({ hour: d1.get('hour'), minute: d1.get('minute'), second: d1.get('second') }); - if (starting.isAfter(ended_at)) ended_at = moment(ended_at).add(1, 'days'); - if(ended_at && ended_at !== undefined) setApprovedTimes({ ...approvedTimes, out: ended_at }); - } - }} - value={approvedTimes.out} - use12Hours - /> - } - - ({shiftEndTime}) - - {shiftNextDay && - This shift ended on the next day}> - - - } - {clockin.automatically_closed && - Automatically clocked out}> - - - } - - -

{clockinHours}

- (Plan: {plannedHours}) - - {readOnly ? - {payment.breaktime_minutes} min - : - - { - e.target.value != '' ? setBreaktime(Math.abs(parseInt(e.target.value))) : setBreaktime(0)} value={breaktime} - /> - } - minutes - - } - {clockInTotalHoursAfterBreak} - {clockin.shift || !readOnly ? diff : "-"} - {readOnly ? - - {payment.status === "APPROVED" ? - : payment.status === "REJECTED" ? - : `${payment.status}<${readOnly ? "true" : "false"}` - } - {period.status === "OPEN" && (payment.status === "APPROVED" || payment.status === "REJECTED") && - onUndo(payment)} className="fas fa-undo ml-2 pointer"> - } - - : - - -
; - } - if(!periods) return "Loading..."; - let note = null; - if (periods && periods.length > 0) { - const end = moment(periods[0].ending_at); - end.add(7, 'days'); - if (end.isBefore(TODAY())) note = "Payroll was generated until " + end.format('M d'); - } - return (
-
-
-
-
-

Select a timesheet:

-
    -
    - {periods.length === 0 &&

    No previous payroll periods have been found

    } - {periods.map(p => - history.push(`/payroll/period/${p.id}`)} - > -
    - {p.status === "FINALIZED" ? - : p.status === "OPEN" ? - : '' - } -
    - From {moment(p.starting_at).format('MMM DD, YYYY')} to {moment(p.ending_at).format('MMM DD, YYYY')} -

    0 ? 'badge-secondary' : 'badge-info'}`}>{p.total_payments} Payments

    -
    - )} - {!noMorePeriods && Array.isArray(periods) && periods.length > 0 ? ( -
    -
    - -
    -
    - ) : null} -
    - -
-
-
- - -
); -}; -SelectTimesheet.propTypes = { - onSave: PropTypes.func.isRequired, - onCancel: PropTypes.func.isRequired, - history: PropTypes.object.isRequired, - onChange: PropTypes.func, - formData: PropTypes.object, - catalog: PropTypes.object //contains the data needed for the form to load -}; - -export const SelectShiftPeriod = ({ catalog, formData, onChange, onSave, onCancel, history }) => { - const { bar } = useContext(Theme.Context); - - let note = null; - if (formData.periods.length > 0) { - const end = moment(formData.periods[0].ending_at); - end.add(7, 'days'); - if (end.isBefore(TODAY())) note = "Payroll was generated until " + end.format('MM dd'); - } - return (
-
-
-
-
-
-

Select a payment period:

-