Browse Source

Merge branch 'master' of https://source.prod.sidali.vertibiz.com/yazid/ptb-be

yazid138 2 months ago
parent
commit
3849af50b6

+ 263 - 0
controller/auto.controller.js

@@ -0,0 +1,263 @@
+const handleError = require('../utils/handleError')
+const response = require('../utils/responseHandler')
+const { notifWA } = require('../utils/notifFunction')
+const sanksiModel = require('../model/sanksi.model')
+const {
+  TEMPLATE_KEBERATAN,
+  TEMPLATE_BANDING,
+  TEMPLATE_REMINDER,
+} = require('../utils/constanta')
+const moment = require('moment')
+
+exports.keberatan = handleError(async (req, res) => {
+  const dataSanksi = await sanksiModel
+    .find({
+      'batas_waktu.keberatan': {
+        $lt: new Date().toISOString(),
+      },
+      'batas_waktu.jawaban_keberatan': {
+        $exists: false,
+        $eq: null,
+      },
+    })
+    .populate('user')
+    .populate('laporan')
+
+  if (!dataSanksi.length) {
+    return response.success(res, {
+      message: 'Tidak ada notifikasi yg dikirim',
+    })
+  }
+
+  Promise.all(
+    dataSanksi.map(
+      async (sanksi) =>
+        await notifWA(TEMPLATE_KEBERATAN, [
+          {
+            key: '1',
+            value: 'nama_pt',
+            value_text: sanksi.laporan.pt.nama,
+          },
+          {
+            key: '2',
+            value: 'pemberi_sanksi',
+            value_text: sanksi.user.lembaga.nama,
+          },
+          {
+            key: '3',
+            value: 'no_laporan',
+            value_text: sanksi.laporan.no_laporan,
+          },
+        ])
+    )
+  )
+  return response.success(res, {
+    message: 'Notifikasi berhasil terkirim',
+  })
+})
+
+exports.banding = handleError(async (req, res) => {
+  const dataSanksi = await sanksiModel
+    .find({
+      'batas_waktu.banding': {
+        $lt: new Date().toISOString(),
+      },
+      'batas_waktu.jawaban_banding': {
+        $exists: false,
+        $eq: null,
+      },
+      'batas_waktu.jawaban_keberatan': {
+        $exists: true,
+        $ne: null,
+      },
+    })
+    .populate('user')
+    .populate('laporan')
+
+  if (!dataSanksi.length) {
+    return response.success(res, {
+      message: 'Tidak ada notifikasi yg dikirim',
+    })
+  }
+
+  Promise.all(
+    dataSanksi.map(
+      async (sanksi) =>
+        await notifWA(TEMPLATE_BANDING, [
+          {
+            key: '1',
+            value: 'nama_pt',
+            value_text: sanksi.laporan.pt.nama,
+          },
+          {
+            key: '2',
+            value: 'pemberi_sanksi',
+            value_text: sanksi.user.lembaga.nama,
+          },
+          {
+            key: '3',
+            value: 'no_laporan',
+            value_text: sanksi.laporan.no_laporan,
+          },
+        ])
+    )
+  )
+  return response.success(res, {
+    message: 'Notifikasi berhasil terkirim',
+  })
+})
+
+exports.reminderKeberatan = handleError(async (req, res) => {
+  let dataSanksi = await sanksiModel
+    .find({
+      'batas_waktu.jawaban_keberatan': {
+        $exists: true,
+        $ne: null,
+      },
+      'jawaban.keberatan': {
+        $exists: false,
+        $eq: null,
+      },
+    })
+    .populate('user')
+    .populate('laporan')
+  const notif = await Promise.all(
+    dataSanksi.map(async (e) => {
+      if (
+        e.batas_waktu.jawaban_keberatan &&
+        new Date() >
+          moment(e.batas_waktu.jawaban_keberatan).add(-7, 'days').toDate() &&
+        new Date() < e.batas_waktu.jawaban_keberatan
+      ) {
+        const dayLeft = moment(e.batas_waktu.jawaban_keberatan).diff(
+          new Date(),
+          'days'
+        )
+        try {
+          await notifWA(TEMPLATE_REMINDER, [
+            {
+              key: '1',
+              value: 'no_laporan',
+              value_text: e.laporan.no_laporan,
+            },
+            {
+              key: '2',
+              value: 'keterangan',
+              value_text: 'Proses Menjawab Pengajuan Keberatan',
+            },
+            {
+              key: '3',
+              value: 'pt',
+              value_text: e.laporan.pt.nama,
+            },
+            {
+              key: '4',
+              value: 'masa',
+              value_text: `menjawab pengajuan keberatan tersisa ${dayLeft} hari lagi.`,
+            },
+          ])
+        } catch (error) {
+          return response.error(res, {
+            message: 'Notifikasi gagal terkirim',
+            error: error.message,
+          })
+        }
+      }
+    })
+  )
+
+  let message = 'Tidak ada notifikasi yang dikirim'
+  if (notif.length) message = 'Notifikasi berhasil terkirim'
+
+  return response.success(res, {
+    message,
+  })
+})
+
+exports.reminderBanding = handleError(async (req, res) => {
+  let dataSanksi = await sanksiModel
+    .find({
+      'batas_waktu.jawaban_banding': {
+        $exists: true,
+        $ne: null,
+      },
+      'jawaban.banding': {
+        $exists: false,
+        $eq: null,
+      },
+    })
+    .populate('user')
+    .populate('laporan')
+  const notif = await Promise.all(
+    dataSanksi.map(async (e) => {
+      if (
+        e.batas_waktu.jawaban_banding &&
+        new Date() >
+          moment(e.batas_waktu.jawaban_banding).add(-7, 'days').toDate() &&
+        new Date() < e.batas_waktu.jawaban_banding
+      ) {
+        const dayLeft = moment(e.batas_waktu.jawaban_banding).diff(
+          new Date(),
+          'days'
+        )
+        try {
+          await notifWA(TEMPLATE_REMINDER, [
+            {
+              key: '1',
+              value: 'no_laporan',
+              value_text: e.laporan.no_laporan,
+            },
+            {
+              key: '2',
+              value: 'keterangan',
+              value_text: 'Proses Menjawab Pengajuan Banding',
+            },
+            {
+              key: '3',
+              value: 'pt',
+              value_text: e.laporan.pt.nama,
+            },
+            {
+              key: '4',
+              value: 'masa',
+              value_text: `menjawab pengajuan banding tersisa ${dayLeft} hari lagi.`,
+            },
+          ])
+        } catch (error) {
+          return response.error(res, {
+            message: 'Notifikasi gagal terkirim',
+            error: error.message,
+          })
+        }
+      }
+    })
+  )
+
+  let message = 'Tidak ada notifikasi yang dikirim'
+  if (notif.length) message = 'Notifikasi berhasil terkirim'
+
+  return response.success(res, {
+    message,
+  })
+})
+
+exports.updateStatusSanksi = handleError(async (req, res) => {
+  const sanksi = await sanksiModel.find({
+    'masa_berlaku.to_date': {
+      $lte: new Date().toISOString(),
+    },
+    aktif: true,
+  })
+
+  Promise.all(
+    sanksi.map(async (e) =>
+      sanksiModel.findByIdAndUpdate(e._id, {
+        aktif: false,
+      })
+    )
+  )
+
+  return response.success(res, {
+    message: 'update status sanksi berhasil',
+  })
+})

