diff --git a/client/src/constants/constants.js b/client/src/constants/constants.js index 22e9725..dca00cb 100644 --- a/client/src/constants/constants.js +++ b/client/src/constants/constants.js @@ -1,3 +1,5 @@ +export const CONTAINER_WIDTH_PERCENTAGE = 90; + export const defaultDateFormat = 'YYYY-MM-DD'; export const doorLockRelatedWithReservationIncidentHeaders = [ @@ -5,6 +7,7 @@ export const doorLockRelatedWithReservationIncidentHeaders = [ 'resourceName', 'memberName', 'reservation', + 'doorLockTimestamps', 'incidentType', 'feeDescription', 'totalChargeFee' diff --git a/client/src/scenes/Home/index.js b/client/src/scenes/Home/index.js index 21c2698..33d192c 100644 --- a/client/src/scenes/Home/index.js +++ b/client/src/scenes/Home/index.js @@ -4,12 +4,13 @@ import { Container, Message } from 'semantic-ui-react'; import MainMenu from '../../components/MainMenu'; import { mainMenuItems } from '../../constants/menuItems'; +import {CONTAINER_WIDTH_PERCENTAGE} from "../../constants/constants"; class Home extends Component { render () { return ( - +

SIMA SPACE


diff --git a/client/src/scenes/IncidentsReport/index.js b/client/src/scenes/IncidentsReport/index.js index 951e642..891f87a 100644 --- a/client/src/scenes/IncidentsReport/index.js +++ b/client/src/scenes/IncidentsReport/index.js @@ -8,6 +8,7 @@ import MemberIncidentsTables from '../../components/MemberIncidentsTables'; import GenerateFeesInORDButton from '../../components/GenerateFeesInORDButton'; import { fetchIncidents } from '../../store/actions'; +import { CONTAINER_WIDTH_PERCENTAGE } from '../../constants/constants'; class IncidentsReport extends Component { state = {dateRange: null}; @@ -33,7 +34,7 @@ class IncidentsReport extends Component { } return ( - +

Incidents Report


diff --git a/client/src/scenes/MemberPracticeSummaryReport/index.js b/client/src/scenes/MemberPracticeSummaryReport/index.js index fcec497..aaba9ad 100644 --- a/client/src/scenes/MemberPracticeSummaryReport/index.js +++ b/client/src/scenes/MemberPracticeSummaryReport/index.js @@ -5,6 +5,7 @@ import { Container, Button, Loader, Input, Message, Grid } from 'semantic-ui-rea import MainMenu from '../../components/MainMenu'; import { fetchMemberPracticeSummaryReport } from '../../store/actions'; +import {CONTAINER_WIDTH_PERCENTAGE} from "../../constants/constants"; class MemberPracticeSummaryReport extends Component { @@ -54,7 +55,7 @@ class MemberPracticeSummaryReport extends Component { error = fetchReportError ? fetchReportError : error; return ( - +

Member Practice Summary Report


diff --git a/client/src/scenes/RoomOfficeNameMapping/components/SingleMapping.js b/client/src/scenes/RoomOfficeNameMapping/components/SingleMapping.js index 2e7d36d..61daa4a 100644 --- a/client/src/scenes/RoomOfficeNameMapping/components/SingleMapping.js +++ b/client/src/scenes/RoomOfficeNameMapping/components/SingleMapping.js @@ -76,67 +76,71 @@ class SingleMapping extends Component { }; render() { - const { singleMapping: { officeSlug, resourceSlug } } = this.props; - const { officeId, resourceId, officeOptions, allResourceOptions, pendingMappings } = this.props; - const { showDeletePrompt, newOfficeId, newResourceId } = this.state; + try { + const {singleMapping: {officeSlug, resourceSlug}} = this.props; + const {officeId, resourceId, officeOptions, allResourceOptions, pendingMappings} = this.props; + const {showDeletePrompt, newOfficeId, newResourceId} = this.state; - const selectedOfficeId = newOfficeId ? newOfficeId : officeId; - const selectedResourceId = newResourceId ? newResourceId : resourceId; + const selectedOfficeId = newOfficeId ? newOfficeId : officeId; + const selectedResourceId = newResourceId ? newResourceId : resourceId; - const resourceOptions = allResourceOptions && officeId ? allResourceOptions[selectedOfficeId].roomOptions : []; + const resourceOptions = allResourceOptions && officeId ? allResourceOptions[selectedOfficeId].roomOptions : []; - const enableActions = !pendingMappings; - const enableSave = enableActions && ((newOfficeId !== null) || (newResourceId !== null)); - const saveIconColor = enableSave ? 'green' : null; + const enableActions = !pendingMappings; + const enableSave = enableActions && ((newOfficeId !== null) || (newResourceId !== null)); + const saveIconColor = enableSave ? 'green' : null; - return ( - - - - - - - + - - - - - - - - - - ); + + + + + + + + + + + + + + + ); + }catch (e) { + return null; + } } } diff --git a/client/src/scenes/RoomOfficeNameMapping/index.js b/client/src/scenes/RoomOfficeNameMapping/index.js index 19fa6ec..6b36438 100644 --- a/client/src/scenes/RoomOfficeNameMapping/index.js +++ b/client/src/scenes/RoomOfficeNameMapping/index.js @@ -5,6 +5,7 @@ import { Container, Message, Loader, Table } from 'semantic-ui-react'; import MainMenu from '../../components/MainMenu'; import { fetchMappings } from '../../store/actions'; import SingleMapping from './components/SingleMapping'; +import {CONTAINER_WIDTH_PERCENTAGE} from "../../constants/constants"; class RoomOfficeNameMapping extends Component { @@ -47,7 +48,7 @@ class RoomOfficeNameMapping extends Component { }); return ( - +

Room Office Mapping

diff --git a/client/src/scenes/SpecificMemberIncidentsReport/index.js b/client/src/scenes/SpecificMemberIncidentsReport/index.js index 0ed11bd..5e1c0fb 100644 --- a/client/src/scenes/SpecificMemberIncidentsReport/index.js +++ b/client/src/scenes/SpecificMemberIncidentsReport/index.js @@ -10,6 +10,7 @@ import MemberIncidentsTables from '../../components/MemberIncidentsTables'; import GenerateFeesInORDButton from '../../components/GenerateFeesInORDButton'; import { fetchMemberIncidents } from '../../store/actions'; +import {CONTAINER_WIDTH_PERCENTAGE} from "../../constants/constants"; class SpecificMemberIncidentsReport extends Component { constructor(props){ @@ -48,7 +49,7 @@ class SpecificMemberIncidentsReport extends Component { const addFeesButtonDisabled = !memberId || !dateRange || loading; return ( - +

Member Incidents Report


diff --git a/client/src/scenes/UploadDLockData/index.js b/client/src/scenes/UploadDLockData/index.js index 8d245c8..8aedf72 100644 --- a/client/src/scenes/UploadDLockData/index.js +++ b/client/src/scenes/UploadDLockData/index.js @@ -4,10 +4,11 @@ import { Container, Form } from 'semantic-ui-react'; import MainMenu from '../../components/MainMenu'; import FileUpload from './components/FileUpload'; import UploadResults from './components/UploadResults'; +import {CONTAINER_WIDTH_PERCENTAGE} from "../../constants/constants"; function UploadDLockData() { return ( - +

DLock Data


diff --git a/constants/constants.js b/constants/constants.js index 9cffa88..6ee5812 100644 --- a/constants/constants.js +++ b/constants/constants.js @@ -14,37 +14,37 @@ const unlockedIncidentLevelsPrices = { id: 0, title: 'UNLOCKED_0', price: parseInt(process.env.UNLOCK_0) || 0, - description: 'First month - warning', + description: 'first month - warning', }, UNLOCKED_1: { id: 1, title: 'UNLOCKED_1', price: parseInt(process.env.UNLOCK_1) || 10, - description: 'Second month', + description: 'second month', }, UNLOCKED_2: { id: 2, title: 'UNLOCKED_2', price: parseInt(process.env.UNLOCK_2) || 20, - description: 'Third month', + description: 'third month', }, UNLOCKED_3: { id: 3, title: 'UNLOCKED_3', price: parseInt(process.env.UNLOCK_3) || 30, - description: 'Fourth month', + description: 'fourth month', }, UNLOCKED_4: { id: 4, title: 'UNLOCKED_4', price: parseInt(process.env.UNLOCK_4) || 40, - description: 'Fifth month', + description: 'fifth month', }, UNLOCKED_5: { id: 5, title: 'UNLOCKED_5', price: parseInt(process.env.UNLOCK_5) || 50, - description: 'Sixth month and onward', + description: 'sixth month and onward', } }; const csvParserErrors = { @@ -95,14 +95,14 @@ const incidentType = { }; const incidentTypeExplanations = {}; -incidentTypeExplanations[incidentType.UNLOCKED_INCIDENT_RELATED_WITH_RESERVATION] = 'Door left unlocked'; -incidentTypeExplanations[incidentType.UNLOCKED_INCIDENT_STANDALONE] = 'Door left unlocked'; -incidentTypeExplanations[incidentType.UNSCHEDULED_INCIDENT_BEFORE_RESERVATION] = 'Room used before reservation'; -incidentTypeExplanations[incidentType.UNSCHEDULED_INCIDENT_AFTER_RESERVATION] = 'Room used after reservation'; -incidentTypeExplanations[incidentType.UNSCHEDULED_INCIDENT_STANDALONE] = 'Room used without reservation'; -incidentTypeExplanations[incidentType.BOOKING_MOVED_TO_ANOTHER_DAY] = 'Reservation moved to another day'; -incidentTypeExplanations[incidentType.BOOKING_SHORTENED] = 'Reservation shortened after grace period'; -incidentTypeExplanations[incidentType.BOOKING_CANCELED_LATE] = 'Reservation cancelled after grace period'; +incidentTypeExplanations[incidentType.UNLOCKED_INCIDENT_RELATED_WITH_RESERVATION] = 'door left unlocked'; +incidentTypeExplanations[incidentType.UNLOCKED_INCIDENT_STANDALONE] = 'door left unlocked'; +incidentTypeExplanations[incidentType.UNSCHEDULED_INCIDENT_BEFORE_RESERVATION] = 'room used before reservation'; +incidentTypeExplanations[incidentType.UNSCHEDULED_INCIDENT_AFTER_RESERVATION] = 'room used after reservation'; +incidentTypeExplanations[incidentType.UNSCHEDULED_INCIDENT_STANDALONE] = 'room used without reservation'; +incidentTypeExplanations[incidentType.BOOKING_MOVED_TO_ANOTHER_DAY] = 'reservation moved to another day'; +incidentTypeExplanations[incidentType.BOOKING_SHORTENED] = 'reservation shortened after grace period'; +incidentTypeExplanations[incidentType.BOOKING_CANCELED_LATE] = 'reservation cancelled after grace period'; const UI_TIMEZONE = process.env.UI_TIMEZONE || 'America/Los_Angeles'; diff --git a/services/integration/invoiceIntegration.js b/services/integration/invoiceIntegration.js index b2a49b0..5e08211 100644 --- a/services/integration/invoiceIntegration.js +++ b/services/integration/invoiceIntegration.js @@ -17,6 +17,7 @@ const createFeeFromIncident = (incident) => { memberId, officeId, officeName, + officeSlug, resourceName, oldResourceName, newResourceName, @@ -45,6 +46,8 @@ const createFeeFromIncident = (incident) => { let bookingTimeExplanation = ''; let incidentTimeExplanation = ''; + let spacing = ''; + let roomExplanation = ''; let dateExplanation = ''; @@ -62,7 +65,8 @@ const createFeeFromIncident = (incident) => { switch (incidentTypeNumber) { case incidentType.UNLOCKED_INCIDENT_RELATED_WITH_RESERVATION: - roomExplanation = resourceName; + spacing = ' '; + roomExplanation = resourceName || 'Unknown'; dateExplanation = bookingStartMoment.clone().startOf('day').format('MMM DD'); bookingTimeExplanation = `[${bookingStartMoment.clone().format('HH:mm')} to ${bookingEndMoment.clone().format('HH:mm')}]`; incidentTimeExplanation = `unlock : ${unlockMoment.clone().format('HH:mm')}`; @@ -74,7 +78,8 @@ const createFeeFromIncident = (incident) => { quantity = 1.00; break; case incidentType.UNSCHEDULED_INCIDENT_BEFORE_RESERVATION: - roomExplanation = resourceName; + spacing = ' '; + roomExplanation = resourceName || 'Unknown'; dateExplanation = bookingStartMoment.clone().startOf('day').format('MMM DD'); bookingTimeExplanation = `[${bookingStartMoment.clone().format('HH:mm')} to ${bookingEndMoment.clone().format('HH:mm')}]`; incidentTimeExplanation = `unlock : ${unlockMoment.clone().format('HH:mm')}`; @@ -86,7 +91,8 @@ const createFeeFromIncident = (incident) => { quantity = +timeIntervalsToCharge.toFixed(2); break; case incidentType.UNSCHEDULED_INCIDENT_AFTER_RESERVATION: - roomExplanation = resourceName; + spacing = ' '; + roomExplanation = resourceName || 'Unknown'; dateExplanation = bookingStartMoment.clone().startOf('day').format('MMM DD'); bookingTimeExplanation = `[${bookingStartMoment.clone().format('HH:mm')} to ${bookingEndMoment.clone().format('HH:mm')}]`; incidentTimeExplanation = `lock : ${lockMoment.clone().format('HH:mm')}`; @@ -98,7 +104,8 @@ const createFeeFromIncident = (incident) => { quantity = +timeIntervalsToCharge.toFixed(2); break; case incidentType.UNLOCKED_INCIDENT_STANDALONE: - roomExplanation = resourceName; + spacing = ' '; + roomExplanation = resourceName || 'Unknown'; dateExplanation = unlockMoment.clone().startOf('day').format('MMM DD'); bookingTimeExplanation = `[${unlockMoment.clone().format('HH:mm')} to ${lockMoment.clone().format('HH:mm')}]`; incidentTimeExplanation = `unlock : ${unlockMoment.clone().format('HH:mm')}`; @@ -110,7 +117,8 @@ const createFeeFromIncident = (incident) => { quantity = 1.00; break; case incidentType.UNSCHEDULED_INCIDENT_STANDALONE: - roomExplanation = resourceName; + spacing = ' '; + roomExplanation = resourceName || 'Unknown'; dateExplanation = unlockMoment.clone().startOf('day').format('MMM DD'); bookingTimeExplanation = `[${unlockMoment.clone().format('HH:mm')} to ${lockMoment.clone().format('HH:mm')}]`; //incidentTimeExplanation = `unlock : ${unlockMoment.clone().format('HH:mm')}, lock : ${lockMoment.clone().format('HH:mm')}`; @@ -121,12 +129,13 @@ const createFeeFromIncident = (incident) => { quantity = +timeIntervalsToCharge.toFixed(2); break; case incidentType.BOOKING_MOVED_TO_ANOTHER_DAY: + spacing = ' '; // if (oldResourceName !== newResourceName){ // roomExplanation = `${oldResourceName} -> ${newResourceName}`; // }else{ // roomExplanation = oldResourceName; // } - roomExplanation = newResourceName; + roomExplanation = newResourceName || 'Unknown'; // dateExplanation = `${oldBookingStartMoment.clone().format('ddd, MMM DD')} -> ${newBookingStartMoment.clone().format('ddd, MMM DD')}`; dateExplanation = `${newBookingStartMoment.clone().format('MMM DD')}`; @@ -140,18 +149,35 @@ const createFeeFromIncident = (incident) => { quantity = 1.00; break; case incidentType.BOOKING_SHORTENED: + spacing = ' '; // if (oldResourceName !== newResourceName){ // roomExplanation = `${oldResourceName} -> ${newResourceName}`; // }else{ // roomExplanation = oldResourceName; // } - roomExplanation = newResourceName; + roomExplanation = newResourceName || 'Unknown'; // dateExplanation = `${oldBookingStartMoment.clone().format('ddd, MMM DD')}`; + const oldBookingDuration = oldBookingEndMoment.diff(oldBookingStartMoment, "minutes", false); + const durationInHours = Math.floor(oldBookingDuration / 60); + const durationInMinutes = Math.floor(oldBookingDuration % 60); + let durationAsText = ''; + if (durationInHours !== 0){ + durationAsText += durationInHours + ' hour'; + if (durationInHours === 1){ + durationAsText += ' '; + }else{ + durationAsText += 's '; + } + } + durationAsText += durationInMinutes + ' minute'; + if (durationInMinutes > 1){ + durationAsText += 's'; + } dateExplanation = `${newBookingStartMoment.clone().format('MMM DD')}`; bookingTimeExplanation = `[${newBookingStartMoment.clone().format('HH:mm')} to ${newBookingEndMoment.clone().format('HH:mm')}]`; - incidentTimeExplanation = `shortened on : ${incidentTimestampMoment.clone().format('MMM DD, HH:mm')}`; - incidentExplanation += `, ${incidentTimeExplanation}`; + incidentTimeExplanation = `reservation shortened from ${durationAsText} on : ${incidentTimestampMoment.clone().format('MMM DD, HH:mm')}`; + incidentExplanation = `${incidentTimeExplanation}`; date = incidentTimestampMoment.clone().startOf('day').format(); @@ -159,7 +185,8 @@ const createFeeFromIncident = (incident) => { quantity = 1.00; break; case incidentType.BOOKING_CANCELED_LATE: - roomExplanation = oldResourceName; + spacing = ' '; + roomExplanation = oldResourceName || 'Unknown'; // dateExplanation = `${oldBookingStartMoment.clone().format('ddd, MMM DD')}`; dateExplanation = `${oldBookingStartMoment.clone().format('MMM DD')}`; bookingTimeExplanation = `[${oldBookingStartMoment.clone().format('HH:mm')} to ${oldBookingEndMoment.clone().format('HH:mm')}]`; @@ -173,7 +200,7 @@ const createFeeFromIncident = (incident) => { break; } - const formattedName = `${dateExplanation} ${bookingTimeExplanation} ${roomExplanation}, ${officeName}, ${incidentExplanation}`; + const formattedName = `${officeSlug}, ${dateExplanation} ${bookingTimeExplanation}${spacing}${roomExplanation}, ${incidentExplanation}`; return { name: formattedName, @@ -202,14 +229,14 @@ const createFeeFromBooking = (booking, resourceMappings) => { const endMoment = moment.tz(end, DEFAULT_DATE_FORMAT, timezone); const reservationLength = endMoment.diff(startMoment, 'hours', true); - const officeName = officesMap[officeId].officeName || 'Unknown'; + const officeSlug = officesMap[officeId].officeSlug || 'Unknown'; const resourceName = resourcesMap[resourceId].resourceName || 'Unknown'; const formattedDate = startMoment.clone().startOf('day').format('MMM DD'); const formattedStartTime = startMoment.format('HH:mm'); const formattedEndTime = endMoment.format('HH:mm'); - const formattedName = `${formattedDate} [${formattedStartTime} to ${formattedEndTime}] ${resourceName}, ${officeName}`; + const formattedName = `${officeSlug}, ${formattedDate} [${formattedStartTime} to ${formattedEndTime}] ${resourceName}`; return { name: formattedName, @@ -330,7 +357,7 @@ const getMembersFeesForDateRange = (dateRange, memberIds) => { allIncidents.forEach((incident) => { const feeFromIncident = createFeeFromIncident(incident); if (feeFromIncident){ - allFees.push(createFeeFromIncident(incident)); + allFees.push(feeFromIncident); } const incidentsValuableForDiscountCalculation = [ @@ -464,7 +491,7 @@ const getMembersFeesForDateRange = (dateRange, memberIds) => { fee.team = memberIdTeamMappings[member] || null; if (teamId){ //if member is part of the company, add name to the fee description/name - fee.name += `, ${memberName}`; + fee.name = `${memberName}, ${fee.name}`; } } }); diff --git a/services/integration/reports.js b/services/integration/reports.js index 4d054e3..3717112 100644 --- a/services/integration/reports.js +++ b/services/integration/reports.js @@ -225,6 +225,7 @@ const getAllIncidents = (dateRange, memberIds) => { resourceName: resourcesMap[unlockedIncident.resourceId].resourceName, officeId: resourcesMap[unlockedIncident.resourceId].officeId, officeName: officesMap[resourcesMap[unlockedIncident.resourceId].officeId].officeName, + officeSlug: officesMap[resourcesMap[unlockedIncident.resourceId].officeId].officeSlug, bookingStart: formatTime(unlockedIncident.bookingStart), bookingEnd: formatTime(unlockedIncident.bookingEnd), bookingStartRaw: unlockedIncident.bookingStart, @@ -255,6 +256,7 @@ const getAllIncidents = (dateRange, memberIds) => { resourceName: resourcesMap[unscheduledIncident.resourceId].resourceName, officeId: resourcesMap[unscheduledIncident.resourceId].officeId, officeName: officesMap[resourcesMap[unscheduledIncident.resourceId].officeId].officeName, + officeSlug: officesMap[resourcesMap[unscheduledIncident.resourceId].officeId].officeSlug, bookingStart: formatTime(unscheduledIncident.bookingStart), bookingEnd: formatTime(unscheduledIncident.bookingEnd), bookingStartRaw: unscheduledIncident.bookingStart, @@ -292,6 +294,7 @@ const getAllIncidents = (dateRange, memberIds) => { const newResourceName = newResource ? newResource.resourceName : null; const officeId = oldResource.officeId; const officeName = officesMap[officeId].officeName; + const officeSlug = officesMap[officeId].officeSlug; allIncidents.push({ incidentId: id, memberId, @@ -300,6 +303,7 @@ const getAllIncidents = (dateRange, memberIds) => { newResourceName, officeId, officeName, + officeSlug, oldBookingStart: formatTime(oldBookingStart), oldBookingEnd: formatTime(oldBookingEnd), newBookingStart: formatTime(newBookingStart), diff --git a/services/officeRnD/bookings.js b/services/officeRnD/bookings.js index bea8189..d7b508e 100644 --- a/services/officeRnD/bookings.js +++ b/services/officeRnD/bookings.js @@ -202,7 +202,6 @@ const bulkWriteReservationsWithChangesTracking = (reservations, resourcesMap) => }else{ hourlyRate = resourceId ? resourcesMap[resourceId].price.price : 0; } - console.log(hourlyRate); instance.setDataValue('hourlyRate', hourlyRate); } } diff --git a/services/officeRnD/resources.js b/services/officeRnD/resources.js index 4d8024c..33b71d3 100644 --- a/services/officeRnD/resources.js +++ b/services/officeRnD/resources.js @@ -15,6 +15,7 @@ const fetchOffices = () => { cleanedOffices.push({ officeId: office['_id'], officeName: office.name, + officeSlug: office.description, }); }); resolve(cleanedOffices);