eHealthAfrica/direct-delivery-dashboard

View on GitHub
src/app/planning/schedule/schedules.service.js

Summary

Maintainability
D
2 days
Test Coverage
'use strict'

angular.module('planning')
  .service('scheduleService', function (dbService, log, utility, pouchUtil, $filter) {
    var _this = this

    _this.getAlertReceiversForRound = function (deliveryRound) {
      var stateCode = deliveryRound.roundCode && deliveryRound.roundCode.split('-')[0] || deliveryRound.id.split('-')[0]
      var view = 'dashboard-delivery-rounds/alert-receivers'
      var options = {include_docs: true, keys: ['all', stateCode]}

      return dbService.getView(view, options)
        .then(function (res) {
          return res
        })
        .then(pouchUtil.pluckValues)
        .then(function (data) {
          var obj = {emails: ['adam@ehealthafrica.org'], phones: []}
          return data.filter(function (item) {
            return item.active
          }).reduce(function (previous, current) {
            current.emails.forEach(function (item) {
              if (!previous.emails.indexOf(item)) {
                previous.emails.push({email: item, type: 'to', name: current.name})
              }
            })
            current.phones.forEach(function (item) {
              if (!previous.phones.indexOf(item)) {
                previous.phones.push(item)
              }
            })
            return previous
          }, obj)
        })
    }

    _this.getRoundEmailTemplate = function (deliveryRound) {
      var doc = 'round-email'
      var options = {include_docs: true}
      return dbService.get(doc, options)
        .then(function (data) {
          var msg = data && data.content && data.content.replace('{roundId}', deliveryRound.roundCode)
          var subject = data && data.subject && data.subject.replace('{roundId}', deliveryRound.roundCode)
          var result = {msg: msg, subject: subject}
          return result
        })
    }

    _this.getStartRoundEmailTemplate = function (deliveryRound) {
      var doc = 'round-start-email'
      var options = {include_docs: true}
      return dbService.get(doc, options)
        .then(function (data) {
          var msg = data && data.content && data.content
              .replace('{roundId}', deliveryRound.id)
              .replace('{state}', deliveryRound.state).replace('{startDate}', $filter('date')(deliveryRound.startDate, 'dd-MM-yyyy'))
              .replace('{endDate}', $filter('date')(deliveryRound.endDate, 'dd-MM-yyyy'))
          var subject = data && data.subject && data.subject.replace('{roundId}', deliveryRound.id)
          var result = {msg: msg, subject: subject}
          return result
        })
    }

    _this.getHeaders = function () {
      return _this.headerIndex
    }

    _this.headerIndex = {
      uuid: {
        text: 'UUID',
        index: 0
      },
      roundCode: {
        text: 'Round Code',
        index: 1
      },
      facilityName: {
        text: 'Facility Name',
        index: 2
      },
      facilityCode: {
        text: 'Facility Code',
        index: 3
      },
      deliveryDate: {
        text: 'Delivery Date',
        index: 4
      },
      driverID: {
        text: 'Driver ID',
        index: 5
      },
      drop: {
        text: 'Drop',
        index: 6
      },
      distance: {
        text: 'Distance (KM)',
        index: 7
      },
      window: {
        text: 'Window',
        index: 8
      }
    }

    _this.saveSchedules = function (dailyDeliveries) {
      var result = dailyDeliveries.map(function (row) {
        if (utility.isValidDate(row.date)) {
          row.date = utility.formatDate(row.date)
        } else {
          row.date = ''
        }
        return row
      })
      return dbService.saveDocs(result)
    }

    _this.save = function (doc) {
      return dbService.save(doc)
    }

    _this.presetDate = function (date) {
      if (utility.isValidDate(date)) {
        return new Date(date)
      }
      return ''
    }

    _this.flatten = function (dailyDeliveries) {
      var schedules = []
      // /TODO: Remove after splitting Daily Delivery doc into
      function flattenSchedule (dailySchedule) {
        if (angular.isArray(dailySchedule.facilityRounds)) {
          dailySchedule.facilityRounds
            .forEach(function (facRnd) {
              var schedule = {
                _id: dailySchedule._id,
                facility: facRnd.facility,
                date: _this.presetDate(dailySchedule.date),
                driverID: dailySchedule.driverID,
                drop: facRnd.drop,
                window: facRnd.window,
                status: facRnd.status,
                distance: facRnd.distance
              }
              schedules.push(schedule)
            })
        } else {
          dailySchedule.date = _this.presetDate(dailySchedule.date)
          schedules.push(dailySchedule)
        }
      }

      dailyDeliveries.forEach(flattenSchedule)
      return schedules
    }

    function getHeaderTexts () {
      var headers = []
      for (var i in _this.headerIndex) {
        if (_this.headerIndex.hasOwnProperty(i)) {
          headers.push(_this.headerIndex[i].text)
        }
      }
      return headers
    }

    _this.prepareExport = function (roundId, dailyDeliveries) {
      var rows = dailyDeliveries.map(function (row) {
        var deliveryDate = ''
        if (utility.isValidDate(row.date)) {
          deliveryDate = utility.formatDate(row.date)
        }
        return {
          uuid: row._id,
          roundId: roundId,
          facilityName: row.facility.name,
          facilityCode: row.facility.id,
          deliveryDate: deliveryDate,
          driver: row.driverID,
          drop: row.drop,
          distance: row.distance,
          window: row.window
        }
      })

      var headers = getHeaderTexts()
        .sort(function (a, b) {
          return a.index - b.index
        })

      return {
        rows: rows,
        headers: headers
      }
    }

    _this.parseCSV = function (csvJSON) {
      var result = {}
      var headers = _this.getHeaders()
      csvJSON.forEach(function (csvRow) {
        var row = {
          id: csvRow[headers.uuid.text],
          roundId: csvRow[headers.roundCode.text],
          facilityName: csvRow[headers.facilityName.text],
          facilityCode: csvRow[headers.facilityCode.text],
          deliveryDate: csvRow[headers.deliveryDate.text],
          driver: csvRow[headers.driverID.text],
          drop: csvRow[headers.drop.text],
          distance: csvRow[headers.distance.text],
          window: csvRow[headers.window.text]
        }
        var rowHash = _this.hashRow(row.roundId, row.facilityCode, row.id)
        result[rowHash] = row
      })
      return result
    }

    _this.hashRow = function (roundId, facilityCode, dailyDeliveryId) {
      return [ roundId, facilityCode, dailyDeliveryId ].join('-')
    }

    _this.applyChanges = function (dailyDeliveries, schedulesInfo) {
      function applyUpdate (dailyDelivery) {
        var rowHash
        var scheduleInfo
        if (angular.isArray(dailyDelivery.facilityRounds)) {
          dailyDelivery.facilityRounds
            .forEach(function (facRnd) {
              rowHash = _this.hashRow(dailyDelivery.deliveryRoundID, facRnd.facility.id, dailyDelivery._id)
              scheduleInfo = schedulesInfo[rowHash]
              if (scheduleInfo) {
                facRnd.drop = scheduleInfo.drop
                facRnd.window = scheduleInfo.window
                facRnd.distance = scheduleInfo.distance
                facRnd.status = scheduleInfo.status
              }
            })
        } else {
          rowHash = _this.hashRow(dailyDelivery.deliveryRoundID, dailyDelivery.facility.id, dailyDelivery._id)
          scheduleInfo = schedulesInfo[rowHash]
          if (scheduleInfo) {
            dailyDelivery.drop = scheduleInfo.drop
            dailyDelivery.window = scheduleInfo.window
            dailyDelivery.distance = scheduleInfo.distance
            dailyDelivery.status = scheduleInfo.status
          }
        }

        if (scheduleInfo) {
          if (dailyDelivery.date !== scheduleInfo.deliveryDate) {
            dailyDelivery.targetDate = dailyDelivery.date
          }
          dailyDelivery.driverID = scheduleInfo.driver
          dailyDelivery.date = scheduleInfo.deliveryDate
        }

        return dailyDelivery
      }

      return dailyDeliveries.map(applyUpdate)
    }

    _this.onSaveError = function (err) {
      if (err.status === 401) {
        return log.error('unauthorizedAccess', err)
      }
      if (err.status === 409) {
        return log.error('updateConflict', err)
      }
      log.error('saveBatchScheduleFailed', err)
    }

    function formatRounds (list) {
      list.sort(function (a, b) {
        return a.drop - b.drop
      })
      return list
    }

    _this.getDaySchedule = function (driverID, date) {
      var deliveryDate = date || new Date()
      var key = driverID + '-' + utility.formatDate(deliveryDate)
      var options = {
        include_docs: true,
        key: key
      }
      return dbService.getView('daily-deliveries/by-driver-date', options)
        .then(pouchUtil.pluckDocs)
        .then(pouchUtil.rejectIfEmpty)
        .then(formatRounds)
    }

    _this.getDriverLastDrop = function (driverId, date) {
      return _this.getDaySchedule(driverId, date)
        .then(function (response) {
          return [response[response.length - 1], response]
        })
    }

    _this.scheduleCompleted = function (delivery, go) {
      delivery.scheduleComplete = true
      if (!utility.isValidDate(delivery.date)) {
        go = false
      }
      if (!utility.isValidEmail(delivery.driverID)) {
        go = false
      }
      if (angular.isUndefined(delivery.drop) || delivery.drop === '') {
        go = false
      }
      if (angular.isUndefined(delivery.window) || delivery.window === '') {
        go = false
      }
      if (angular.isUndefined(delivery.distance) || delivery.distance === '') {
        go = false
      }

      return go
    }

    this.isScheduleComplete = function (dailyDeliveries) {
      dailyDeliveries = dailyDeliveries || []
      var isComplete = dailyDeliveries.length > 0
      var go = isComplete
      for (var i = 0; i < dailyDeliveries.length; i++) {
        var delivery = dailyDeliveries[i]
        _this.scheduleCompleted(delivery, go)
        if (!go) {
          delivery.scheduleComplete = false
          isComplete = false
          break
        }
      }
      return isComplete
    }
  })