+ 533 - 0
controller/graph.controller.js

@@ -0,0 +1,533 @@
+const handleError = require('../utils/handleError')
+const excel = require('../utils/excel')
+const response = require('../utils/responseHandler')
+const {
+  cekBanyakDataLaporan,
+  dataLaporanAggregate,
+  cekBanyakDataSanksi,
+} = require('../utils/cekData')
+const laporanModel = require('../model/laporan.model')
+const sanksiModel = require('../model/sanksi.model')
+const moment = require('moment')
+
+exports.laporan = handleError(async (req, res) => {
+  const user = req.user
+  const data = {}
+  const date = new Date()
+
+  // let berdasarkan_tahun = {}
+  const {
+    jumlahLaporan,
+    jadwal,
+    evaluasi,
+    sanksi,
+    newLaporan,
+    laporanBulan,
+    laporanTahun,
+    bulan,
+    tahun,
+    listJadwal,
+  } = req.query
+
+  // if (tahun) {
+  berdasarkan_tahun = {
+    $and: [
+      {
+        createdAt: {
+          $gte: new Date(`${tahun || date.getFullYear()}`),
+        },
+      },
+      {
+        createdAt: {
+          $lt: new Date(`${parseInt(tahun) + 1 || date.getFullYear() + 1}`),
+        },
+      },
+    ],
+  }
+  // }
+
+  const laporan = await cekBanyakDataLaporan(user, { ...berdasarkan_tahun })
+
+  if (jumlahLaporan == 'true') {
+    const delegasi = await cekBanyakDataLaporan(user, {
+      delegasi: true,
+      ...berdasarkan_tahun,
+    })
+    const ditutup = await cekBanyakDataLaporan(user, {
+      aktif: false,
+      ...berdasarkan_tahun,
+    })
+
+    data.jumlah_laporan = {
+      dikti: laporan.length,
+      lldikti: delegasi.length,
+      ditutup: ditutup.length,
+      tes: {
+        delegasi: true,
+        ...berdasarkan_tahun,
+      },
+    }
+  }
+
+  if (jadwal == 'true') {
+    const hasJadwal = laporan.filter((e) => e.jadwal.judul).length
+    const notHasJadwal = laporan.filter((e) => !e.jadwal.judul).length
+
+    data.jadwal = {
+      hasJadwal,
+      notHasJadwal,
+    }
+  }
+
+  if (evaluasi == 'true') {
+    const hasEvaluasi = laporan.filter(
+      (e) => e.evaluasi.length && e.jadwal.judul
+    ).length
+    const notHasEvaluasi = laporan.filter(
+      (e) => e.evaluasi.length == 0 && e.jadwal.judul
+    ).length
+
+    data.evaluasi = {
+      hasEvaluasi,
+      notHasEvaluasi,
+    }
+  }
+
+  if (sanksi == 'true') {
+    const hasSanksi = laporan.filter(
+      (e) => e.sanksi && e.evaluasi.length
+    ).length
+    const notHasSanksi = laporan.filter(
+      (e) => !e.sanksi && e.evaluasi.length
+    ).length
+
+    data.sanksi = {
+      hasSanksi,
+      notHasSanksi,
+    }
+  }
+
+  if (newLaporan == 'true') {
+    data.newLaporan = await cekBanyakDataLaporan(user, {
+      limit: 3,
+      select: 'no_laporan pt.nama -user createdAt',
+    })
+  }
+
+  if (laporanBulan == 'true') {
+    let date = {}
+    if (bulan || (bulan && tahun)) {
+      const temp = new Date()
+      date = {
+        $expr: {
+          $and: [
+            { $eq: [{ $month: '$createdAt' }, parseInt(bulan)] },
+            {
+              $eq: [
+                { $year: '$createdAt' },
+                parseInt(tahun) || temp.getFullYear(),
+              ],
+            },
+          ],
+        },
+      }
+    }
+
+    data.laporan_perbulan = await dataLaporanAggregate(
+      user,
+      { ...date },
+      {
+        _id: {
+          bulan: {
+            $month: '$createdAt',
+          },
+          tahun: {
+            $year: '$createdAt',
+          },
+        },
+        jumlah_laporan: {
+          $sum: 1,
+        },
+      }
+    )
+  } else if (laporanTahun == 'true') {
+    const temp = new Date()
+    let date = {
+      $expr: {
+        $eq: [{ $year: '$createdAt' }, parseInt(tahun) || temp.getFullYear()],
+      },
+    }
+
+    data.laporan_perTahun = await dataLaporanAggregate(
+      user,
+      { ...date },
+      {
+        _id: {
+          bulan: {
+            $month: '$createdAt',
+          },
+          tahun: {
+            $year: '$createdAt',
+          },
+        },
+        jumlah_laporan: {
+          $sum: 1,
+        },
+      }
+    )
+  }
+
+  if (listJadwal == 'true') {
+    const temp = new Date()
+    let date = {
+      $expr: {
+        $and: [
+          {
+            $eq: [
+              { $month: '$jadwal.dari_tanggal' },
+              parseInt(bulan) || temp.getMonth() + 1,
+            ],
+          },
+          {
+            $eq: [
+              { $year: '$jadwal.dari_tanggal' },
+              parseInt(tahun) || temp.getFullYear(),
+            ],
+          },
+        ],
+      },
+    }
+
+    data.list_jadwal = await dataLaporanAggregate(
+      user,
+      {
+        aktif: true,
+        ...date,
+        jadwal: {
+          $ne: null,
+          $exists: true,
+        },
+      },
+      {
+        _id: {
+          bulan: {
+            $month: '$jadwal.dari_tanggal',
+          },
+          tahun: {
+            $year: '$jadwal.dari_tanggal',
+          },
+        },
+        jadwal: {
+          $push: '$jadwal',
+        },
+      }
+    )
+  }
+
+  return response.success(res, {
+    message: 'Berhasil menganalisis data',
+    data,
+  })
+})
+
+exports.excel = handleError(async (req, res) => {
+  const user = req.user
+  const w = {}
+  const date = new Date()
+  switch (user.role.id) {
+    case 2020:
+      w['$or'] = [
+        {
+          role_asal: 'dikti',
+        },
+        {
+          role_data: 'dikti',
+        },
+      ]
+      break
+    case 2021:
+      w['$or'] = [
+        {
+          role_asal: 'lldikti',
+        },
+        {
+          role_data: 'lldikti',
+        },
+      ]
+      w['pt.pembina.id'] = user.lembaga.id
+      break
+  }
+
+  const { tahun, penjadwalan, pelaporan, pemeriksaan, delegasi, sanksi } =
+    req.query
+
+  berdasarkan_tahun = {
+    $and: [
+      {
+        createdAt: {
+          $gte: new Date(`${tahun || date.getFullYear()}`),
+        },
+      },
+      {
+        createdAt: {
+          $lt: new Date(`${parseInt(tahun) + 1 || date.getFullYear() + 1}`),
+        },
+      },
+    ],
+  }
+
+  const laporan = await laporanModel
+    .find({ ...w, ...berdasarkan_tahun })
+    .populate('user')
+
+  const dataDelegasi = laporan.map((value) => ({
+    Tanggal: moment(value.createdAt).format('DD-MMMM-YYYY'),
+    'No. Laporan': value.no_laporan,
+    'Nama Perguruan Tinggi': value.pt.nama,
+    'Keterangan Laporan': value.keterangan,
+    'Dibuat Oleh': value.user.nama,
+    Status: !value.aktif
+      ? 'Ditutup'
+      : (value.role_asal === 'dikti' && value.role_data === 'dikti') ||
+        (value.role_data == 'dikti' && user.role.id === 2020) ||
+        (value.role_asal === 'lldikti' && value.role_data === 'lldikti') ||
+        (value.role_data == 'lldikti' && user.role.id === 2021)
+      ? `Ditindaklanjuti ${value.role_data === 'dikti' ? 'DIKTI' : 'LLDIKTI'}`
+      : `Delegasi Ke ${value.role_data === 'dikti' ? 'DIKTI' : 'LLDIKTI'}`,
+  }))
+
+  const dataLaporan = laporan.map((value) => ({
+    Tanggal: moment(value.createdAt).format('DD-MMMM-YYYY'),
+    'No. Laporan': value.no_laporan,
+    'Nama Perguruan Tinggi': value.pt.nama,
+    'Keterangan Laporan': value.keterangan,
+    'Dibuat Oleh': value.user.nama,
+    Status:
+      value.sanksi || value.aktif === false
+        ? 'Pelaporan Selesai'
+        : 'Pelaporan Belum Selesai',
+  }))
+
+  const dataJadwal = laporan
+    .filter((e) => e.aktif === true)
+    .map((value) => ({
+      Tanggal: moment(value.createdAt).format('DD-MMMM-YYYY'),
+      'No. Laporan': value.no_laporan,
+      'Nama Perguruan Tinggi': value.pt.nama,
+      'Keterangan Laporan': value.keterangan,
+      'Dibuat Oleh': value.user.nama,
+      'Dari Tanggal':
+        value.jadwal.judul &&
+        moment(value.jadwal.dari_tanggal).format('DD-MMMM-YYYY'),
+      'Sampai Tanggal':
+        value.jadwal.judul &&
+        moment(value.jadwal.sampai_tanggal).format('DD-MMMM-YYYY'),
+      Status: value.jadwal.judul ? 'Sudah ada jadwal' : 'Belum ada jadwal',
+    }))
+
+  const dataPemeriksaan = laporan
+    .filter((e) => e.aktif === true && e.jadwal.judul)
+    .map((value) => ({
+      Tanggal: moment(value.createdAt).format('DD-MMMM-YYYY'),
+      'No. Laporan': value.no_laporan,
+      'Nama Perguruan Tinggi': value.pt.nama,
+      'Keterangan Laporan': value.keterangan,
+      'Dibuat Oleh': value.user.nama,
+      Status: value.evaluasi.length ? 'Sudah diperiksa' : 'Belum diperiksa',
+    }))
+
+  const dataSanksi = laporan
+    .filter((e) => e.aktif === true && e.evaluasi.length)
+    .map((value) => ({
+      Tanggal: moment(value.createdAt).format('DD-MMMM-YYYY'),
+      'No. Laporan': value.no_laporan,
+      'Nama Perguruan Tinggi': value.pt.nama,
+      'Keterangan Laporan': value.keterangan,
+      'Dibuat Oleh': value.user.nama,
+      Status: value.sanksi ? 'Sudah ditetapkan' : 'Belum ditetapkan',
+    }))
+
+  const data = []
+  if (delegasi === 'true') {
+    data.push({ SheetNames: 'Delegasi', data: dataDelegasi })
+  }
+  if (pelaporan === 'true') {
+    data.push({ SheetNames: 'Pelaporan', data: dataLaporan })
+  }
+  if (penjadwalan === 'true') {
+    data.push({
+      SheetNames: 'Penjadwalan',
+      data: dataJadwal,
+    })
+  }
+  if (pemeriksaan === 'true') {
+    data.push({ SheetNames: 'Pemeriksaan', data: dataPemeriksaan })
+  }
+  if (sanksi === 'true') {
+    data.push({ SheetNames: 'Sanksi', data: dataSanksi })
+  }
+  const buffer = excel.to_excel(data)
+
+  res.header(
+    'Content-Type',
+    'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
+  )
+  return res.end(Buffer.from(buffer))
+})
+
+exports.laporanSelesai = handleError(async (req, res) => {
+  const user = req.user
+
+  laporan = await cekBanyakDataLaporan(user, { aktif: false })
+  sanksi = await cekBanyakDataSanksi(user, { aktif: false })
+  const data = {
+    laporan,
+    sanksi,
+    jumlah_selesai: sanksi.length,
+    jumlah_ditutup: laporan.length,
+  }
+
+  return response.success(res, {
+    message: 'Berhasil menganalisis data',
+    data,
+  })
+})
+
+exports.jumlahStatusLaporan = handleError(async (req, res) => {
+  let dataPembina = await laporanModel.find({
+    aktif: true,
+  })
+  const user = req.user
+
+  dataPembina = [
+    ...new Set(
+      dataPembina.map((e) => `${e.pt.pembina.id};${e.pt.pembina.nama}`)
+    ),
+  ]
+
+  dataPembina = dataPembina.map((e) => ({
+    id: e.split(';')[0],
+    name: e.split(';')[1],
+  })).sort((a, b) => a.name < b.name ? -1 : 1)
+
+  let data = await Promise.all(
+    dataPembina.map(async (e) => {
+      return {
+        pembina: e,
+        laporan: await cekBanyakDataLaporan(user, {
+          all: true,
+          ['pt.pembina.id']: e.id,
+        }),
+        sanksi: (
+          await cekBanyakDataSanksi(
+            user,
+            { all: true },
+            { ['pt.pembina.id']: e.id }
+          )
+        ).filter((e) => e.laporan != null),
+        jumlah_jadwal_evaluasi: await laporanModel
+          .find({
+            aktif: true,
+            jadwal: {
+              $ne: null,
+              $exists: true,
+            },
+            'pt.pembina.id': e.id,
+          })
+          .count(),
+        jumlah_pemeriksaan: await laporanModel
+          .find({
+            aktif: true,
+            evaluasi: {
+              $ne: null,
+              $not: {
+                $size: 0,
+              },
+              $exists: true,
+            },
+            'pt.pembina.id': e.id,
+          })
+          .count(),
+        jumlah_sanksi: await laporanModel
+          .find({
+            aktif: true,
+            sanksi: {
+              $ne: null,
+              $exists: true,
+            },
+            'pt.pembina.id': e.id,
+          })
+          .count(),
+        jumlah_keberatan: (
+          await sanksiModel
+            .find({
+              aktif: true,
+              'pengajuan.keberatan': {
+                $ne: null,
+                $exists: true,
+              },
+            })
+            .populate({
+              path: 'laporan',
+              match: {
+                'pt.pembina.id': e.id,
+              },
+            })
+        ).filter((e) => e.laporan != null).length,
+        jumlah_banding: (
+          await sanksiModel
+            .find({
+              aktif: true,
+              'pengajuan.banding': {
+                $ne: null,
+                $exists: true,
+              },
+            })
+            .populate({
+              path: 'laporan',
+              match: {
+                'pt.pembina.id': e.id,
+              },
+            })
+        ).filter((e) => e.laporan != null).length,
+        jumlah_pemantauan_perbaikan: (
+          await sanksiModel
+            .find({
+              aktif: true,
+              perbaikan: {
+                $ne: [],
+                $exists: true,
+              },
+            })
+            .populate({
+              path: 'laporan',
+              match: {
+                'pt.pembina.id': e.id,
+              },
+            })
+        ).filter((e) => e.laporan != null).length,
+        jumlah_pencabutan_sanksi: (
+          await sanksiModel
+            .find({
+              aktif: true,
+              'pengajuan.cabut_sanksi': {
+                $ne: null,
+                $exists: true,
+              },
+            })
+            .populate({
+              path: 'laporan',
+              match: {
+                'pt.pembina.id': e.id,
+              },
+            })
+        ).filter((e) => e.laporan != null).length,
+      }
+    })
+  )
+
+  return response.success(res, {
+    message: 'Berhasil menganalisis data',
+    data,
+  })
+})

