From d4f823ff72d68be1a4034985154596d7fe912d29 Mon Sep 17 00:00:00 2001 From: Bilal Catic Date: Wed, 20 Nov 2019 14:53:53 +0100 Subject: [PATCH 1/7] add deleted field to the unlocked/unscheduled incidents table and model --- ...-deleted-column-for-unlocked-incidents-table.js | 14 ++++++++++++++ ...leted-column-for-unscheduled-incidents-table.js | 14 ++++++++++++++ models/unlockedIncident.js | 1 + models/unscheduledIncident.js | 1 + 4 files changed, 30 insertions(+) create mode 100644 migrations/20191120144357-add-deleted-column-for-unlocked-incidents-table.js create mode 100644 migrations/20191120144439-add-deleted-column-for-unscheduled-incidents-table.js diff --git a/migrations/20191120144357-add-deleted-column-for-unlocked-incidents-table.js b/migrations/20191120144357-add-deleted-column-for-unlocked-incidents-table.js new file mode 100644 index 0000000..a3bcb91 --- /dev/null +++ b/migrations/20191120144357-add-deleted-column-for-unlocked-incidents-table.js @@ -0,0 +1,14 @@ +'use strict'; + +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.addColumn('unlockedIncidents', 'deleted', { + type: Sequelize.BOOLEAN, + defaultValue: false, + }); + }, + + down: (queryInterface, Sequelize) => { + return queryInterface.removeColumn('unlockedIncidents', 'deleted'); + } +}; diff --git a/migrations/20191120144439-add-deleted-column-for-unscheduled-incidents-table.js b/migrations/20191120144439-add-deleted-column-for-unscheduled-incidents-table.js new file mode 100644 index 0000000..52b9681 --- /dev/null +++ b/migrations/20191120144439-add-deleted-column-for-unscheduled-incidents-table.js @@ -0,0 +1,14 @@ +'use strict'; + +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.addColumn('unscheduledIncidents', 'deleted', { + type: Sequelize.BOOLEAN, + defaultValue: false, + }); + }, + + down: (queryInterface, Sequelize) => { + return queryInterface.removeColumn('unscheduledIncidents', 'deleted'); + } +}; diff --git a/models/unlockedIncident.js b/models/unlockedIncident.js index d77c126..dd0ebdf 100644 --- a/models/unlockedIncident.js +++ b/models/unlockedIncident.js @@ -22,6 +22,7 @@ module.exports = (sequelize, DataTypes) => { }, incidentLevelPrice: DataTypes.FLOAT, unlockTimestamp: DataTypes.DATE, + deleted: DataTypes.BOOLEAN }, {}); unlockedIncident.associate = function(models) { // associations can be defined here diff --git a/models/unscheduledIncident.js b/models/unscheduledIncident.js index c24ce79..04ac39f 100644 --- a/models/unscheduledIncident.js +++ b/models/unscheduledIncident.js @@ -19,6 +19,7 @@ module.exports = (sequelize, DataTypes) => { totalChargeFee: DataTypes.FLOAT, unlockTimestamp: DataTypes.DATE, lockTimestamp: DataTypes.DATE, + deleted: DataTypes.BOOLEAN }, {}); unscheduledIncident.associate = function(models) { // associations can be defined here From 3d051766b1d3646c700532e7392b1093b0ebb667 Mon Sep 17 00:00:00 2001 From: Bilal Catic Date: Wed, 20 Nov 2019 15:26:20 +0100 Subject: [PATCH 2/7] fetch only non-deleted unlocked/unscheduled incidents --- services/integration/doorLockCharges.js | 5 ++++- services/integration/reports.js | 8 ++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/services/integration/doorLockCharges.js b/services/integration/doorLockCharges.js index 582ba28..0a1d706 100644 --- a/services/integration/doorLockCharges.js +++ b/services/integration/doorLockCharges.js @@ -18,7 +18,8 @@ const { getAllFinishedBookings, getFirstPreviousBooking, getFirstNextBooking } = const getSortedIncidentsForMember = (memberId) => { const attributes = ['bookingStart', 'incidentLevel', 'incidentLevelPrice', 'unlockTimestamp']; const filters = { - memberId + memberId, + deleted: false }; const order = [['unlockTimestamp', 'DESC']]; @@ -59,6 +60,7 @@ const insertUnscheduledIncidents = (incidents) => { bookingEnd: end, unlockTimestamp, lockTimestamp, + deleted: false }, defaults: {...incidentForDB}, })); @@ -93,6 +95,7 @@ const insertUnlockedIncidents = (incidents) => { bookingEnd: end, unlockTimestamp, incidentLevel, + deleted: false }, defaults: {...incidentForDB}, })); diff --git a/services/integration/reports.js b/services/integration/reports.js index 3717112..c605c5c 100644 --- a/services/integration/reports.js +++ b/services/integration/reports.js @@ -18,7 +18,9 @@ const { getChargedCanceledReservations } = require('../integration/bookingChange const getUnlockedIncidents = (startDate, endDate, memberIds) => { const attributes = ['id', 'reservationId', 'memberId', 'resourceId', 'bookingStart', 'bookingEnd', 'unlockTimestamp', 'incidentLevel', 'incidentLevelPrice']; - const filters = {}; + const filters = { + deleted: false + }; if (startDate && endDate) { const bookingStartCondition = { @@ -76,7 +78,9 @@ const getUnscheduledIncidents = (startDate, endDate, memberIds) => { 'totalChargeFee' ]; - const filters = {}; + const filters = { + deleted: false + }; if (startDate && endDate) { const bookingStartCondition = { From 8a3db0d481ed44d9d4e52e719507086685973592 Mon Sep 17 00:00:00 2001 From: Bilal Catic Date: Thu, 21 Nov 2019 07:12:50 +0100 Subject: [PATCH 3/7] add deleteFees route and implement logic --- controllers/integration.js | 39 ++++++++++++++++++++ routes/index.js | 2 + services/integration/bookingChangeCharges.js | 11 ++++++ services/integration/doorLockCharges.js | 25 ++++++++++++- 4 files changed, 76 insertions(+), 1 deletion(-) diff --git a/controllers/integration.js b/controllers/integration.js index be3ffed..47c0c0f 100644 --- a/controllers/integration.js +++ b/controllers/integration.js @@ -9,6 +9,8 @@ const { deleteFeesFromORD, addFeesToORD } = require('../services/officeRnD/fees' const { reformatMembershipsName } = require('../services/officeRnD/memberships'); const { checkBookingChanges } = require('../services/integration/checkBookingChange'); const { checkIfProcessing } = require('../services/integration/processingStatus'); +const { deleteUnlockedIncidentsById, deleteUnscheduledIncidentsById } = require('../services/integration/doorLockCharges'); +const { deleteBookingChangeIncidentsById } = require('../services/integration/bookingChangeCharges'); const { UI_TIMEZONE, DEFAULT_DATE_FORMAT, ALLOW_SENDING_FEES, integrationServiceErrors } = require('../constants/constants'); @@ -80,6 +82,8 @@ const updateMapping = (req, res) => { }; const getAllIncidentsController = (req, res) => { + console.log('get all incidents : '); + console.log(req.params); const dateRange = { startDate: req.params.startDate, endDate: req.params.endDate, @@ -175,6 +179,40 @@ const addFees = (req, res) => { } }; +const deleteFees= (req, res) => { + const deleteData = req.body; + console.log('Delete fees request : '); + console.log(req.body); + const dateRange = deleteData.dateRange ? deleteData.dateRange : null; + const incidents = deleteData.incidentsToDelete ? deleteData.incidentsToDelete : null; + + const unlockedIncidentIds = incidents.unlockedIncidentIds ? incidents.unlockedIncidentIds : []; + const unscheduledIncidentIds = incidents.unscheduledIncidentIds ? incidents.unscheduledIncidentIds : []; + const bookingChangeIncidentIds = incidents.bookingChangeIncidentIds ? incidents.bookingChangeIncidentIds : []; + + req.params.startDate = dateRange.startDate ? dateRange.startDate : null; + req.params.endDate = dateRange.endDate ? dateRange.endDate : null; + + if (Array.isArray(unlockedIncidentIds) && Array.isArray(unscheduledIncidentIds) && Array.isArray(bookingChangeIncidentIds)){ + const asyncDeleteActions = [ + deleteUnlockedIncidentsById(unlockedIncidentIds), + deleteUnscheduledIncidentsById(unscheduledIncidentIds), + deleteBookingChangeIncidentsById(bookingChangeIncidentIds) + ]; + + Promise.all(asyncDeleteActions) + .then(() => { + getAllIncidentsController(req, res); + }) + .catch((error) => { + console.log('Error deleting incidents : ', error); + res.status(500).send(); + }); + }else{ + getAllIncidentsController(req, res); + } +}; + const checkProcessingStatus = (req, res) => { checkIfProcessing() .then((processing) => { @@ -227,4 +265,5 @@ module.exports = { addFees, checkProcessingStatus, getPracticeSummaryReport, + deleteFees }; diff --git a/routes/index.js b/routes/index.js index c8d30fe..e35c18d 100644 --- a/routes/index.js +++ b/routes/index.js @@ -13,6 +13,7 @@ const { addFees, checkProcessingStatus, getPracticeSummaryReport, + deleteFees } = require('../controllers/integration'); const { calculateDoorLockCharges } = require('../services/integration/doorLockCharges'); @@ -34,6 +35,7 @@ router.get('/integration/report/allIncidents/:startDate/:endDate', getAllInciden router.get('/officeRnD/membersList', fetchMembersList); router.post('/integration/addFees', addFees); +router.delete('/integration/fees', deleteFees); router.get('/integration/processing', checkProcessingStatus); diff --git a/services/integration/bookingChangeCharges.js b/services/integration/bookingChangeCharges.js index 9412561..1197eb4 100644 --- a/services/integration/bookingChangeCharges.js +++ b/services/integration/bookingChangeCharges.js @@ -274,6 +274,16 @@ const deleteBookingChangeIncidents = (incidents) => { return Promise.all(asyncActions); }; +const deleteBookingChangeIncidentsById = (incidentIds) => { + console.log('Delete booking changes in DB :', incidentIds); + const filters = { + id: { + [Op.in]: incidentIds + } + }; + return db.bookingChangeIncident.update({deleted: true},{where: filters}); +}; + module.exports = { getChargedCanceledReservations, getIncidentsFromChanges, @@ -281,4 +291,5 @@ module.exports = { getShorteningIncidentsForReservationId, getReservationsIncidentsForRemoval, deleteBookingChangeIncidents, + deleteBookingChangeIncidentsById }; diff --git a/services/integration/doorLockCharges.js b/services/integration/doorLockCharges.js index 0a1d706..3460835 100644 --- a/services/integration/doorLockCharges.js +++ b/services/integration/doorLockCharges.js @@ -2,6 +2,7 @@ const moment = require('moment-timezone'); const db = require('../../models/index'); +const Op = require('sequelize').Op; const { doorLockEvents, @@ -69,6 +70,16 @@ const insertUnscheduledIncidents = (incidents) => { return Promise.all(asyncJobs); }; +const deleteUnscheduledIncidentsById = (incidentIds) => { + console.log('Delete unscheduled in DB :', incidentIds); + const filters = { + id: { + [Op.in]: incidentIds + } + }; + return db.unscheduledIncident.update({deleted: true},{where: filters}); +}; + const insertUnlockedIncidents = (incidents) => { const asyncJobs = []; incidents.forEach((incident) => { @@ -104,6 +115,16 @@ const insertUnlockedIncidents = (incidents) => { return Promise.all(asyncJobs); }; +const deleteUnlockedIncidentsById = (incidentIds) => { + console.log('Delete unlocked in DB :', incidentIds); + const filters = { + id: { + [Op.in]: incidentIds + } + }; + return db.unlockedIncident.update({deleted: true},{where: filters}); +}; + const setUnlockedIncidentsLevel = (incidents) => { return new Promise ((resolve, reject) => { const sortingFunction = (incidentA, incidentB) => { @@ -576,5 +597,7 @@ const calculateDoorLockCharges = () => { }; module.exports = { - calculateDoorLockCharges + calculateDoorLockCharges, + deleteUnlockedIncidentsById, + deleteUnscheduledIncidentsById }; From 37abb86961d26344adb96ce7096f3a2702c812ef Mon Sep 17 00:00:00 2001 From: Bilal Catic Date: Thu, 21 Nov 2019 07:13:30 +0100 Subject: [PATCH 4/7] add and implement action to send "delete fees" request --- .../components/SingleIncidentsTable.js | 318 ++++++++++-------- .../components/MemberIncidentsTables/index.js | 5 +- client/src/scenes/IncidentsReport/index.js | 2 +- .../src/store/actions/integrationActions.js | 11 + 4 files changed, 188 insertions(+), 148 deletions(-) diff --git a/client/src/components/MemberIncidentsTables/components/SingleIncidentsTable.js b/client/src/components/MemberIncidentsTables/components/SingleIncidentsTable.js index 7219cc1..b694963 100644 --- a/client/src/components/MemberIncidentsTables/components/SingleIncidentsTable.js +++ b/client/src/components/MemberIncidentsTables/components/SingleIncidentsTable.js @@ -1,5 +1,6 @@ -import React from 'react'; -import { Loader } from 'semantic-ui-react'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { Loader, Button } from 'semantic-ui-react'; import ReactTable from 'react-table'; import 'react-table/react-table.css'; import { NavLink } from 'react-router-dom'; @@ -13,155 +14,180 @@ import { UNSCHEDULED_INCIDENT_BEFORE_RESERVATION, UNSCHEDULED_INCIDENT_STANDALONE } from '../../../constants/enums'; import { doorLockRelatedWithReservationIncidentHeaders, standaloneDoorLockIncidentHeaders, bookingChangeIncidentHeaders } from '../../../constants/constants'; +import { deleteIncidents } from "../../../store/actions"; +class SingleIncidentsTable extends Component { + deleteSelectedFees = () => { + const { dateRange, deleteIncidentsById } = this.props; -const SingleIncidentsTable = props => { - const { - loading, - title, - openMemberSummaryOnMemberClick, - hideMemberName, - tableType - } = props; - const incidents = props.incidents ? props.incidents : []; - const columns = []; + const unlockedIncidentIds = []; + const unscheduledIncidentIds = []; + const bookingChangeIncidentIds = []; - if (incidents && incidents.length > 0){ - let tableHeaders; - switch (tableType) { - case incidentTableTypes.INCIDENTS_RELATED_TO_RESERVATIONS: - tableHeaders = doorLockRelatedWithReservationIncidentHeaders; - break; - case incidentTableTypes.STANDALONE_INCIDENTS: - tableHeaders = standaloneDoorLockIncidentHeaders; - break; - case incidentTableTypes.BOOKING_CHANGE_INCIDENTS: - tableHeaders = bookingChangeIncidentHeaders; - break; - default: - break; + const incidentsToDelete = { + unlockedIncidentIds, + unscheduledIncidentIds, + bookingChangeIncidentIds + }; + + deleteIncidentsById(dateRange, incidentsToDelete); + }; + + render(){ + const { + loading, + title, + openMemberSummaryOnMemberClick, + hideMemberName, + tableType + } = this.props; + const incidents = this.props.incidents ? this.props.incidents : []; + const columns = []; + + if (incidents && incidents.length > 0){ + let tableHeaders; + switch (tableType) { + case incidentTableTypes.INCIDENTS_RELATED_TO_RESERVATIONS: + tableHeaders = doorLockRelatedWithReservationIncidentHeaders; + break; + case incidentTableTypes.STANDALONE_INCIDENTS: + tableHeaders = standaloneDoorLockIncidentHeaders; + break; + case incidentTableTypes.BOOKING_CHANGE_INCIDENTS: + tableHeaders = bookingChangeIncidentHeaders; + break; + default: + break; + } + + tableHeaders.forEach((header) => { + const columnTitle = incidentsReportHeaderTitles[header]; + + let showColumn = true; + if (header === 'memberName' && hideMemberName){ + showColumn = false; + } + + if (columnTitle && showColumn){ + const columnAlignments = { + left: 'left', + right: 'right', + }; + let columnContentsAlignment = columnAlignments.left; + + columns.push({ + Header: incidentsReportHeaderTitles[header], + accessor: header, + Cell: props => { + let cellValue = ''; + let urlValue = undefined; + + switch (props.column.id) { + case 'memberName': + const memberId = props.row['_original'].memberId; + urlValue = `/specific-member-incidents-report/${memberId}`; + cellValue = props.value; + break; + case 'resourceName': + if (props.row['_original'].resourceName){ + cellValue = props.row['_original'].resourceName || '---'; + }else{ + const oldResourceName = props.row['_original'].oldResourceName || '---'; + const newResourceName = props.row['_original'].newResourceName || '---'; + if (oldResourceName !== newResourceName){ + cellValue = `${oldResourceName}\n${newResourceName}`; + }else{ + cellValue = oldResourceName; + } + } + break; + case 'reservation': + const bookingStart = props.row['_original'].bookingStart; + const bookingEnd = props.row['_original'].bookingEnd; + cellValue = `${bookingStart}\n${bookingEnd}`; + break; + case 'doorLockTimestamps': + const unlockTimestamp = props.row['_original'].unlockTimestamp; + const lockTimestamp = props.row['_original'].lockTimestamp; + cellValue = `${unlockTimestamp ? unlockTimestamp : '---'}\n${lockTimestamp ? lockTimestamp : '---'}`; + break; + case 'incidentType': + cellValue = incidentDescriptions[props.value]; + break; + case 'incidentLevel': + cellValue = incidentLevelDescriptions[props.value]; + break; + case 'feeDescription': + const { incidentType, incidentLevel, timeIntervalsToCharge } = props.row['_original']; + + switch (incidentType) { + case UNLOCKED_INCIDENT_RELATED_WITH_RESERVATION: + case UNLOCKED_INCIDENT_STANDALONE: + cellValue = `${incidentLevelDescriptions[incidentLevel]}`; + break; + case UNSCHEDULED_INCIDENT_BEFORE_RESERVATION: + case UNSCHEDULED_INCIDENT_AFTER_RESERVATION: + case UNSCHEDULED_INCIDENT_STANDALONE: + cellValue = `${timeIntervalsToCharge} x 5 min`; + break; + default: + cellValue = ''; + break; + } + break; + case 'totalChargeFee': + const totalFee = (props.row['_original'].incidentPrice || props.value) || 0; + const totalFeeFormatted = parseFloat(totalFee).toFixed(2); + cellValue = `$ ${totalFeeFormatted}`; + columnContentsAlignment = columnAlignments.right; + break; + case 'oldReservation': + const oldBookingStart = props.row['_original'].oldBookingStart; + const oldBookingEnd = props.row['_original'].oldBookingEnd; + cellValue = `${oldBookingStart}\n${oldBookingEnd}`; + break; + case 'newReservation': + const newBookingStart = props.row['_original'].newBookingStart || '---'; + const newBookingEnd = props.row['_original'].newBookingEnd || '---'; + cellValue = `${newBookingStart}\n${newBookingEnd}`; + break; + default: + cellValue = props.value; + } + + if (openMemberSummaryOnMemberClick && urlValue){ + return {cellValue} + }else{ + return
{cellValue}
+ } + } + }); + } + }); } - tableHeaders.forEach((header) => { - const columnTitle = incidentsReportHeaderTitles[header]; - - let showColumn = true; - if (header === 'memberName' && hideMemberName){ - showColumn = false; - } - - if (columnTitle && showColumn){ - const columnAlignments = { - left: 'left', - right: 'right', - }; - let columnContentsAlignment = columnAlignments.left; - - columns.push({ - Header: incidentsReportHeaderTitles[header], - accessor: header, - Cell: props => { - let cellValue = ''; - let urlValue = undefined; - - switch (props.column.id) { - case 'memberName': - const memberId = props.row['_original'].memberId; - urlValue = `/specific-member-incidents-report/${memberId}`; - cellValue = props.value; - break; - case 'resourceName': - if (props.row['_original'].resourceName){ - cellValue = props.row['_original'].resourceName || '---'; - }else{ - const oldResourceName = props.row['_original'].oldResourceName || '---'; - const newResourceName = props.row['_original'].newResourceName || '---'; - if (oldResourceName !== newResourceName){ - cellValue = `${oldResourceName}\n${newResourceName}`; - }else{ - cellValue = oldResourceName; - } - } - break; - case 'reservation': - const bookingStart = props.row['_original'].bookingStart; - const bookingEnd = props.row['_original'].bookingEnd; - cellValue = `${bookingStart}\n${bookingEnd}`; - break; - case 'doorLockTimestamps': - const unlockTimestamp = props.row['_original'].unlockTimestamp; - const lockTimestamp = props.row['_original'].lockTimestamp; - cellValue = `${unlockTimestamp ? unlockTimestamp : '---'}\n${lockTimestamp ? lockTimestamp : '---'}`; - break; - case 'incidentType': - cellValue = incidentDescriptions[props.value]; - break; - case 'incidentLevel': - cellValue = incidentLevelDescriptions[props.value]; - break; - case 'feeDescription': - const { incidentType, incidentLevel, timeIntervalsToCharge } = props.row['_original']; - - switch (incidentType) { - case UNLOCKED_INCIDENT_RELATED_WITH_RESERVATION: - case UNLOCKED_INCIDENT_STANDALONE: - cellValue = `${incidentLevelDescriptions[incidentLevel]}`; - break; - case UNSCHEDULED_INCIDENT_BEFORE_RESERVATION: - case UNSCHEDULED_INCIDENT_AFTER_RESERVATION: - case UNSCHEDULED_INCIDENT_STANDALONE: - cellValue = `${timeIntervalsToCharge} x 5 min`; - break; - default: - cellValue = ''; - break; - } - break; - case 'totalChargeFee': - const totalFee = (props.row['_original'].incidentPrice || props.value) || 0; - const totalFeeFormatted = parseFloat(totalFee).toFixed(2); - cellValue = `$ ${totalFeeFormatted}`; - columnContentsAlignment = columnAlignments.right; - break; - case 'oldReservation': - const oldBookingStart = props.row['_original'].oldBookingStart; - const oldBookingEnd = props.row['_original'].oldBookingEnd; - cellValue = `${oldBookingStart}\n${oldBookingEnd}`; - break; - case 'newReservation': - const newBookingStart = props.row['_original'].newBookingStart || '---'; - const newBookingEnd = props.row['_original'].newBookingEnd || '---'; - cellValue = `${newBookingStart}\n${newBookingEnd}`; - break; - default: - cellValue = props.value; - } - - if (openMemberSummaryOnMemberClick && urlValue){ - return {cellValue} - }else{ - return
{cellValue}
- } - } - }); - } - }); + return ( +
+

{title}

+ + { + + } + { + !loading && incidents && + + } +
+ ); } +} - return ( -
-

{title}

- - { - !loading && incidents && - - } -
- ); -}; +const mapDispatchToProps = (dispatch) => ({ + deleteIncidentsById: (dateRange, incidentsToDelete) => deleteIncidents(dispatch, {dateRange, incidentsToDelete}) +}); -export default SingleIncidentsTable; +export default connect(null, mapDispatchToProps)(SingleIncidentsTable); diff --git a/client/src/components/MemberIncidentsTables/index.js b/client/src/components/MemberIncidentsTables/index.js index 45ec9d1..d1c7f5b 100644 --- a/client/src/components/MemberIncidentsTables/index.js +++ b/client/src/components/MemberIncidentsTables/index.js @@ -8,7 +8,7 @@ import { } from '../../constants/enums'; export default function MemberIncidentsTables (props) { - const { pendingIncidents, incidents, hideMemberName } = props; + const { pendingIncidents, incidents, hideMemberName, dateRange } = props; const incidentsRelatedToReservations = []; const standaloneIncidents = []; @@ -46,6 +46,7 @@ export default function MemberIncidentsTables (props) { openMemberSummaryOnMemberClick hideMemberName={hideMemberName} tableType={incidentTableTypes.INCIDENTS_RELATED_TO_RESERVATIONS} + dateRange={dateRange} /> ); @@ -56,6 +57,7 @@ export default function MemberIncidentsTables (props) { openMemberSummaryOnMemberClick hideMemberName={hideMemberName} tableType={incidentTableTypes.STANDALONE_INCIDENTS} + dateRange={dateRange} /> ); @@ -66,6 +68,7 @@ export default function MemberIncidentsTables (props) { openMemberSummaryOnMemberClick hideMemberName={hideMemberName} tableType={incidentTableTypes.BOOKING_CHANGE_INCIDENTS} + dateRange={dateRange} /> ); diff --git a/client/src/scenes/IncidentsReport/index.js b/client/src/scenes/IncidentsReport/index.js index 891f87a..987fb5d 100644 --- a/client/src/scenes/IncidentsReport/index.js +++ b/client/src/scenes/IncidentsReport/index.js @@ -47,7 +47,7 @@ class IncidentsReport extends Component {



- + ); } diff --git a/client/src/store/actions/integrationActions.js b/client/src/store/actions/integrationActions.js index bef2eb7..9b6b545 100644 --- a/client/src/store/actions/integrationActions.js +++ b/client/src/store/actions/integrationActions.js @@ -88,6 +88,17 @@ export const fetchIncidents = (dispatch, dateRange) => { }); }; +export const deleteIncidents = (dispatch, deleteData) => { + dispatch({type: FETCH_INCIDENTS_PENDING}); + API.delete(`/integration/fees`, { data: deleteData }) + .then(response => { + dispatch({type: FETCH_INCIDENTS_SUCCESS, payload: response.data}); + }) + .catch(error => { + dispatch({type: FETCH_INCIDENTS_FAILED, payload: error.response}); + }); +}; + export const fetchMembersList = (dispatch) => { dispatch({type: FETCH_MEMBERS_PENDING}); API.get('officeRnD/membersList') From d1d67c346ad1838097e63820965cb336f34e5663 Mon Sep 17 00:00:00 2001 From: Bilal Catic Date: Thu, 21 Nov 2019 09:21:21 +0100 Subject: [PATCH 5/7] add checkbox option to the incident tables --- .../components/SingleIncidentsTable.js | 8 +- client/src/components/SelectTable/index.js | 109 ++++++++++++++++++ 2 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 client/src/components/SelectTable/index.js diff --git a/client/src/components/MemberIncidentsTables/components/SingleIncidentsTable.js b/client/src/components/MemberIncidentsTables/components/SingleIncidentsTable.js index b694963..27d5872 100644 --- a/client/src/components/MemberIncidentsTables/components/SingleIncidentsTable.js +++ b/client/src/components/MemberIncidentsTables/components/SingleIncidentsTable.js @@ -5,6 +5,8 @@ import ReactTable from 'react-table'; import 'react-table/react-table.css'; import { NavLink } from 'react-router-dom'; +import SelectTable from "../../SelectTable"; + import {incidentsReportHeaderTitles} from '../../../constants/constants'; import { incidentTableTypes, @@ -42,6 +44,9 @@ class SingleIncidentsTable extends Component { tableType } = this.props; const incidents = this.props.incidents ? this.props.incidents : []; + incidents.forEach(incident => { + incident.id = `${incident.incidentType}-${incident.incidentId}`; + }); const columns = []; if (incidents && incidents.length > 0){ @@ -175,10 +180,11 @@ class SingleIncidentsTable extends Component { } { !loading && incidents && - } diff --git a/client/src/components/SelectTable/index.js b/client/src/components/SelectTable/index.js new file mode 100644 index 0000000..7b570dd --- /dev/null +++ b/client/src/components/SelectTable/index.js @@ -0,0 +1,109 @@ +import React, { Component } from 'react'; +import Table from 'react-table'; +import SelectTableHOC from 'react-table/lib/hoc/selectTable'; + +const SelectTableElement = SelectTableHOC(Table); + +class SelectTable extends Component { + static defaultProps = { + keyField: "id" + }; + + /** + * Toggle a single checkbox for select table + */ + toggleSelection = (key, shift, row) => { + // start off with the existing state + let selection = [...this.state.selection]; + const keyIndex = selection.indexOf(key); + + // check to see if the key exists + if (keyIndex >= 0) { + // it does exist so we will remove it using destructing + selection = [ + ...selection.slice(0, keyIndex), + ...selection.slice(keyIndex + 1) + ]; + } else { + // it does not exist so add it + selection.push(key); + } + // update the state + this.setState({ selection }); + }; + + /** + * Toggle all checkboxes for select table + */ + toggleAll = () => { + const { keyField } = this.props; + const selectAll = !this.state.selectAll; + const selection = []; + + if (selectAll) { + // we need to get at the internals of ReactTable + const wrappedInstance = this.checkboxTable.getWrappedInstance(); + // the 'sortedData' property contains the currently accessible records based on the filter and sort + const currentRecords = wrappedInstance.getResolvedState().sortedData; + // we just push all the IDs onto the selection array + currentRecords.forEach(item => { + selection.push(`select-${item._original[keyField]}`); + }); + } + this.setState({ selectAll, selection }); + }; + + /** + * Whether or not a row is selected for select table + */ + isSelected = key => { + return this.state.selection.includes(`select-${key}`); + }; + + rowFn = (state, rowInfo, column, instance) => { + const { selection } = this.state; + + return { + onClick: (e, handleOriginal) => { + // console.log("It was in this row:", rowInfo); + + // IMPORTANT! React-Table uses onClick internally to trigger + // events like expanding SubComponents and pivots. + // By default a custom 'onClick' handler will override this functionality. + // If you want to fire the original onClick handler, call the + // 'handleOriginal' function. + if (handleOriginal) { + handleOriginal(); + } + }, + style: { + background: + rowInfo && + selection.includes(`select-${rowInfo.original.id}`) && + "lightgreen" + } + }; + }; + + state = { + selectAll: false, + selection: [] + }; + + render() { + return ( + (this.checkboxTable = r)} + toggleSelection={this.toggleSelection} + selectAll={this.state.selectAll} + selectType="checkbox" + toggleAll={this.toggleAll} + isSelected={this.isSelected} + getTrProps={this.rowFn} + /> + ); + } +} + +export default SelectTable; From 445a6353005a361094ee56b9708c79069731be91 Mon Sep 17 00:00:00 2001 From: Bilal Catic Date: Thu, 21 Nov 2019 14:32:52 +0100 Subject: [PATCH 6/7] split fees into specific categories and send delete request --- .../components/SingleIncidentsTable.js | 77 ++++++++++++++++--- client/src/components/SelectTable/index.js | 2 + 2 files changed, 70 insertions(+), 9 deletions(-) diff --git a/client/src/components/MemberIncidentsTables/components/SingleIncidentsTable.js b/client/src/components/MemberIncidentsTables/components/SingleIncidentsTable.js index 27d5872..05d5761 100644 --- a/client/src/components/MemberIncidentsTables/components/SingleIncidentsTable.js +++ b/client/src/components/MemberIncidentsTables/components/SingleIncidentsTable.js @@ -1,7 +1,6 @@ import React, { Component } from 'react'; import { connect } from 'react-redux'; import { Loader, Button } from 'semantic-ui-react'; -import ReactTable from 'react-table'; import 'react-table/react-table.css'; import { NavLink } from 'react-router-dom'; @@ -19,20 +18,68 @@ import { doorLockRelatedWithReservationIncidentHeaders, standaloneDoorLockIncide import { deleteIncidents } from "../../../store/actions"; class SingleIncidentsTable extends Component { + state = { + selectedUnlockedIncidentIds: [], + selectedUnscheduledIncidentIds: [], + selectedBookingChangeIncidentIds: [] + }; + + onSelectChange = (selectedIncidents) => { + const newSelectedUnlockedIncidentIds = []; + const newSelectedUnscheduledIncidentIds = []; + const newSelectedBookingChangeIncidentIds = []; + + selectedIncidents.forEach(incident => { + const incidentDetails = incident.split('-'); + // incident is described as : select-incidentType-incidentId + if (Array.isArray(incidentDetails) && incidentDetails.length > 2){ + const incidentType = parseInt(incidentDetails[1]); + const incidentId = parseInt(incidentDetails[2]); + + switch (incidentType) { + case 2: + case 5: + newSelectedUnlockedIncidentIds.push(incidentId); + break; + case 3: + case 4: + case 6: + newSelectedUnscheduledIncidentIds.push(incidentId); + break; + case 7: + case 8: + case 9: + newSelectedBookingChangeIncidentIds.push(incidentId); + break; + default: + break; + } + } + }); + + this.setState({ + selectedUnlockedIncidentIds: newSelectedUnlockedIncidentIds, + selectedUnscheduledIncidentIds: newSelectedUnscheduledIncidentIds, + selectedBookingChangeIncidentIds: newSelectedBookingChangeIncidentIds + }); + }; + deleteSelectedFees = () => { const { dateRange, deleteIncidentsById } = this.props; - - const unlockedIncidentIds = []; - const unscheduledIncidentIds = []; - const bookingChangeIncidentIds = []; + const { selectedUnlockedIncidentIds, selectedUnscheduledIncidentIds, selectedBookingChangeIncidentIds } = this.state; const incidentsToDelete = { - unlockedIncidentIds, - unscheduledIncidentIds, - bookingChangeIncidentIds + unlockedIncidentIds: selectedUnlockedIncidentIds, + unscheduledIncidentIds: selectedUnscheduledIncidentIds, + bookingChangeIncidentIds: selectedBookingChangeIncidentIds }; deleteIncidentsById(dateRange, incidentsToDelete); + this.setState({ + selectedUnlockedIncidentIds: [], + selectedUnscheduledIncidentIds: [], + selectedBookingChangeIncidentIds: [] + }); }; render(){ @@ -43,6 +90,16 @@ class SingleIncidentsTable extends Component { hideMemberName, tableType } = this.props; + + const { + selectedUnlockedIncidentIds, + selectedUnscheduledIncidentIds, + selectedBookingChangeIncidentIds + } = this.state; + + const totalSelected = selectedUnlockedIncidentIds.length + selectedUnscheduledIncidentIds.length + selectedBookingChangeIncidentIds.length; + const numberOfSelectedText = totalSelected > 0 ? ` (${totalSelected})` : ''; + const incidents = this.props.incidents ? this.props.incidents : []; incidents.forEach(incident => { incident.id = `${incident.incidentType}-${incident.incidentId}`; @@ -176,8 +233,9 @@ class SingleIncidentsTable extends Component {

{title}

{ - + } +

{ !loading && incidents && } diff --git a/client/src/components/SelectTable/index.js b/client/src/components/SelectTable/index.js index 7b570dd..f91653a 100644 --- a/client/src/components/SelectTable/index.js +++ b/client/src/components/SelectTable/index.js @@ -29,6 +29,7 @@ class SelectTable extends Component { selection.push(key); } // update the state + this.props.onSelectChange(selection); this.setState({ selection }); }; @@ -50,6 +51,7 @@ class SelectTable extends Component { selection.push(`select-${item._original[keyField]}`); }); } + this.props.onSelectChange(selection); this.setState({ selectAll, selection }); }; From fa4e574d6e83869ee581f6560706ff7d11a34836 Mon Sep 17 00:00:00 2001 From: Bilal Catic Date: Thu, 21 Nov 2019 14:34:50 +0100 Subject: [PATCH 7/7] remove obsolete logging --- controllers/integration.js | 4 ---- services/integration/bookingChangeCharges.js | 1 - services/integration/doorLockCharges.js | 2 -- 3 files changed, 7 deletions(-) diff --git a/controllers/integration.js b/controllers/integration.js index 47c0c0f..d3fc46f 100644 --- a/controllers/integration.js +++ b/controllers/integration.js @@ -82,8 +82,6 @@ const updateMapping = (req, res) => { }; const getAllIncidentsController = (req, res) => { - console.log('get all incidents : '); - console.log(req.params); const dateRange = { startDate: req.params.startDate, endDate: req.params.endDate, @@ -181,8 +179,6 @@ const addFees = (req, res) => { const deleteFees= (req, res) => { const deleteData = req.body; - console.log('Delete fees request : '); - console.log(req.body); const dateRange = deleteData.dateRange ? deleteData.dateRange : null; const incidents = deleteData.incidentsToDelete ? deleteData.incidentsToDelete : null; diff --git a/services/integration/bookingChangeCharges.js b/services/integration/bookingChangeCharges.js index 1197eb4..597a632 100644 --- a/services/integration/bookingChangeCharges.js +++ b/services/integration/bookingChangeCharges.js @@ -275,7 +275,6 @@ const deleteBookingChangeIncidents = (incidents) => { }; const deleteBookingChangeIncidentsById = (incidentIds) => { - console.log('Delete booking changes in DB :', incidentIds); const filters = { id: { [Op.in]: incidentIds diff --git a/services/integration/doorLockCharges.js b/services/integration/doorLockCharges.js index 3460835..89bca84 100644 --- a/services/integration/doorLockCharges.js +++ b/services/integration/doorLockCharges.js @@ -71,7 +71,6 @@ const insertUnscheduledIncidents = (incidents) => { }; const deleteUnscheduledIncidentsById = (incidentIds) => { - console.log('Delete unscheduled in DB :', incidentIds); const filters = { id: { [Op.in]: incidentIds @@ -116,7 +115,6 @@ const insertUnlockedIncidents = (incidents) => { }; const deleteUnlockedIncidentsById = (incidentIds) => { - console.log('Delete unlocked in DB :', incidentIds); const filters = { id: { [Op.in]: incidentIds