+ 36 - 0
controller/log.controller.js

@@ -0,0 +1,36 @@
+const logModel = require('../model/log.model')
+const handleError = require('../utils/handleError')
+const response = require('../utils/responseHandler')
+const { validate } = require('../utils/validation')
+
+exports.create = handleError(async (req, res) => {
+  const user = req.user
+  const { aktivitas, os, ipv4, menu } = req.body
+
+  const isValid = validate(res, req.body, {
+    aktivitas: 'string',
+    os: 'string',
+    ipv4: 'string',
+  })
+  if (!isValid) return
+
+  await logModel.create({
+    user: user._id,
+    aktivitas,
+    os,
+    ipv4,
+    menu,
+  })
+
+  return response.success(res, {
+    message: 'log berhasil dibuat',
+  })
+})
+
+exports.all = handleError(async (req, res) => {
+  const log = await logModel.find().populate('user').sort({ createdAt: -1 })
+
+  return response.success(res, {
+    data: log,
+  })
+})

+ 146 - 0
controller/pengunjung.controller.js

@@ -0,0 +1,146 @@
+const pengunjungModel = require('../model/pengunjung.model')
+const handleError = require('../utils/handleError')
+const response = require('../utils/responseHandler')
+const { validate } = require('../utils/validation')
+
+exports.create = handleError(async (req, res) => {
+  const { os, ipv4, location } = req.body
+  const isValid = validate(res, req.body, {
+    os: 'string',
+    ipv4: 'string',
+    location: {
+      $$type: 'object',
+      country: 'string',
+      region: 'string',
+      city: 'string',
+      lat: 'number',
+      lon: 'number',
+      timezone: 'string',
+    },
+  })
+  if (!isValid) return
+
+  await pengunjungModel.create({ os, ipv4, location })
+
+  return response.success(res, {
+    message: 'data pengunjung berhasil dibuat',
+  })
+})
+
+exports.getPengunjung = handleError(async (req, res) => {
+  const { tahun } = req.query
+
+  let date = {}
+  if (tahun) {
+    date = {
+      $expr: {
+        $eq: [
+          { $year: '$createdAt' },
+          parseInt(tahun) || new Date().getFullYear(),
+        ],
+      },
+    }
+  }
+
+  const pengunjung = await pengunjungModel.aggregate([
+    { $match: date },
+    {
+      $group: {
+        _id: {
+          bulan: {
+            $month: '$createdAt',
+          },
+          tahun: {
+            $year: '$createdAt',
+          },
+        },
+        jumlah_pengunjung: {
+          $sum: 1,
+        },
+      },
+    },
+    {
+      $sort: {
+        ['_id.bulan']: 1,
+      },
+    },
+  ])
+
+  return response.success(res, {
+    message: 'data pengunjung',
+    data: pengunjung,
+  })
+})
+
+exports.getPengunjungPublic = handleError(async (req, res) => {
+  const { tahun, bulan } = req.query
+
+  let date = {}
+  if (tahun || bulan) {
+    date = {
+      $expr: {
+        $and: [
+          {
+            $eq: [
+              { $year: '$createdAt' },
+              parseInt(tahun) || new Date().getFullYear(),
+            ],
+          },
+          {
+            $eq: [
+              { $month: '$createdAt' },
+              parseInt(bulan) || new Date().getMonth() + 1,
+            ],
+          },
+        ],
+      },
+    }
+  }
+
+  const pengunjung = await pengunjungModel.aggregate([
+    { $match: date },
+    {
+      $group: {
+        _id: {
+          tanggal: {
+            $dayOfMonth: '$createdAt',
+          },
+          bulan: {
+            $month: '$createdAt',
+          },
+          tahun: {
+            $year: '$createdAt',
+          },
+        },
+        jumlah_pengunjung: {
+          $sum: 1,
+        },
+        data_ip: {
+          $addToSet: '$ipv4',
+        },
+      },
+    },
+    {
+      $addFields: {
+        jumlah_pengunjung: {
+          $size: '$data_ip',
+        },
+      },
+    },
+    {
+      $project: {
+        data_ip: 0,
+      },
+    },
+    {
+      $sort: {
+        ['_id.tanggal']: 1,
+      },
+    },
+  ])
+
+  return response.success(res, {
+    message: 'data pengunjung',
+    data: pengunjung,
+  })
+})

+ 60 - 0
controller/rekomendasi.controller.js

@@ -0,0 +1,60 @@
+const handleError = require('../utils/handleError')
+const response = require('../utils/responseHandler')
+const { addManyDokumen } = require('../utils/dokumenFunction')
+const { cekSatuDataSanksi } = require('../utils/cekData')
+const pemantauanModel = require('../model/pemantauan.model')
+const sanksiModel = require('../model/sanksi.model')
+
+exports.createRekomendasi = handleError(async (req, res) => {
+  const user = req.user
+  const { id } = req.params
+
+  const sanksi = await cekSatuDataSanksi(res, user, id, { delegasi: true })
+  if (!sanksi) return
+
+  const files = req.files
+  if (!files.length) {
+    return response.error(res, {
+      message: 'dokumen harus ada',
+    })
+  }
+  const dokumen = await addManyDokumen(files)
+  const dokumen_id = dokumen.map((e) => e._id)
+
+  const data = await sanksiModel.findOneAndUpdate(
+    {
+      _id: sanksi._id,
+    },
+    {
+      $push: {
+        rekomendasi: {
+          dokumen: dokumen_id,
+        },
+      },
+    },
+    {
+      new: true,
+    }
+  )
+
+  let for_public = true
+  if (sanksi.rekomendasi.length > 0) {
+    for_public = false
+  }
+
+  await pemantauanModel.create({
+    laporan: sanksi.laporan._id,
+    user: user._id,
+    action: 'ADD REKOMENDASI',
+    pt_id: sanksi.laporan.pt.id,
+    keterangan: 'Melakukan rekomendasi delegasi',
+    dokumen: dokumen_id,
+    for_pt: false,
+    for_public,
+  })
+
+  return response.success(res, {
+    message: 'Berhasil tambah rekomendasi delegasi',
+    data,
+  })
+})

+ 5 - 5
package.json

@@ -1,6 +1,6 @@
 {
   "name": "ptb-api",
-  "version": "0.0.0",
+  "version": "1.0.0",
   "type": "commonjs",
   "private": true,
   "scripts": {
@@ -8,7 +8,7 @@
     "dev": "nodemon ./bin/www"
   },
   "dependencies": {
-    "axios": "^0.26.1",
+    "axios": "^0.27.2",
     "bcrypt": "^5.0.1",
     "child-process": "^1.0.2",
     "cookie-parser": "~1.4.4",
@@ -28,8 +28,8 @@
     "xlsx": "^0.18.5"
   },
   "devDependencies": {
-    "eslint": "^8.10.0",
-    "nodemon": "^2.0.15",
-    "prettier-eslint": "^13.0.0"
+    "eslint": "^8.17.0",
+    "nodemon": "^2.0.16",
+    "prettier-eslint": "^15.0.1"
   }
 }

+ 1 - 0
routes/v1/laporan/index.js

@@ -2,6 +2,7 @@ const router = require('express').Router()
 const laporan = require('../../../controller/v1/laporan.controller')
 const handleDokumen = require('../../../utils/handleDokumen')
 const roleId = require('../../../middleware/role')
+const roleId = require('../../../middleware/role')
 
 router.get('/', laporan.getAll)
 router.get('/jumlah', laporan.jumlahLaporan)

+ 4 - 0
tes.js

@@ -0,0 +1,4 @@
+const ip = require('ip')
+
+console.log(ip.address())
+console.log(process.platform)

+ 33 - 0
utils/notifFunction.js

@@ -0,0 +1,33 @@
+const axios = require('../utils/axios')
+const kontakModel = require('../model/kontak.model')
+
+exports.notifWA = async (templateId, data, where = {}) => {
+  const kontak = await kontakModel.find(where)
+  const contacts = kontak.map((e) => ({ name: e.nama, number: e.no_hp }))
+  const send = await axios.post(
+    'https://api.kemdikbud.go.id:8243/qontak/1.0/send',
+    {
+      templateId,
+      contacts,
+      body: data,
+    }
+  )
+  return send
+}
+
+exports.notifWA2 = async (templateId, { nama, no_hp }, data) => {
+  const send = await axios.post(
+    'https://api.kemdikbud.go.id:8243/qontak/1.0/send',
+    {
+      templateId,
+      contacts: [
+        {
+          name: nama,
+          number: no_hp,
+        },
+      ],
+      body: data,
+    }
+  )
+  return send
+}