2610 lines
111 KiB
JavaScript
2610 lines
111 KiB
JavaScript
const fs = require('fs');
|
|
const moment = require('moment');
|
|
const Validator = require('validatorjs');
|
|
const path = require("path");
|
|
const axios = require('axios').default;
|
|
const url = require('url');
|
|
const mysql = require('mysql');
|
|
const response = require('../config/response');
|
|
const Helper = require('../library/LibHelper');
|
|
// const LibPassword = require('../library/LibPassword');
|
|
const LibJwt = require('../library/LibJwt');
|
|
const LibHelper = require('../library/LibHelper');
|
|
const LibFirebase = require('../library/LibFirebase');
|
|
const LibCurl = require('../library/LibCurl');
|
|
const LibFile = require('../library/LibFile');
|
|
const LibMail = require('../library/LibMail');
|
|
const LibLogReqResApi = require('../library/LibLogReqResApi');
|
|
const LibImgGeotagging = require('../library/LibImgGeotagging');
|
|
const GpsTracksModels = require('../models/GpsTracksModels');
|
|
const DriversModels = require('../models/DriversModels');
|
|
const OrdersModels = require('../models/OrdersModels');
|
|
const OrdersPickupsModels = require('../models/OrdersPickupsModels');
|
|
const OrdersDropsModels = require('../models/OrdersDropsModels');
|
|
const OrdersPckDropsModels = require('../models/OrdersPckDropsModels');
|
|
const OrdersDriversUploadsModels = require('../models/OrdersDriversUploadsModels');
|
|
const OrdersCheckpointsModels = require('../models/OrdersCheckpointsModels');
|
|
const VhcModels = require('../models/VhcModels');
|
|
const ZoneModels = require('../models/ZoneModels');
|
|
const UsersModels = require('../models/UsersModels');
|
|
const OrdersAItemsModels = require('../models/OrdersAItemsModels');
|
|
const OrdersTerminsModels = require('../models/OrdersTerminsModels');
|
|
const LogbookKeysModels = require('../models/LogbookKeysModels');
|
|
const LogbookOrdersModels = require('../models/LogbookOrdersModels');
|
|
const OrdersLogsTfModels = require('../models/OrdersLogsTfModels');
|
|
const DanaModels = require('../models/DanaModels');
|
|
|
|
Validator.useLang('id');
|
|
moment.locale('id');
|
|
|
|
class ServiceDriverController {
|
|
|
|
// AUTHENTIFICATION
|
|
async login(req, res) {
|
|
let apiRes = {}
|
|
try {
|
|
const now = moment().unix()
|
|
|
|
// input validation
|
|
const input = {
|
|
phone: req.body.phone,
|
|
device_id: req.body.device_id,
|
|
fcm_token: req.body.fcm_token,
|
|
lat: req.body.lat,
|
|
lng: req.body.lng,
|
|
brand: req.body.brand || '0',
|
|
product: req.body.product || '0',
|
|
model: req.body.model || '0',
|
|
type: req.body.type || '0',
|
|
manufacture: req.body.manufacture || '0',
|
|
android_id: req.body.android_id || '0',
|
|
host: req.body.host || '0',
|
|
hardware: req.body.hardware || '0',
|
|
display: req.body.display || '0',
|
|
board: req.body.board || '0',
|
|
bootloader: req.body.bootloader || '0',
|
|
v_sdk_int: req.body.v_sdk_int || '0',
|
|
v_preview_sdk_int: req.body.v_preview_sdk_int || '0',
|
|
v_release: req.body.v_release || '0',
|
|
v_incremental: req.body.v_incremental || '0',
|
|
v_codename: req.body.v_codename || '0',
|
|
v_base_os: req.body.v_base_os || '0',
|
|
v_security_patch: req.body.v_security_patch || '0',
|
|
// password: req.body.password,
|
|
};
|
|
const rulesInput = {
|
|
phone: 'required|integer',
|
|
device_id: 'required|string|max:16',
|
|
fcm_token: 'required|string|max:255',
|
|
lat: 'required|string|max:125',
|
|
lng: 'required|string|max:125',
|
|
brand: 'string|max:125',
|
|
product: 'string|max:125',
|
|
model: 'string|max:125',
|
|
type: 'string|max:125',
|
|
manufacture: 'string|max:125',
|
|
android_id: 'string|max:125',
|
|
host: 'string|max:125',
|
|
hardware: 'string|max:125',
|
|
display: 'string|max:125',
|
|
board: 'string|max:125',
|
|
bootloader: 'string|max:125',
|
|
v_sdk_int: 'string|max:125',
|
|
v_preview_sdk_int: 'string|max:125',
|
|
v_release: 'string|max:125',
|
|
v_incremental: 'string|max:125',
|
|
v_codename: 'string|max:125',
|
|
v_base_os: 'string|max:125',
|
|
v_security_patch: 'string|max:125',
|
|
// password: 'required|string',
|
|
};
|
|
const isInputValid = new Validator(input, rulesInput);
|
|
if (isInputValid.fails()) {
|
|
apiRes = JSON.parse(JSON.stringify(response[422]));
|
|
apiRes.meta.message += Helper.setErrMsg(': ' + Object.values(isInputValid.errors.all())[0][0]); // get first message
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
|
|
// login
|
|
const getDrivers = await DriversModels.findPhone(input.phone);
|
|
if (getDrivers.length < 1) {
|
|
apiRes = JSON.parse(JSON.stringify(response[404]));
|
|
apiRes.meta.code += '_1';
|
|
apiRes.meta.message = 'account not found';
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
// const isPwValid = await LibPassword.checkPw(getDrivers[0].password, input.password);
|
|
// if (!isPwValid) {
|
|
// apiRes.meta = JSON.parse(JSON.stringify(response['wrong_password'].meta));
|
|
// return res.status(200).json(apiRes);
|
|
// }
|
|
|
|
/**
|
|
* create or update t_users based on t_drivers data without password, with role as driver
|
|
* create or update t_phone_devices
|
|
* case multiple device => update hanya berlaku jika device_id(IMEI) sama, jadi did bisa duplicate namun device_id(IMEI) tidak ada yang duplicate
|
|
* case single device => update hanya berlaku jika did sama, jadi tidak ada did dan device_id(IMEI) yang duplicate
|
|
* harus tentuin salah satu mau single / multiple, soalnya nanti bingung ngambil fcm_tokennya
|
|
* is_login ? taro di t_phone_devices aja, jadi ketauan kalo dia logout
|
|
* login_lat & login_lng ? taro di t_phone_devices aja, jadi ketauan device ini adanya dimana
|
|
* jika sedang ada yang login maka driver tidak bisa dihapus
|
|
*/
|
|
|
|
// yang sekarang 1 device 1 driver
|
|
const checkDeviceByDid = await DriversModels.getDeviceByDid(getDrivers[0].id);
|
|
let phone_device_id = 0;
|
|
if (checkDeviceByDid.length < 1) {
|
|
const checkDeviceByImei = await DriversModels.getDeviceByImei(input.device_id);
|
|
if (checkDeviceByImei.length < 1) {
|
|
const insDevice = { ...input };
|
|
insDevice.did = getDrivers[0].id;
|
|
insDevice.is_active = DriversModels.IS_ACTIVE;
|
|
insDevice.is_login = DriversModels.IS_LOGIN;
|
|
insDevice.login_lat = input.lat;
|
|
insDevice.login_lng = input.lng;
|
|
insDevice.login_at = now;
|
|
insDevice.crt = now;
|
|
insDevice.updt = now;
|
|
delete insDevice.phone;
|
|
delete insDevice.lat;
|
|
delete insDevice.lng;
|
|
const insPhoneDevice = await DriversModels.insPhoneDevice(insDevice);
|
|
phone_device_id = insPhoneDevice.insertId;
|
|
} else {
|
|
if (checkDeviceByImei[0].is_login === DriversModels.IS_LOGIN) {
|
|
if (checkDeviceByImei[0].device_id !== input.device_id) { // || checkDeviceByImei[0].phone !== input.phone
|
|
apiRes = JSON.parse(JSON.stringify(response[400]));
|
|
apiRes.meta.code += '_2';
|
|
apiRes.meta.message = 'account is used by another phone, please contact customer service';
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
}
|
|
const updtDevice = { ...input };
|
|
updtDevice.did = getDrivers[0].id;
|
|
updtDevice.is_active = DriversModels.IS_ACTIVE;
|
|
updtDevice.is_login = DriversModels.IS_LOGIN;
|
|
updtDevice.login_lat = input.lat;
|
|
updtDevice.login_lng = input.lng;
|
|
updtDevice.login_at = now;
|
|
updtDevice.updt = now;
|
|
delete updtDevice.phone;
|
|
delete updtDevice.lat;
|
|
delete updtDevice.lng;
|
|
const updtPhoneDevice = await DriversModels.updtPhoneDevice(updtDevice, checkDeviceByImei[0].id);
|
|
phone_device_id = checkDeviceByImei[0].id;
|
|
}
|
|
} else {
|
|
if (checkDeviceByDid[0].is_login === DriversModels.IS_LOGIN) {
|
|
if (checkDeviceByDid[0].device_id !== input.device_id) { // || checkDeviceByDid[0].phone !== input.phone
|
|
apiRes = JSON.parse(JSON.stringify(response[400]));
|
|
apiRes.meta.code += '_2';
|
|
apiRes.meta.message = 'account is used by another phone, please contact customer service';
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
}
|
|
const updtDevice = { ...input };
|
|
updtDevice.did = getDrivers[0].id;
|
|
updtDevice.is_active = DriversModels.IS_ACTIVE;
|
|
updtDevice.is_login = DriversModels.IS_LOGIN;
|
|
updtDevice.login_lat = input.lat;
|
|
updtDevice.login_lng = input.lng;
|
|
updtDevice.login_at = now;
|
|
updtDevice.updt = now;
|
|
delete updtDevice.phone;
|
|
delete updtDevice.lat;
|
|
delete updtDevice.lng;
|
|
const updtPhoneDevice = await DriversModels.updtPhoneDevice(updtDevice, checkDeviceByDid[0].id);
|
|
phone_device_id = checkDeviceByDid[0].id;
|
|
}
|
|
|
|
delete getDrivers[0].client_group_id;
|
|
delete getDrivers[0].client_div_id;
|
|
delete getDrivers[0].client_gp_id;
|
|
// delete getDrivers[0].status;
|
|
delete getDrivers[0].is_in_ord;
|
|
delete getDrivers[0].ord_id;
|
|
delete getDrivers[0].ord_code;
|
|
delete getDrivers[0].ord_ids;
|
|
delete getDrivers[0].ord_code;
|
|
|
|
// success response
|
|
const jwt = await LibJwt.createToken({
|
|
did: getDrivers[0].id,
|
|
phone: getDrivers[0].phone,
|
|
device_id: input.device_id,
|
|
phone_device_id,
|
|
uid: 0,
|
|
});
|
|
|
|
const profileDriver = {
|
|
drv_id: getDrivers[0].id,
|
|
nik: getDrivers[0].nik,
|
|
fullname: getDrivers[0].fullname,
|
|
fullname2: getDrivers[0].fullname2 || '',
|
|
phone: getDrivers[0].phone_code + '' +getDrivers[0].phone,
|
|
phone2: getDrivers[0].phone2_code + '' +getDrivers[0].phone2,
|
|
email: getDrivers[0].email || '',
|
|
dob: moment(getDrivers[0].dob).format('DD-MM-YYYY'),
|
|
age: getDrivers[0].age || 0,
|
|
gender: (getDrivers[0].gender === 1) ? 'Laki-Laki' : 'Perempuan',
|
|
blood: getDrivers[0].blood || '',
|
|
fulladdress: getDrivers[0].fulladdress || '',
|
|
vdr_id: getDrivers[0].vendor_id || 0,
|
|
// status: getDrivers[0].status,
|
|
// is_in_ord: getDrivers[0].is_in_ord,
|
|
// ord_ids: (getDrivers[0].ord_ids === null) ? getDrivers[0].ord_ids : JSON.parse(getDrivers[0].ord_ids),
|
|
token: jwt.token,
|
|
};
|
|
|
|
apiRes = JSON.parse(JSON.stringify(response[200]));
|
|
apiRes.meta.message = 'success login';
|
|
apiRes.data = profileDriver;
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
} catch (e) {
|
|
apiRes = JSON.parse(JSON.stringify(response[500]));
|
|
apiRes.meta.message += Helper.setErrMsg(': ' + e.message);
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(500).json(apiRes);
|
|
}
|
|
}
|
|
|
|
async profile(req, res) {
|
|
let apiRes = {}
|
|
try {
|
|
const now = moment().unix();
|
|
const { did } = req.auth;
|
|
|
|
const getDrivers = await DriversModels.find(did);
|
|
if (getDrivers.length < 1) {
|
|
apiRes = JSON.parse(JSON.stringify(response[404]));
|
|
apiRes.meta.code += '_1';
|
|
apiRes.meta.message = 'account not found, please login again';
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
const profileDriver = {
|
|
drv_id: getDrivers[0].id,
|
|
nik: getDrivers[0].nik,
|
|
fullname: getDrivers[0].fullname,
|
|
fullname2: getDrivers[0].fullname2 || '',
|
|
phone: getDrivers[0].phone_code + '' +getDrivers[0].phone,
|
|
phone2: getDrivers[0].phone2_code + '' +getDrivers[0].phone2,
|
|
email: getDrivers[0].email || '',
|
|
dob: (getDrivers[0].dob) ? moment(getDrivers[0].dob).format('DD-MM-YYYY') : '',
|
|
age: getDrivers[0].age || 0,
|
|
gender: (getDrivers[0].gender === 1) ? 'Laki-Laki' : 'Perempuan',
|
|
blood: getDrivers[0].blood || '',
|
|
fulladdress: getDrivers[0].fulladdress || '',
|
|
vdr_id: getDrivers[0].vendor_id || 0,
|
|
// status: getDrivers[0].status,
|
|
// is_in_ord: getDrivers[0].is_in_ord,
|
|
// ord_ids: (getDrivers[0].ord_ids === null) ? getDrivers[0].ord_ids : JSON.parse(getDrivers[0].ord_ids),
|
|
};
|
|
|
|
apiRes = JSON.parse(JSON.stringify(response[200]));
|
|
apiRes.data = profileDriver;
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
} catch (e) {
|
|
apiRes = JSON.parse(JSON.stringify(response[500]));
|
|
apiRes.meta.message += Helper.setErrMsg(': ' + e.message);
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(500).json(apiRes);
|
|
}
|
|
}
|
|
|
|
async logout(req, res) {
|
|
let apiRes = {}
|
|
try {
|
|
const now = moment().unix();
|
|
const { phone_device_id } = req.auth;
|
|
|
|
const updtDevice = {
|
|
is_login: DriversModels.IS_LOGOUT,
|
|
logout_at: now,
|
|
};
|
|
const updtPhoneDevice = await DriversModels.updtPhoneDevice(updtDevice, phone_device_id);
|
|
|
|
apiRes = JSON.parse(JSON.stringify(response[200]));
|
|
apiRes.meta.message = 'success logout';
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
} catch (e) {
|
|
apiRes = JSON.parse(JSON.stringify(response[500]));
|
|
apiRes.meta.message += Helper.setErrMsg(': ' + e.message);
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(500).json(apiRes);
|
|
}
|
|
}
|
|
|
|
// JOBS
|
|
async listActiveJobs(req, res) {
|
|
let apiRes = {}
|
|
try {
|
|
const now = moment().unix();
|
|
|
|
// console.log(Buffer.from(`32_34_34_28`, 'ascii').toString('hex'));
|
|
|
|
const { did, device_id, phone } = req.auth;
|
|
|
|
const filter = {
|
|
is_active: OrdersModels.IS_ACTIVE,
|
|
// order_status: [OrdersModels.STTS_HAVE_GET_VHC,OrdersModels.STTS_PCK,OrdersModels.STTS_GO,OrdersModels.STTS_ARV,OrdersModels.STTS_DROP],
|
|
delivery_statuses: [
|
|
OrdersPckDropsModels.STTS_DELIVERY_OTW_PICKUP,OrdersPckDropsModels.STTS_DELIVERY_ARRIVED_PICKUP,OrdersPckDropsModels.STTS_DELIVERY_PROCESS_PICKUP
|
|
,OrdersPckDropsModels.STTS_DELIVERY_FINISH_PICKUP,OrdersPckDropsModels.STTS_DELIVERY_TRAVEL_DOC,OrdersPckDropsModels.STTS_DELIVERY_OTW_DROP
|
|
,OrdersPckDropsModels.STTS_DELIVERY_ARRIVED_DROP,OrdersPckDropsModels.STTS_DELIVERY_PROCESS_DROP,OrdersPckDropsModels.STTS_DELIVERY_FINISH_DROP
|
|
// ,OrdersPckDropsModels.STTS_DELIVERY_HANDOVER_DOC
|
|
],
|
|
get_prefer_type_truck: 1,
|
|
couple_pck_drop: 1,
|
|
get_pic_zone: 1,
|
|
did,
|
|
};
|
|
const activeOrders = await OrdersModels.listOrders(filter);
|
|
if (activeOrders.length < 1) {
|
|
apiRes = JSON.parse(JSON.stringify(response[404]));
|
|
apiRes.meta.code = '200'; // += '_1';
|
|
apiRes.meta.message = 'there are no active orders';
|
|
apiRes.data = [];
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
|
|
const formattedActiveOrders = [], includedPckId = [], includedDropId = [];
|
|
for (const row of activeOrders) {
|
|
if (includedPckId.includes(row.ord_pck_id) || includedDropId.includes(row.ord_drop_id)) continue;
|
|
includedPckId.push(row.ord_pck_id);
|
|
includedDropId.push(row.ord_drop_id);
|
|
|
|
const detail_id = Buffer.from(`${row.ord_id}_${row.ord_pck_id}_${row.ord_drop_id}_${row.ord_pck_drop_id}`, 'ascii').toString('hex');
|
|
// const decoded_detail_id = Buffer.from('34365f34305f3339', 'hex').toString('ascii');
|
|
|
|
let status_desc = '';
|
|
if (row.stts_delivery === OrdersPckDropsModels.STTS_DELIVERY_OTW_PICKUP) { status_desc = 'Kendaraan Menuju Lokasi Jemput'; }
|
|
else if (row.stts_delivery === OrdersPckDropsModels.STTS_DELIVERY_ARRIVED_PICKUP) { status_desc = 'Kendaraan Tiba dilokasi Jemput'; }
|
|
else if (row.stts_delivery === OrdersPckDropsModels.STTS_DELIVERY_PROCESS_PICKUP) { status_desc = 'Kendaraan Memuat Barang'; }
|
|
else if (row.stts_delivery === OrdersPckDropsModels.STTS_DELIVERY_FINISH_PICKUP) { status_desc = 'Kendaraan Selesai Memuat Barang'; }
|
|
else if (row.stts_delivery === OrdersPckDropsModels.STTS_DELIVERY_TRAVEL_DOC) { status_desc = 'Driver Sudah Mengupload Dokumen Perjalanan'; }
|
|
else if (row.stts_delivery === OrdersPckDropsModels.STTS_DELIVERY_OTW_DROP) { status_desc = 'Kendaraan Menuju Lokasi Pengantaran'; }
|
|
else if (row.stts_delivery === OrdersPckDropsModels.STTS_DELIVERY_ARRIVED_DROP) { status_desc = 'Kendaraan Sampai Dilokasi Pengantaran'; }
|
|
else if (row.stts_delivery === OrdersPckDropsModels.STTS_DELIVERY_PROCESS_DROP) { status_desc = 'Kendaraan Membongkar Barang'; }
|
|
else if (row.stts_delivery === OrdersPckDropsModels.STTS_DELIVERY_FINISH_DROP) { status_desc = 'Kendaraan Selesai Membongkar Barang'; }
|
|
else if (row.stts_delivery === OrdersPckDropsModels.STTS_DELIVERY_HANDOVER_DOC) { status_desc = 'Driver Sudah Mengupload Dokumen Serah Terima'; }
|
|
|
|
// validate is_going / ongoing by pickup date
|
|
let is_ongoing = false;
|
|
if (row.set_pck_at) {
|
|
let cur_date = moment.unix(now).set({hour:0,minute:0,second:0,millisecond:0}); // as start
|
|
let pck_date = moment.unix(row.set_pck_at).set({hour:0,minute:0,second:0,millisecond:0}); // as end
|
|
let duration = moment.duration(pck_date.diff(cur_date));
|
|
if (duration.asDays() <= 0) {
|
|
is_ongoing = true;
|
|
}
|
|
}
|
|
|
|
// https://stackoverflow.com/questions/23299950/convert-date-to-utc-using-moment-js
|
|
formattedActiveOrders.push({
|
|
detail_id,
|
|
// ord_pck_drop_id: row.ord_pck_drop_id,
|
|
ord_id: row.ord_id,
|
|
ord_code: row.ord_code,
|
|
// pck_total: row.pck_total,
|
|
// drop_total: row.drop_total,
|
|
is_ongoing,
|
|
pck: {
|
|
id: row.ord_pck_id,
|
|
set_at_unix: row.set_pck_at,
|
|
// set_at_raw: (row.set_pck_at != 0) ? moment.unix(row.set_pck_at).utc().format('YYYY-MM-DDTHH:mm:ss.SSS') + 'Z' : '', // utc
|
|
set_at_raw: (row.set_pck_at != 0) ? moment.unix(row.set_pck_at).format('YYYY-MM-DDTHH:mm:ss.SSS') + 'Z' : '', // gmt +7
|
|
// stts: row.stts_pck,
|
|
name: row.pck_name,
|
|
addr: row.pck_addr,
|
|
pic_name: row.pck_pic_name,
|
|
pic_phone: row.pck_pic_phone_code + '' + row.pck_pic_phone_val,
|
|
pic_mail: row.pck_pic_mail || '',
|
|
client_name: row.c_name,
|
|
client_phone: row.c_phone_code + '' + row.c_phone_val,
|
|
client_mail: row.c_mail,
|
|
client_prefer_truck_type: row.prefer_truck_type_name || '',
|
|
},
|
|
// going_at_unix: row.going_at,
|
|
// going_at_raw: (row.going_at != 0) ? moment.unix(row.going_at).utc().format('YYYY-MM-DDTHH:mm:ss.SSS') + 'Z' : '',
|
|
// going_note: row.going_note,
|
|
drop: {
|
|
id: row.ord_drop_id,
|
|
// stts: row.ord_drop_stts,
|
|
name: row.drop_name,
|
|
addr: row.drop_addr,
|
|
pic_name: row.drop_pic_name,
|
|
pic_phone: row.drop_pic_phone_code + '' + row.drop_pic_phone_val,
|
|
pic_mail: row.drop_pic_mail || '',
|
|
client_name: row.c_name,
|
|
client_phone: row.c_phone_code + '' + row.c_phone_val,
|
|
client_mail: row.c_mail,
|
|
client_prefer_truck_type: row.prefer_truck_type_name || '',
|
|
},
|
|
// arrived_at_unix: row.arrived_at,
|
|
// arrived_at_raw: (row.arrived_at != 0) ? moment.unix(row.arrived_at).utc().format('YYYY-MM-DDTHH:mm:ss.SSS') + 'Z' : '',
|
|
// arrived_note: row.arrived_note,
|
|
lead_time: row.lead_time,
|
|
lead_time_unit: row.lead_time_unit,
|
|
// buy_price: row.buy_price,
|
|
status: row.stts_delivery,
|
|
status_desc,
|
|
// c_name: row.c_name,
|
|
// c_phone: row.c_phone_code + '' + row.c_phone_val,
|
|
// c_mail: row.c_mail,
|
|
// prefer_truck_type: row.prefer_truck_type,
|
|
// prefer_truck_type_name: row.prefer_truck_type_name || '',
|
|
vdr: {
|
|
name: row.vdr_name,
|
|
phone: row.vdr_phone_code + '' + row.vdr_phone_val,
|
|
mail: row.vdr_mail,
|
|
addr: row.vdr_addr,
|
|
},
|
|
drv: {
|
|
name: row.drv_name,
|
|
kenek_name: row.drv_name2,
|
|
phone: row.drv_phone_code + '' + row.drv_phone_val,
|
|
kenek_phone: row.drv_phone2_code + '' + row.drv_phone2_val,
|
|
mail: row.drv_mail,
|
|
addr: row.drv_addr,
|
|
},
|
|
vhc: {
|
|
name_bukan_nopol: row.vhc_name,
|
|
nopol1: row.vhc_nopol1,
|
|
nopol2: row.vhc_nopol2,
|
|
nopol3: row.vhc_nopol3,
|
|
nopol_full: row.vhc_nopol1 + ' ' + row.vhc_nopol2 + ' ' + row.vhc_nopol3,
|
|
},
|
|
});
|
|
}
|
|
|
|
apiRes = JSON.parse(JSON.stringify(response[200]));
|
|
apiRes.data = formattedActiveOrders;
|
|
// apiRes.raw = activeOrders;
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
} catch (e) {
|
|
apiRes = JSON.parse(JSON.stringify(response[500]));
|
|
apiRes.meta.message += Helper.setErrMsg(': ' + e.message);
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(500).json(apiRes);
|
|
}
|
|
}
|
|
|
|
async detailJobs(req, res) {
|
|
let apiRes = {}
|
|
try {
|
|
const now = moment().unix();
|
|
|
|
const { did, device_id, phone } = req.auth;
|
|
const { detail_id } = req.params;
|
|
|
|
// input validation
|
|
const input = {
|
|
detail_id,
|
|
};
|
|
const rulesInput = {
|
|
detail_id: 'required|string',
|
|
};
|
|
const isInputValid = new Validator(input, rulesInput);
|
|
if (isInputValid.fails()) {
|
|
apiRes = JSON.parse(JSON.stringify(response[422]));
|
|
apiRes.meta.message += Helper.setErrMsg(': ' + Object.values(isInputValid.errors.all())[0][0]); // get first message
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
|
|
const decoded_detail_id = Buffer.from(detail_id, 'hex').toString('ascii');
|
|
const split_detail_id = decoded_detail_id.split('_');
|
|
if (split_detail_id.length !== 4) {
|
|
apiRes = JSON.parse(JSON.stringify(response[422]));
|
|
apiRes.meta.code += '_1';
|
|
apiRes.meta.message = 'detail id not valid';
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
const [ ord_id, pck_id, drop_id, ord_pck_drop_id ] = split_detail_id;
|
|
|
|
const filter = {
|
|
ord_id,
|
|
pck_id,
|
|
drop_id,
|
|
ord_pck_drop_id,
|
|
// is_active: OrdersModels.IS_ACTIVE,
|
|
// order_status: [OrdersModels.STTS_HAVE_GET_VHC,OrdersModels.STTS_PCK,OrdersModels.STTS_GO,OrdersModels.STTS_ARV,OrdersModels.STTS_DROP],
|
|
get_prefer_type_truck: 1,
|
|
couple_pck_drop: 1,
|
|
get_pic_zone: 1,
|
|
did,
|
|
};
|
|
const activeOrders = await OrdersModels.listOrders(filter);
|
|
if (activeOrders.length < 1) {
|
|
apiRes = JSON.parse(JSON.stringify(response[404]));
|
|
apiRes.meta.code += '_4';
|
|
apiRes.meta.message = 'job not found';
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
|
|
const drvUps = await OrdersDriversUploadsModels.list({ ord_id,pck_id,drop_id,ord_pck_drop_id });
|
|
/**
|
|
* 0 => disable
|
|
* 1 => enable
|
|
* 2 => finish
|
|
*/
|
|
const menu = {
|
|
menu_arrived_pickup: {
|
|
content: '1. Foto sudah dilokasi muat',
|
|
status: 0,
|
|
photo: '',
|
|
},
|
|
menu_process_pickup: {
|
|
content: '2. Foto sedang memuat barang',
|
|
status: 0,
|
|
photo: '',
|
|
},
|
|
menu_finish_pickup: {
|
|
content: '3. Foto selesai memuat barang',
|
|
status: 0,
|
|
photo: '',
|
|
},
|
|
menu_travel_document: {
|
|
content: '4. Foto dokumen perjalanan',
|
|
status: 0,
|
|
photo: '',
|
|
},
|
|
menu_otw_drop: {
|
|
content: '5. Foto saat diperjalanan (/2jam)',
|
|
status: 0,
|
|
photo: [],
|
|
},
|
|
menu_arrived_drop: {
|
|
content: '6. Foto tiba dilokasi bongkar',
|
|
status: 0,
|
|
photo: '',
|
|
},
|
|
menu_process_drop: {
|
|
content: '7. Foto proses bongkar',
|
|
status: 0,
|
|
photo: '',
|
|
},
|
|
menu_finish_drop: {
|
|
content: '8. Foto selesai bongkar',
|
|
status: 0,
|
|
photo: '',
|
|
},
|
|
menu_handover_document: {
|
|
content: '9. Foto dokumen serah terima',
|
|
status: 0,
|
|
photo: '',
|
|
},
|
|
menu_accident: {
|
|
content: 'Menu Accident',
|
|
status: 1,
|
|
photo: [],
|
|
},
|
|
};
|
|
for (const drvUp of drvUps) {
|
|
if (drvUp.stts === OrdersDriversUploadsModels.PHOTO_STATUS_ARRIVED_PICKUP) {
|
|
menu.menu_arrived_pickup.status = 2;
|
|
menu.menu_arrived_pickup.photo = drvUp.img;
|
|
} else if (drvUp.stts === OrdersDriversUploadsModels.PHOTO_STATUS_PROCESS_PICKUP) {
|
|
menu.menu_process_pickup.status = 2;
|
|
menu.menu_process_pickup.photo = drvUp.img;
|
|
} else if (drvUp.stts === OrdersDriversUploadsModels.PHOTO_STATUS_FINISH_PICKUP) {
|
|
menu.menu_finish_pickup.status = 2;
|
|
menu.menu_finish_pickup.photo = drvUp.img;
|
|
} else if (drvUp.stts === OrdersDriversUploadsModels.PHOTO_STATUS_TRAVEL_DOCUMENT) {
|
|
menu.menu_travel_document.status = 2;
|
|
menu.menu_travel_document.photo = drvUp.img;
|
|
} else if (drvUp.stts === OrdersDriversUploadsModels.PHOTO_STATUS_OTW_DROP) {
|
|
// if (row.drv_app_lock_menu_otw_drop_at !== 0) { menu.menu_otw_drop.status = 2; } else { menu.menu_otw_drop.status = 1; }
|
|
menu.menu_otw_drop.status = 2;
|
|
menu.menu_otw_drop.photo.push(drvUp.img);
|
|
} else if (drvUp.stts === OrdersDriversUploadsModels.PHOTO_STATUS_ARRIVED_DROP) {
|
|
menu.menu_arrived_drop.status = 2;
|
|
menu.menu_arrived_drop.photo = drvUp.img;
|
|
} else if (drvUp.stts === OrdersDriversUploadsModels.PHOTO_STATUS_PROCESS_DROP) {
|
|
menu.menu_process_drop.status = 2;
|
|
menu.menu_process_drop.photo = drvUp.img;
|
|
} else if (drvUp.stts === OrdersDriversUploadsModels.PHOTO_STATUS_FINISH_DROP) {
|
|
menu.menu_finish_drop.status = 2;
|
|
menu.menu_finish_drop.photo = drvUp.img;
|
|
} else if (drvUp.stts === OrdersDriversUploadsModels.PHOTO_STATUS_HANDOVER_DOCUMENT) {
|
|
menu.menu_handover_document.status = 2;
|
|
menu.menu_handover_document.photo = drvUp.img;
|
|
} else if (drvUp.stts === OrdersDriversUploadsModels.PHOTO_STATUS_ACCIDENT) {
|
|
menu.menu_accident.status = 1;
|
|
menu.menu_accident.photo.push(drvUp.img);
|
|
}
|
|
}
|
|
|
|
const formattedActiveOrders = [], includedPckId = [], includedDropId = [];
|
|
for (const row of activeOrders) {
|
|
if (includedPckId.includes(row.ord_pck_id) || includedDropId.includes(row.ord_drop_id)) continue;
|
|
includedPckId.push(row.ord_pck_id);
|
|
includedDropId.push(row.ord_drop_id);
|
|
|
|
const detail_id = Buffer.from(`${row.ord_id}_${row.ord_pck_id}_${row.ord_drop_id}_${row.ord_pck_drop_id}`, 'ascii').toString('hex');
|
|
// const decoded_detail_id = Buffer.from('34365f34305f3339', 'hex').toString('ascii');
|
|
|
|
let status_desc = '';
|
|
let is_wait_aprv_otw_drop = 0; // 0=>disable, 1=>enable
|
|
let is_wait_aprv_otw_drop_desc = '';
|
|
|
|
// old way
|
|
// if (row.stts_delivery === OrdersPckDropsModels.STTS_DELIVERY_OTW_PICKUP) { status_desc = 'Kendaraan Menuju Lokasi Jemput'; menu.menu_arrived_pickup.status = 1; }
|
|
// else if (row.stts_delivery === OrdersPckDropsModels.STTS_DELIVERY_ARRIVED_PICKUP) { status_desc = 'Kendaraan Tiba dilokasi Jemput'; menu.menu_process_pickup.status = 1; }
|
|
// else if (row.stts_delivery === OrdersPckDropsModels.STTS_DELIVERY_PROCESS_PICKUP) { status_desc = 'Kendaraan Memuat Barang'; menu.menu_finish_pickup.status = 1; }
|
|
// else if (row.stts_delivery === OrdersPckDropsModels.STTS_DELIVERY_FINISH_PICKUP) {
|
|
// status_desc = 'Kendaraan Selesai Memuat Barang';
|
|
// if (menu.menu_travel_document.status === 2) { menu.menu_otw_drop.status = 1; } else { menu.menu_travel_document.status = 1; }
|
|
// }
|
|
// else if (row.stts_delivery === OrdersPckDropsModels.STTS_DELIVERY_OTW_DROP) {
|
|
// status_desc = 'Kendaraan Menuju Lokasi Pengantaran';
|
|
// if (row.drv_app_lock_menu_otw_drop_at !== 0) { menu.menu_arrived_drop.status = 1; } else { menu.menu_otw_drop.status = 1; }
|
|
// }
|
|
// else if (row.stts_delivery === OrdersPckDropsModels.STTS_DELIVERY_ARRIVED_DROP) { status_desc = 'Kendaraan Sampai Dilokasi Pengantaran'; menu.menu_process_drop.status = 1; }
|
|
// else if (row.stts_delivery === OrdersPckDropsModels.STTS_DELIVERY_PROCESS_DROP) { status_desc = 'Kendaraan Membongkar Barang'; menu.menu_finish_drop.status = 1; }
|
|
// else if (row.stts_delivery === OrdersPckDropsModels.STTS_DELIVERY_FINISH_DROP) {
|
|
// status_desc = 'Kendaraan Selesai Membongkar Barang';
|
|
// if (menu.menu_handover_document.status === 2) { } else { menu.menu_handover_document.status = 1; }
|
|
// }
|
|
// new way
|
|
if (row.stts_delivery === OrdersPckDropsModels.STTS_DELIVERY_OTW_PICKUP) { status_desc = 'Kendaraan Menuju Lokasi Jemput'; menu.menu_arrived_pickup.status = 1; }
|
|
else if (row.stts_delivery === OrdersPckDropsModels.STTS_DELIVERY_ARRIVED_PICKUP) { status_desc = 'Kendaraan Tiba dilokasi Jemput'; menu.menu_process_pickup.status = 1; }
|
|
else if (row.stts_delivery === OrdersPckDropsModels.STTS_DELIVERY_PROCESS_PICKUP) { status_desc = 'Kendaraan Memuat Barang'; menu.menu_finish_pickup.status = 1; }
|
|
else if (row.stts_delivery === OrdersPckDropsModels.STTS_DELIVERY_FINISH_PICKUP) { status_desc = 'Kendaraan Selesai Memuat Barang'; menu.menu_travel_document.status = 1; }
|
|
else if (row.stts_delivery === OrdersPckDropsModels.STTS_DELIVERY_TRAVEL_DOC) {
|
|
status_desc = 'Driver Sudah Mengupload Dokumen Perjalanan';
|
|
if (row.is_aprv_pck == OrdersPckDropsModels.IS_APRV_YES) {
|
|
menu.menu_otw_drop.status = 1;
|
|
is_wait_aprv_otw_drop = 1;
|
|
is_wait_aprv_otw_drop_desc = 'Menunggu persetujuan dari checker';
|
|
} else {
|
|
menu.menu_otw_drop.status = 0; // disable sementara, seharusnya 0
|
|
}
|
|
}
|
|
else if (row.stts_delivery === OrdersPckDropsModels.STTS_DELIVERY_OTW_DROP) {
|
|
status_desc = 'Kendaraan Menuju Lokasi Pengantaran';
|
|
if (row.drv_app_lock_menu_otw_drop_at !== 0) { menu.menu_arrived_drop.status = 1; } else { menu.menu_otw_drop.status = 1; }
|
|
}
|
|
else if (row.stts_delivery === OrdersPckDropsModels.STTS_DELIVERY_ARRIVED_DROP) { status_desc = 'Kendaraan Sampai Dilokasi Pengantaran'; menu.menu_process_drop.status = 1; }
|
|
else if (row.stts_delivery === OrdersPckDropsModels.STTS_DELIVERY_PROCESS_DROP) { status_desc = 'Kendaraan Membongkar Barang'; menu.menu_finish_drop.status = 1; }
|
|
else if (row.stts_delivery === OrdersPckDropsModels.STTS_DELIVERY_FINISH_DROP) { status_desc = 'Kendaraan Selesai Membongkar Barang'; menu.menu_handover_document.status = 1; }
|
|
else if (row.stts_delivery === OrdersPckDropsModels.STTS_DELIVERY_HANDOVER_DOC) { status_desc = 'Driver Sudah Mengupload Dokumen Serah Terima'; }
|
|
|
|
// validate is_going / ongoing by pickup date
|
|
let is_ongoing = false;
|
|
if (row.set_pck_at) {
|
|
let cur_date = moment.unix(now).set({hour:0,minute:0,second:0,millisecond:0}); // as start
|
|
let pck_date = moment.unix(row.set_pck_at).set({hour:0,minute:0,second:0,millisecond:0}); // as end
|
|
let duration = moment.duration(pck_date.diff(cur_date));
|
|
if (duration.asDays() <= 0) {
|
|
is_ongoing = true;
|
|
}
|
|
}
|
|
|
|
formattedActiveOrders.push({
|
|
detail_id,
|
|
// ord_pck_drop_id: row.ord_pck_drop_id,
|
|
ord_id: row.ord_id,
|
|
ord_code: row.ord_code,
|
|
// pck_total: row.pck_total,
|
|
// drop_total: row.drop_total,
|
|
is_ongoing,
|
|
pck: {
|
|
id: row.ord_pck_id,
|
|
set_at_unix: row.set_pck_at,
|
|
// set_at_raw: (row.set_pck_at != 0) ? moment.unix(row.set_pck_at).utc().format('YYYY-MM-DDTHH:mm:ss.SSS') + 'Z' : '', // utc
|
|
set_at_raw: (row.set_pck_at != 0) ? moment.unix(row.set_pck_at).format('YYYY-MM-DDTHH:mm:ss.SSS') + 'Z' : '', // gmt +7
|
|
// stts: row.stts_pck,
|
|
name: row.pck_name,
|
|
addr: row.pck_addr,
|
|
pic_name: row.pck_pic_name,
|
|
pic_phone: row.pck_pic_phone_code + '' + row.pck_pic_phone_val,
|
|
pic_mail: row.pck_pic_mail || '',
|
|
client_name: row.c_name,
|
|
client_phone: row.c_phone_code + '' + row.c_phone_val,
|
|
client_mail: row.c_mail,
|
|
client_prefer_truck_type: row.prefer_truck_type_name || '',
|
|
},
|
|
// going_at_unix: row.going_at,
|
|
// going_at_raw: (row.going_at != 0) ? moment.unix(row.going_at).utc().format('YYYY-MM-DDTHH:mm:ss.SSS') + 'Z' : '',
|
|
// going_note: row.going_note,
|
|
drop: {
|
|
id: row.ord_drop_id,
|
|
// stts: row.ord_drop_stts,
|
|
name: row.drop_name,
|
|
addr: row.drop_addr,
|
|
pic_name: row.drop_pic_name,
|
|
pic_phone: row.drop_pic_phone_code + '' + row.drop_pic_phone_val,
|
|
pic_mail: row.drop_pic_mail || '',
|
|
client_name: row.c_name,
|
|
client_phone: row.c_phone_code + '' + row.c_phone_val,
|
|
client_mail: row.c_mail,
|
|
client_prefer_truck_type: row.prefer_truck_type_name || '',
|
|
},
|
|
// arrived_at_unix: row.arrived_at,
|
|
// arrived_at_raw: (row.arrived_at != 0) ? moment.unix(row.arrived_at).utc().format('YYYY-MM-DDTHH:mm:ss.SSS') + 'Z' : '',
|
|
// arrived_note: row.arrived_note,
|
|
lead_time: row.lead_time,
|
|
lead_time_unit: row.lead_time_unit,
|
|
// buy_price: row.buy_price,
|
|
status: row.stts_delivery,
|
|
status_desc,
|
|
is_wait_aprv_otw_drop,
|
|
is_wait_aprv_otw_drop_desc,
|
|
// c_name: row.c_name,
|
|
// c_phone: row.c_phone_code + '' + row.c_phone_val,
|
|
// c_mail: row.c_mail,
|
|
// prefer_truck_type: row.prefer_truck_type,
|
|
// prefer_truck_type_name: row.prefer_truck_type_name || '',
|
|
vdr: {
|
|
name: row.vdr_name,
|
|
phone: row.vdr_phone_code + '' + row.vdr_phone_val,
|
|
mail: row.vdr_mail,
|
|
addr: row.vdr_addr,
|
|
},
|
|
drv: {
|
|
name: row.drv_name,
|
|
kenek_name: row.drv_name2,
|
|
phone: row.drv_phone_code + '' + row.drv_phone_val,
|
|
kenek_phone: row.drv_phone2_code + '' + row.drv_phone2_val,
|
|
mail: row.drv_mail,
|
|
addr: row.drv_addr,
|
|
},
|
|
vhc: {
|
|
name_bukan_nopol: row.vhc_name,
|
|
nopol1: row.vhc_nopol1,
|
|
nopol2: row.vhc_nopol2,
|
|
nopol3: row.vhc_nopol3,
|
|
nopol_full: row.vhc_nopol1 + ' ' + row.vhc_nopol2 + ' ' + row.vhc_nopol3,
|
|
},
|
|
menu,
|
|
});
|
|
}
|
|
|
|
apiRes = JSON.parse(JSON.stringify(response[200]));
|
|
apiRes.data = formattedActiveOrders[0];
|
|
// apiRes.raw = activeOrders;
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
} catch (e) {
|
|
apiRes = JSON.parse(JSON.stringify(response[500]));
|
|
apiRes.meta.message += Helper.setErrMsg(': ' + e.message);
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(500).json(apiRes);
|
|
}
|
|
}
|
|
|
|
async jobPhotoTransitions(req, res) {
|
|
let apiRes = {}
|
|
try {
|
|
const now = moment().unix();
|
|
|
|
const { did, device_id, phone } = req.auth;
|
|
const { detail_id, type_up_photo, photo, lat, lng, photo_at } = req.body;
|
|
// input validation
|
|
const input = {
|
|
detail_id,
|
|
type_up_photo,
|
|
photo,
|
|
lat,
|
|
lng,
|
|
photo_at,
|
|
};
|
|
const rulesInput = {
|
|
detail_id: 'required|string',
|
|
type_up_photo: 'required|numeric|max:12',
|
|
photo: 'required|string',
|
|
lat: 'required|string|max:125',
|
|
lng: 'required|string|max:125',
|
|
photo_at: 'required|numeric',
|
|
};
|
|
const isInputValid = new Validator(input, rulesInput);
|
|
if (isInputValid.fails()) {
|
|
apiRes = JSON.parse(JSON.stringify(response[422]));
|
|
apiRes.meta.message += Helper.setErrMsg(': ' + Object.values(isInputValid.errors.all())[0][0]); // get first message
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
|
|
const decoded_detail_id = Buffer.from(detail_id, 'hex').toString('ascii');
|
|
const split_detail_id = decoded_detail_id.split('_');
|
|
if (split_detail_id.length !== 4) {
|
|
apiRes = JSON.parse(JSON.stringify(response[422]));
|
|
apiRes.meta.code += '_1';
|
|
apiRes.meta.message = 'detail id not valid';
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
const [ ord_id, pck_id, drop_id, ord_pck_drop_id ] = split_detail_id;
|
|
|
|
const required_type_up_photo = [OrdersDriversUploadsModels.PHOTO_STATUS_OTW_PICKUP,OrdersDriversUploadsModels.PHOTO_STATUS_ARRIVED_PICKUP,OrdersDriversUploadsModels.PHOTO_STATUS_PROCESS_PICKUP,OrdersDriversUploadsModels.PHOTO_STATUS_FINISH_PICKUP,OrdersDriversUploadsModels.PHOTO_STATUS_TRAVEL_DOCUMENT,OrdersDriversUploadsModels.PHOTO_STATUS_OTW_DROP,OrdersDriversUploadsModels.PHOTO_STATUS_ARRIVED_DROP,OrdersDriversUploadsModels.PHOTO_STATUS_PROCESS_DROP,OrdersDriversUploadsModels.PHOTO_STATUS_FINISH_DROP,OrdersDriversUploadsModels.PHOTO_STATUS_HANDOVER_DOCUMENT,OrdersDriversUploadsModels.PHOTO_STATUS_ACCIDENT];
|
|
if (!required_type_up_photo.includes(type_up_photo)) {
|
|
apiRes = JSON.parse(JSON.stringify(response[422]));
|
|
apiRes.meta.code += '_2';
|
|
apiRes.meta.message = 'type up photo not valid';
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
|
|
const filter = {
|
|
ord_id,
|
|
pck_id,
|
|
drop_id,
|
|
ord_pck_drop_id,
|
|
// is_active: OrdersModels.IS_ACTIVE,
|
|
// order_status: [OrdersModels.STTS_HAVE_GET_VHC,OrdersModels.STTS_PCK,OrdersModels.STTS_GO,OrdersModels.STTS_ARV,OrdersModels.STTS_DROP],
|
|
get_prefer_type_truck: 1,
|
|
couple_pck_drop: 1,
|
|
get_pic_zone: 1,
|
|
did,
|
|
};
|
|
const activeOrders = await OrdersModels.listOrders(filter);
|
|
if (activeOrders.length < 1) {
|
|
apiRes = JSON.parse(JSON.stringify(response[404]));
|
|
apiRes.meta.code += '_4';
|
|
apiRes.meta.message = 'job not found';
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
|
|
// validate inside zone
|
|
const check_pck_zone = [OrdersDriversUploadsModels.PHOTO_STATUS_ARRIVED_PICKUP,OrdersDriversUploadsModels.PHOTO_STATUS_PROCESS_PICKUP,OrdersDriversUploadsModels.PHOTO_STATUS_FINISH_PICKUP,OrdersDriversUploadsModels.PHOTO_STATUS_TRAVEL_DOCUMENT];
|
|
const check_drop_zone = [OrdersDriversUploadsModels.PHOTO_STATUS_ARRIVED_DROP,OrdersDriversUploadsModels.PHOTO_STATUS_PROCESS_DROP,OrdersDriversUploadsModels.PHOTO_STATUS_FINISH_DROP,OrdersDriversUploadsModels.PHOTO_STATUS_HANDOVER_DOCUMENT];
|
|
if (check_pck_zone.includes(type_up_photo)) {
|
|
const inCircle = await ZoneModels.getOrdInCircle(lat, lng, { zid: activeOrders[0].pck_id });
|
|
const inShape = await ZoneModels.getOrdInShape(lat, lng, { zid: activeOrders[0].pck_id });
|
|
if (inCircle.length < 1 && inShape.length < 1) {
|
|
apiRes = JSON.parse(JSON.stringify(response[400]));
|
|
apiRes.meta.code += '_2';
|
|
apiRes.meta.message = 'driver should inside pickup zone';
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
}
|
|
// else if (check_drop_zone.includes(type_up_photo)) {
|
|
// const inCircle = await ZoneModels.getOrdInCircle(lat, lng, { zid: activeOrders[0].drop_id });
|
|
// const inShape = await ZoneModels.getOrdInShape(lat, lng, { zid: activeOrders[0].drop_id });
|
|
// if (inCircle.length < 1 && inShape.length < 1) {
|
|
// apiRes = JSON.parse(JSON.stringify(response[400]));
|
|
// apiRes.meta.code += '_3';
|
|
// apiRes.meta.message = 'driver should inside drop zone';
|
|
LibLogReqResApi.log(req, apiRes);
|
|
// return res.status(200).json(apiRes);
|
|
// }
|
|
// }
|
|
|
|
// status transitions
|
|
const insUploads = [];
|
|
const updtOrd = {}, updtPck = {}, updtDrop = {}, updtPckDrop = {};
|
|
if (type_up_photo == OrdersDriversUploadsModels.PHOTO_STATUS_ARRIVED_PICKUP) {
|
|
// t_orders
|
|
updtOrd.id = ord_id;
|
|
updtOrd.status = OrdersModels.STTS_PCK;
|
|
// t_orders_pickups
|
|
updtPck.id = pck_id;
|
|
updtPck.stts_pck = OrdersPickupsModels.STTS_PCK_WAIT;
|
|
// updtPck.pck_enter_at = now;
|
|
// t_orders_pck_drops
|
|
updtPckDrop.id = ord_pck_drop_id;
|
|
updtPckDrop.stts = OrdersPckDropsModels.STTS_DELIVERY_ARRIVED_PICKUP;
|
|
} else if (type_up_photo == OrdersDriversUploadsModels.PHOTO_STATUS_PROCESS_PICKUP) {
|
|
// t_orders
|
|
updtOrd.id = ord_id;
|
|
updtOrd.status = OrdersModels.STTS_PCK;
|
|
// t_orders_pickups
|
|
updtPck.id = pck_id;
|
|
updtPck.stts_pck = OrdersPickupsModels.STTS_PCK_PICKING;
|
|
updtPck.pck_at = now;
|
|
// t_orders_pck_drops
|
|
updtPckDrop.id = ord_pck_drop_id;
|
|
updtPckDrop.stts = OrdersPckDropsModels.STTS_DELIVERY_PROCESS_PICKUP;
|
|
} else if (type_up_photo == OrdersDriversUploadsModels.PHOTO_STATUS_FINISH_PICKUP) {
|
|
// t_orders
|
|
updtOrd.id = ord_id;
|
|
updtOrd.status = OrdersModels.STTS_GO;
|
|
updtOrd.going_at = now;
|
|
// t_orders_pickups
|
|
updtPck.id = pck_id;
|
|
updtPck.stts_pck = OrdersPickupsModels.STTS_PCK_PICKED;
|
|
// t_orders_pck_drops
|
|
updtPckDrop.id = ord_pck_drop_id;
|
|
updtPckDrop.stts = OrdersPckDropsModels.STTS_DELIVERY_FINISH_PICKUP;
|
|
} else if (type_up_photo == OrdersDriversUploadsModels.PHOTO_STATUS_TRAVEL_DOCUMENT) {
|
|
// t_orders
|
|
updtOrd.id = ord_id;
|
|
updtOrd.status = OrdersModels.STTS_GO;
|
|
// t_orders_pickups
|
|
updtPck.id = pck_id;
|
|
updtPck.stts_pck = OrdersPickupsModels.STTS_PCK_PICKED;
|
|
// updtPck.pck_leave_at = now;
|
|
// t_orders_pck_drops
|
|
updtPckDrop.id = ord_pck_drop_id;
|
|
updtPckDrop.stts = OrdersPckDropsModels.STTS_DELIVERY_TRAVEL_DOC;
|
|
} else if (type_up_photo == OrdersDriversUploadsModels.PHOTO_STATUS_OTW_DROP) {
|
|
// t_orders
|
|
updtOrd.id = ord_id;
|
|
updtOrd.status = OrdersModels.STTS_GO;
|
|
// t_orders_pickups
|
|
updtPck.id = pck_id;
|
|
updtPck.stts_pck = OrdersPickupsModels.STTS_PCK_PICKED;
|
|
// t_orders_drops
|
|
updtDrop.id = drop_id;
|
|
updtDrop.stts_drop = OrdersDropsModels.STTS_DROP_WAIT;
|
|
// t_orders_pck_drops
|
|
updtPckDrop.id = ord_pck_drop_id;
|
|
updtPckDrop.stts = OrdersPckDropsModels.STTS_DELIVERY_OTW_DROP;
|
|
} else if (type_up_photo == OrdersDriversUploadsModels.PHOTO_STATUS_ARRIVED_DROP) {
|
|
// t_orders
|
|
updtOrd.id = ord_id;
|
|
updtOrd.status = OrdersModels.STTS_ARV;
|
|
updtOrd.arrived_at = now;
|
|
// t_orders_drops
|
|
updtDrop.id = drop_id;
|
|
updtDrop.stts_drop = OrdersDropsModels.STTS_DROP_WAIT;
|
|
// updtDrop.drop_enter_at = now;
|
|
// t_orders_pck_drops
|
|
updtPckDrop.id = ord_pck_drop_id;
|
|
updtPckDrop.stts = OrdersPckDropsModels.STTS_DELIVERY_ARRIVED_DROP;
|
|
} else if (type_up_photo == OrdersDriversUploadsModels.PHOTO_STATUS_PROCESS_DROP) {
|
|
// t_orders
|
|
updtOrd.id = ord_id;
|
|
updtOrd.status = OrdersModels.STTS_ARV;
|
|
// t_orders_drops
|
|
updtDrop.id = drop_id;
|
|
updtDrop.stts_drop = OrdersDropsModels.STTS_DROP_DROPPING;
|
|
updtDrop.drop_at = now;
|
|
// t_orders_pck_drops
|
|
updtPckDrop.id = ord_pck_drop_id;
|
|
updtPckDrop.stts = OrdersPckDropsModels.STTS_DELIVERY_PROCESS_DROP;
|
|
} else if (type_up_photo == OrdersDriversUploadsModels.PHOTO_STATUS_FINISH_DROP) {
|
|
// t_orders
|
|
updtOrd.id = ord_id;
|
|
updtOrd.status = OrdersModels.STTS_DROP;
|
|
// t_orders_drops
|
|
updtDrop.id = drop_id;
|
|
updtDrop.stts_drop = OrdersDropsModels.STTS_DROP_DROPED;
|
|
// t_orders_pck_drops
|
|
updtPckDrop.id = ord_pck_drop_id;
|
|
updtPckDrop.stts = OrdersPckDropsModels.STTS_DELIVERY_FINISH_DROP;
|
|
} else if (type_up_photo == OrdersDriversUploadsModels.PHOTO_STATUS_HANDOVER_DOCUMENT) {
|
|
// t_orders
|
|
updtOrd.id = ord_id;
|
|
updtOrd.status = OrdersModels.STTS_CLIENT_PAY;
|
|
// t_orders_drops
|
|
updtDrop.id = drop_id;
|
|
updtDrop.stts_drop = OrdersDropsModels.STTS_DROP_DROPED;
|
|
// updtDrop.drop_leave_at = now;
|
|
// t_orders_pck_drops
|
|
updtPckDrop.id = ord_pck_drop_id;
|
|
updtPckDrop.stts = OrdersPckDropsModels.STTS_DELIVERY_HANDOVER_DOC;
|
|
|
|
// kalau sudah selesai drop vhc & driver bisa order lagi
|
|
let remaining_multi_drops = await OrdersPckDropsModels.listOrdPckDrop({ ord_id, not_stts: [OrdersPckDropsModels.STTS_DELIVERY_FINISH_DROP, OrdersPckDropsModels.STTS_DELIVERY_HANDOVER_DOC] });
|
|
let vehicle = await VhcModels.getVhcById(activeOrders[0].vhc_id);
|
|
let updtVhc = {};
|
|
if (vehicle[0].ord_ids) {
|
|
let vhc_in_ord_ids = JSON.parse(vehicle[0].ord_ids);
|
|
for (let key in vhc_in_ord_ids) {
|
|
if (vhc_in_ord_ids[key] == ord_id) {
|
|
if (vhc_in_ord_ids.length <= 1) {
|
|
if (remaining_multi_drops.length < 1) {
|
|
updtVhc = {
|
|
is_in_ord: VhcModels.IN_ORD_NO,
|
|
ord_id: 0,
|
|
ord_code: 0,
|
|
ord_ids: null,
|
|
};
|
|
} else {
|
|
vhc_in_ord_ids.splice(key, 1);
|
|
updtVhc['ord_ids'] = vhc_in_ord_ids;
|
|
updtVhc['ord_ids'] = JSON.stringify(updtVhc['ord_ids']);
|
|
if (vehicle[0].ord_id == ord_id) updtVhc['ord_id'] = 0;
|
|
if (vehicle[0].ord_code == activeOrders[0].ord_code) updtVhc['ord_code'] = 0;
|
|
}
|
|
} else {
|
|
vhc_in_ord_ids.splice(key, 1);
|
|
updtVhc['ord_ids'] = vhc_in_ord_ids;
|
|
updtVhc['ord_ids'] = JSON.stringify(updtVhc['ord_ids']);
|
|
if (vehicle[0].ord_id == ord_id) updtVhc['ord_id'] = 0;
|
|
if (vehicle[0].ord_code == activeOrders[0].ord_code) updtVhc['ord_code'] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// if (updtVhc) VhcModles.update(activeOrders[0].vhc_id, updtVhc);
|
|
let driver = await DriversModels.find(activeOrders[0].drv_id);
|
|
let updtDrv = {};
|
|
if (driver[0].ord_ids) {
|
|
let drv_in_ord_ids = JSON.parse(driver[0].ord_ids);
|
|
for (let key in drv_in_ord_ids) {
|
|
if (drv_in_ord_ids[key] == ord_id) {
|
|
if (drv_in_ord_ids.length <= 1) {
|
|
if (remaining_multi_drops.length < 1) {
|
|
updtDrv = {
|
|
is_in_ord: DriversModels.IN_ORD_NO,
|
|
ord_id: 0,
|
|
ord_code: 0,
|
|
ord_ids: null,
|
|
};
|
|
} else {
|
|
drv_in_ord_ids.splice(key, 1);
|
|
updtDrv['ord_ids'] = drv_in_ord_ids;
|
|
updtDrv['ord_ids'] = JSON.stringify(updtDrv['ord_ids']);
|
|
if (driver[0].ord_id == ord_id) updtDrv['ord_id'] = 0;
|
|
if (driver[0].ord_code == activeOrders[0].ord_code) updtDrv['ord_code'] = 0;
|
|
}
|
|
} else {
|
|
drv_in_ord_ids.splice(key, 1);
|
|
updtDrv['ord_ids'] = drv_in_ord_ids;
|
|
updtDrv['ord_ids'] = JSON.stringify(updtDrv['ord_ids']);
|
|
if (driver[0].ord_id == ord_id) updtDrv['ord_id'] = 0;
|
|
if (driver[0].ord_code == activeOrders[0].ord_code) updtDrv['ord_code'] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// if (updtDrv) DriversModels.update(updtDrv, activeOrders[0].drv_id);
|
|
} else if (type_up_photo == OrdersDriversUploadsModels.PHOTO_STATUS_ACCIDENT) {
|
|
// t_orders
|
|
updtOrd.id = ord_id;
|
|
// updtOrd.is_accident = OrdersModels.IS_ACCIDENT;
|
|
// updtOrd.acdnt_at = now;
|
|
// t_orders_pck_drops
|
|
updtPckDrop.id = ord_pck_drop_id;
|
|
updtPckDrop.is_accident = OrdersModels.IS_ACCIDENT;
|
|
updtPckDrop.acdnt_at = now;
|
|
}
|
|
|
|
let stts_reverse_geo = 0;
|
|
const respRGeo = await LibCurl.reverseGeo(lat, lng);
|
|
let { country_id, country_code, country_text, state_id, state_text, city_id, city_text, district_id, district_text, village_id, village_text, postcode, streets, fulladdress, log_reverse_geo } = respRGeo.addrData || {};
|
|
if (respRGeo.type === 'sc') {
|
|
stts_reverse_geo = GpsTracksModels.STTS_REVERSE_GEO_SC;
|
|
} else if (respRGeo.type === 'no_available') {
|
|
stts_reverse_geo = GpsTracksModels.STTS_REVERSE_GEO_LOST;
|
|
} else if (respRGeo.type === 'fail') {
|
|
stts_reverse_geo = GpsTracksModels.STTS_REVERSE_GEO_ER;
|
|
} else if (respRGeo.type === 'error') {
|
|
stts_reverse_geo = GpsTracksModels.STTS_REVERSE_GEO_ER;
|
|
}
|
|
|
|
// start geotagging image
|
|
const tempFileName = moment().valueOf() + '.jpeg';
|
|
const tempFileNamePath = path.resolve(__dirname, '../files/storage') + '/' + tempFileName;
|
|
await LibImgGeotagging.create(tempFileName, tempFileNamePath, photo, {fulladdress, lat, lng, photo_at});
|
|
|
|
const apiSavePhotos = process.env.FMS_URL + 'api/v1/storage/save_photos';
|
|
const namePhoto = `ords_pcks_drops/${ord_pck_drop_id}/drvs_ups/${did}/${now}.jpeg`;
|
|
const respSavePhotos = await LibCurl.formurlencoded(apiSavePhotos, {
|
|
names: [namePhoto],
|
|
photos: [fs.readFileSync(tempFileNamePath, {encoding: 'base64'})],
|
|
});
|
|
|
|
LibFile.remove(tempFileName);
|
|
if (respSavePhotos.type !== 'sc') {
|
|
apiRes = JSON.parse(JSON.stringify(response[400]));
|
|
apiRes.meta.code += '_1';
|
|
apiRes.meta.message = 'fail upload photo';
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
// end geotagging image
|
|
|
|
// get region_id
|
|
if (!village_id) {
|
|
const region = await LibCurl.getRegionId(postcode);
|
|
if (typeof region.addrData !== 'undefined') {
|
|
if (region.addrData.state_id) state_id = region.addrData.state_id;
|
|
if (region.addrData.state_text) state_text = region.addrData.state_text.toUpperCase();
|
|
if (region.addrData.city_id) city_id = region.addrData.city_id;
|
|
if (region.addrData.city_text) city_text = region.addrData.city_text.toUpperCase();
|
|
if (region.addrData.district_id) district_id = region.addrData.district_id;
|
|
if (region.addrData.district_text) district_text = region.addrData.district_text.toUpperCase();
|
|
if (region.addrData.village_id) village_id = region.addrData.village_id;
|
|
if (region.addrData.village_text) village_text = region.addrData.village_text.toUpperCase();
|
|
}
|
|
}
|
|
|
|
// t_orders_drivers_uploads
|
|
insUploads.push({
|
|
did,
|
|
ord_id,
|
|
ord_code: activeOrders[0].ord_code,
|
|
pck_id,
|
|
drop_id,
|
|
ord_pck_drop_id,
|
|
stts: type_up_photo,
|
|
is_active: OrdersDriversUploadsModels.IS_ACTIVE,
|
|
img: process.env.FMS_URL + `storage/${namePhoto}`,
|
|
// desc: undefined,
|
|
lat, lng,
|
|
country_id: country_id || null,
|
|
country_code: country_code || null,
|
|
country_text: country_text || null,
|
|
state_id: state_id || null,
|
|
state_text: state_text || null,
|
|
city_id: city_id || null,
|
|
city_text: city_text || null,
|
|
district_id: district_id || null,
|
|
district_text: district_text || null,
|
|
village_id: village_id || null,
|
|
village_text: village_text || null,
|
|
postcode: postcode || null,
|
|
streets: streets || null,
|
|
fulladdress: fulladdress || null,
|
|
stts_reverse_geo, log_reverse_geo,
|
|
crt: now, crt_drv_at: photo_at, crt_by: did,
|
|
updt: now, updt_by: did,
|
|
});
|
|
|
|
OrdersModels.bundleInsDrvUploads(insUploads, updtOrd, updtPck, updtDrop, updtPckDrop);
|
|
|
|
apiRes = JSON.parse(JSON.stringify(response[200]));
|
|
// apiRes.data = activeOrders;
|
|
// apiRes.raw = respRGeo.addrData || {};
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
} catch (e) {
|
|
apiRes = JSON.parse(JSON.stringify(response[500]));
|
|
apiRes.meta.message += Helper.setErrMsg(': ' + e.message);
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(500).json(apiRes);
|
|
}
|
|
}
|
|
|
|
async lockMenu(req, res) {
|
|
let apiRes = {}
|
|
try {
|
|
const now = moment().unix();
|
|
|
|
const { did, device_id, phone } = req.auth;
|
|
const { detail_id, type_lock_menu } = req.body;
|
|
// input validation
|
|
const input = {
|
|
detail_id,
|
|
type_lock_menu,
|
|
};
|
|
const rulesInput = {
|
|
detail_id: 'required|string',
|
|
type_lock_menu: 'required|numeric|max:12',
|
|
};
|
|
const isInputValid = new Validator(input, rulesInput);
|
|
if (isInputValid.fails()) {
|
|
apiRes = JSON.parse(JSON.stringify(response[422]));
|
|
apiRes.meta.message += Helper.setErrMsg(': ' + Object.values(isInputValid.errors.all())[0][0]); // get first message
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
|
|
const decoded_detail_id = Buffer.from(detail_id, 'hex').toString('ascii');
|
|
const split_detail_id = decoded_detail_id.split('_');
|
|
if (split_detail_id.length !== 4) {
|
|
apiRes = JSON.parse(JSON.stringify(response[422]));
|
|
apiRes.meta.code += '_1';
|
|
apiRes.meta.message = 'detail id not valid';
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
const [ ord_id, pck_id, drop_id, ord_pck_drop_id ] = split_detail_id;
|
|
|
|
const required_type_lock_menu = [OrdersDriversUploadsModels.PHOTO_STATUS_OTW_PICKUP,OrdersDriversUploadsModels.PHOTO_STATUS_ARRIVED_PICKUP,OrdersDriversUploadsModels.PHOTO_STATUS_PROCESS_PICKUP,OrdersDriversUploadsModels.PHOTO_STATUS_FINISH_PICKUP,OrdersDriversUploadsModels.PHOTO_STATUS_TRAVEL_DOCUMENT,OrdersDriversUploadsModels.PHOTO_STATUS_OTW_DROP,OrdersDriversUploadsModels.PHOTO_STATUS_ARRIVED_DROP,OrdersDriversUploadsModels.PHOTO_STATUS_PROCESS_DROP,OrdersDriversUploadsModels.PHOTO_STATUS_FINISH_DROP,OrdersDriversUploadsModels.PHOTO_STATUS_HANDOVER_DOCUMENT,OrdersDriversUploadsModels.PHOTO_STATUS_ACCIDENT];
|
|
if (!required_type_lock_menu.includes(type_lock_menu)) {
|
|
apiRes = JSON.parse(JSON.stringify(response[422]));
|
|
apiRes.meta.code += '_2';
|
|
apiRes.meta.message = 'type lock menu not valid';
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
|
|
const filter = {
|
|
ord_id,
|
|
pck_id,
|
|
drop_id,
|
|
ord_pck_drop_id,
|
|
// is_active: OrdersModels.IS_ACTIVE,
|
|
// order_status: [OrdersModels.STTS_HAVE_GET_VHC,OrdersModels.STTS_PCK,OrdersModels.STTS_GO,OrdersModels.STTS_ARV,OrdersModels.STTS_DROP],
|
|
get_prefer_type_truck: 1,
|
|
couple_pck_drop: 1,
|
|
get_pic_zone: 1,
|
|
did,
|
|
};
|
|
const activeOrders = await OrdersModels.listOrders(filter);
|
|
if (activeOrders.length < 1) {
|
|
apiRes = JSON.parse(JSON.stringify(response[404]));
|
|
apiRes.meta.code += '_4';
|
|
apiRes.meta.message = 'job not found';
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
|
|
const insUploads = [];
|
|
const updtOrd = {}, updtPck = {}, updtDrop = {}, updtPckDrop = {};
|
|
if (type_lock_menu === OrdersDriversUploadsModels.PHOTO_STATUS_OTW_DROP) {
|
|
// t_orders
|
|
updtOrd.id = ord_id;
|
|
updtOrd.status = OrdersModels.STTS_GO;
|
|
// t_orders_pickups
|
|
updtPck.id = pck_id;
|
|
updtPck.stts_pck = OrdersPickupsModels.STTS_PCK_PICKED;
|
|
// t_orders_drops
|
|
updtDrop.id = drop_id;
|
|
updtDrop.stts_drop = OrdersDropsModels.STTS_DROP_WAIT;
|
|
// t_orders_pck_drops
|
|
updtPckDrop.id = ord_pck_drop_id;
|
|
updtPckDrop.drv_app_lock_menu_otw_drop_at = now;
|
|
updtPckDrop.stts = OrdersPckDropsModels.STTS_DELIVERY_OTW_DROP;
|
|
}
|
|
|
|
OrdersModels.bundleInsDrvUploads(insUploads, updtOrd, updtPck, updtDrop, updtPckDrop);
|
|
|
|
apiRes = JSON.parse(JSON.stringify(response[200]));
|
|
// apiRes.data = activeOrders;
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
} catch (e) {
|
|
apiRes = JSON.parse(JSON.stringify(response[500]));
|
|
apiRes.meta.message += Helper.setErrMsg(': ' + e.message);
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(500).json(apiRes);
|
|
}
|
|
}
|
|
|
|
// FINANCE
|
|
async listPockets(req, res) {
|
|
let apiRes = {}
|
|
try {
|
|
const now = moment().unix();
|
|
const { did, device_id, phone } = req.auth;
|
|
|
|
// input validation
|
|
const input = {};
|
|
const rulesInput = {};
|
|
const isInputValid = new Validator(input, rulesInput);
|
|
if (isInputValid.fails()) {
|
|
apiRes = JSON.parse(JSON.stringify(response[422]));
|
|
apiRes.meta.message += Helper.setErrMsg(': ' + Object.values(isInputValid.errors.all())[0][0]); // get first message
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
|
|
const checkpoints = await OrdersCheckpointsModels.list({
|
|
did,
|
|
is_paid: OrdersCheckpointsModels.IS_PAID_OFF,
|
|
order_by: ' ORDER BY checkpoint.pocket_paid_at ASC',
|
|
});
|
|
if (checkpoints.length < 1) {
|
|
apiRes = JSON.parse(JSON.stringify(response[404]));
|
|
apiRes.meta.code += '_1';
|
|
apiRes.meta.message = 'there are no received pocket money';
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
|
|
const formattedCheckpoints = [];
|
|
for (const checkpoint of checkpoints) {
|
|
formattedCheckpoints.push({
|
|
checkpoint_id: checkpoint.checkpoint_id,
|
|
ord_id: checkpoint.ord_id,
|
|
ord_code: checkpoint.ord_code,
|
|
ord_pocket_id: checkpoint.ord_pocket_id,
|
|
// pocket_sort: checkpoint.pocket_sort,
|
|
pocket_total: checkpoint.pocket_total,
|
|
pocket_is_paid: checkpoint.pocket_is_paid,
|
|
pocket_paid_at: checkpoint.pocket_paid_at,
|
|
pocket_paid_at_raw: (checkpoint.pocket_paid_at != 0) ? moment.unix(checkpoint.pocket_paid_at).utc().format('YYYY-MM-DDTHH:mm:ss.SSS') + 'Z' : '',
|
|
// pocket_paid_by: checkpoint.pocket_paid_by,
|
|
pocket_paid_by_name: checkpoint.pocket_paid_by_name || '',
|
|
});
|
|
}
|
|
|
|
apiRes = JSON.parse(JSON.stringify(response[200]));
|
|
apiRes.data = formattedCheckpoints;
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
} catch (e) {
|
|
apiRes = JSON.parse(JSON.stringify(response[500]));
|
|
apiRes.meta.message += Helper.setErrMsg(': ' + e.message);
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(500).json(apiRes);
|
|
}
|
|
}
|
|
|
|
async detailPocket(req, res) {
|
|
let apiRes = {}
|
|
try {
|
|
const now = moment().unix();
|
|
const { did, device_id, phone } = req.auth;
|
|
const { checkpoint_id } = req.params;
|
|
|
|
// input validation
|
|
const input = {
|
|
checkpoint_id,
|
|
};
|
|
const rulesInput = {
|
|
'checkpoint_id': 'required|integer',
|
|
};
|
|
const isInputValid = new Validator(input, rulesInput);
|
|
if (isInputValid.fails()) {
|
|
apiRes = JSON.parse(JSON.stringify(response[422]));
|
|
apiRes.meta.message += Helper.setErrMsg(': ' + Object.values(isInputValid.errors.all())[0][0]); // get first message
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
|
|
const checkpoints = await OrdersCheckpointsModels.list({
|
|
did,
|
|
checkpoint_id,
|
|
limit: 1,
|
|
});
|
|
if (checkpoints.length < 1) {
|
|
apiRes = JSON.parse(JSON.stringify(response[404]));
|
|
apiRes.meta.code += '_1';
|
|
apiRes.meta.message = 'pocket money not found';
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
|
|
const formattedCheckpoints = [];
|
|
for (const checkpoint of checkpoints) {
|
|
formattedCheckpoints.push({
|
|
checkpoint_id: checkpoint.checkpoint_id,
|
|
ord_id: checkpoint.ord_id,
|
|
ord_code: checkpoint.ord_code,
|
|
ord_pocket_id: checkpoint.ord_pocket_id,
|
|
// pocket_sort: checkpoint.pocket_sort,
|
|
pocket_total: checkpoint.pocket_total,
|
|
pocket_is_paid: checkpoint.pocket_is_paid,
|
|
pocket_paid_at: checkpoint.pocket_paid_at,
|
|
pocket_paid_at_raw: (checkpoint.pocket_paid_at != 0) ? moment.unix(checkpoint.pocket_paid_at).utc().format('YYYY-MM-DDTHH:mm:ss.SSS') + 'Z' : '',
|
|
// pocket_paid_by: checkpoint.pocket_paid_by,
|
|
pocket_paid_by_name: checkpoint.pocket_paid_by_name || '',
|
|
});
|
|
}
|
|
|
|
apiRes = JSON.parse(JSON.stringify(response[200]));
|
|
apiRes.data = formattedCheckpoints[0];
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
} catch (e) {
|
|
apiRes = JSON.parse(JSON.stringify(response[500]));
|
|
apiRes.meta.message += Helper.setErrMsg(': ' + e.message);
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(500).json(apiRes);
|
|
}
|
|
}
|
|
|
|
// LOGBOOK
|
|
async listLogBooks(req, res) {
|
|
let apiRes = {}
|
|
try {
|
|
const now = moment().unix();
|
|
|
|
const { did, device_id, phone } = req.auth;
|
|
|
|
const filter = {
|
|
is_active: LogbookKeysModels.IS_ACTIVE,
|
|
};
|
|
const listKeys = await LogbookKeysModels.list(filter);
|
|
if (listKeys.length < 1) {
|
|
apiRes = JSON.parse(JSON.stringify(response[404]));
|
|
apiRes.meta.code = '200'; // += '_1';
|
|
apiRes.meta.message = 'there are no list logbook';
|
|
apiRes.data = [];
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
|
|
const formattedListKeys = [], includedLogbookId = [];
|
|
for (const row of listKeys) {
|
|
if (includedLogbookId.includes(row.lgb_id)) continue;
|
|
includedLogbookId.push(row.lgb_id);
|
|
|
|
// https://stackoverflow.com/questions/23299950/convert-date-to-utc-using-moment-js
|
|
formattedListKeys.push({
|
|
lgb_id: row.lgb_id,
|
|
lgb_name: row.name,
|
|
updt_at: row.updt,
|
|
updt_at_raw: (row.updt != 0) ? moment.unix(row.updt).utc().format('YYYY-MM-DDTHH:mm:ss.SSS') + 'Z' : '',
|
|
});
|
|
}
|
|
|
|
apiRes = JSON.parse(JSON.stringify(response[200]));
|
|
apiRes.data = formattedListKeys;
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
} catch (e) {
|
|
apiRes = JSON.parse(JSON.stringify(response[500]));
|
|
apiRes.meta.message += Helper.setErrMsg(': ' + e.message);
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(500).json(apiRes);
|
|
}
|
|
}
|
|
|
|
async detailLogBook(req, res) {
|
|
let apiRes = {}
|
|
try {
|
|
const now = moment().unix();
|
|
|
|
const { did, device_id, phone } = req.auth;
|
|
const { lgb_id } = req.params;
|
|
|
|
// input validation
|
|
const input = {
|
|
lgb_id,
|
|
};
|
|
const rulesInput = {
|
|
'lgb_id': 'required|integer',
|
|
};
|
|
const isInputValid = new Validator(input, rulesInput);
|
|
if (isInputValid.fails()) {
|
|
apiRes = JSON.parse(JSON.stringify(response[422]));
|
|
apiRes.meta.message += Helper.setErrMsg(': ' + Object.values(isInputValid.errors.all())[0][0]); // get first message
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
|
|
const filter = {
|
|
lgb_id,
|
|
is_active: LogbookKeysModels.IS_ACTIVE,
|
|
limit: 1,
|
|
};
|
|
const listKeys = await LogbookKeysModels.list(filter);
|
|
if (listKeys.length < 1) {
|
|
apiRes = JSON.parse(JSON.stringify(response[404]));
|
|
apiRes.meta.code += '_4';
|
|
apiRes.meta.message = 'logbook not found';
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
|
|
const formattedListKeys = [], includedLogbookId = [];
|
|
for (const row of listKeys) {
|
|
if (includedLogbookId.includes(row.lgb_id)) continue;
|
|
includedLogbookId.push(row.lgb_id);
|
|
|
|
const params = [];
|
|
row.keys = JSON.parse(row.keys);
|
|
row.units = JSON.parse(row.units);
|
|
row.dtypes = JSON.parse(row.dtypes);
|
|
for (let i in row.keys) {
|
|
params.push({
|
|
key: row.keys[i],
|
|
unit: row.units[i],
|
|
dtype: row.dtypes[i],
|
|
value: "",
|
|
})
|
|
}
|
|
|
|
// https://stackoverflow.com/questions/23299950/convert-date-to-utc-using-moment-js
|
|
formattedListKeys.push({
|
|
lgb_id: row.lgb_id,
|
|
lgb_name: row.name,
|
|
updt_at: row.updt,
|
|
updt_at_raw: (row.updt != 0) ? moment.unix(row.updt).utc().format('YYYY-MM-DDTHH:mm:ss.SSS') + 'Z' : '',
|
|
params,
|
|
});
|
|
}
|
|
|
|
apiRes = JSON.parse(JSON.stringify(response[200]));
|
|
apiRes.data = formattedListKeys[0];
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
} catch (e) {
|
|
apiRes = JSON.parse(JSON.stringify(response[500]));
|
|
apiRes.meta.message += Helper.setErrMsg(': ' + e.message);
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(500).json(apiRes);
|
|
}
|
|
}
|
|
|
|
async insOrdLogBook(req, res) {
|
|
let apiRes = {}
|
|
try {
|
|
const now = moment().unix();
|
|
|
|
const { did, device_id, phone } = req.auth;
|
|
const { lgb_id, detail_id, params } = req.body;
|
|
|
|
// input validation
|
|
const input = {
|
|
lgb_id,
|
|
detail_id,
|
|
params,
|
|
};
|
|
const rulesInput = {
|
|
'lgb_id': 'required|integer',
|
|
'detail_id': 'required|string',
|
|
'params': 'required|array',
|
|
'params.*.key': 'required|string|max:255',
|
|
'params.*.unit': 'required|string|max:255',
|
|
'params.*.dtype': 'required|string|max:255',
|
|
'params.*.value': 'required|string',
|
|
};
|
|
const isInputValid = new Validator(input, rulesInput);
|
|
if (isInputValid.fails()) {
|
|
apiRes = JSON.parse(JSON.stringify(response[422]));
|
|
apiRes.meta.message += Helper.setErrMsg(': ' + Object.values(isInputValid.errors.all())[0][0]); // get first message
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
|
|
const decoded_detail_id = Buffer.from(detail_id, 'hex').toString('ascii');
|
|
const split_detail_id = decoded_detail_id.split('_');
|
|
if (split_detail_id.length !== 4) {
|
|
apiRes = JSON.parse(JSON.stringify(response[422]));
|
|
apiRes.meta.code += '_1';
|
|
apiRes.meta.message = 'detail id not valid';
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
const [ ord_id, pck_id, drop_id, ord_pck_drop_id ] = split_detail_id;
|
|
|
|
const filter = {
|
|
ord_id,
|
|
pck_id,
|
|
drop_id,
|
|
ord_pck_drop_id,
|
|
// is_active: OrdersModels.IS_ACTIVE,
|
|
// order_status: [OrdersModels.STTS_HAVE_GET_VHC,OrdersModels.STTS_PCK,OrdersModels.STTS_GO,OrdersModels.STTS_ARV,OrdersModels.STTS_DROP],
|
|
get_prefer_type_truck: 1,
|
|
couple_pck_drop: 1,
|
|
get_pic_zone: 1,
|
|
did,
|
|
};
|
|
const activeOrders = await OrdersModels.listOrders(filter);
|
|
if (activeOrders.length < 1) {
|
|
apiRes = JSON.parse(JSON.stringify(response[404]));
|
|
apiRes.meta.code += '_4';
|
|
apiRes.meta.message = 'job not found';
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
|
|
const filter1 = {
|
|
lgb_id,
|
|
is_active: LogbookKeysModels.IS_ACTIVE,
|
|
join_type: 1,
|
|
limit: 1,
|
|
};
|
|
const listKeys = await LogbookKeysModels.list(filter1);
|
|
if (listKeys.length < 1) {
|
|
apiRes = JSON.parse(JSON.stringify(response[404]));
|
|
apiRes.meta.code += '_5';
|
|
apiRes.meta.message = 'logbook not found';
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
|
|
let dy_cols = "(COLUMN_CREATE(", photo = '';
|
|
let values = [];
|
|
for (const param of params) {
|
|
// dy_cols += "'key', '" + param.key + "', 'unit', '" + param.unit + "', 'dtype', '" + param.dtype + "', 'value', '" + param.value + "',"; // as reference only
|
|
|
|
if (param.dtype === LogbookKeysModels.IMG_BASE64) {
|
|
// start reverse geo
|
|
let stts_reverse_geo = 0;
|
|
const respRGeo = await LibCurl.reverseGeo(param.lat, param.lng);
|
|
let { country_id, country_code, country_text, state_id, state_text, city_id, city_text, district_id, district_text, village_id, village_text, postcode, streets, fulladdress, log_reverse_geo } = respRGeo.addrData || {};
|
|
if (respRGeo.type === 'sc') {
|
|
stts_reverse_geo = GpsTracksModels.STTS_REVERSE_GEO_SC;
|
|
} else if (respRGeo.type === 'no_available') {
|
|
stts_reverse_geo = GpsTracksModels.STTS_REVERSE_GEO_LOST;
|
|
} else if (respRGeo.type === 'fail') {
|
|
stts_reverse_geo = GpsTracksModels.STTS_REVERSE_GEO_ER;
|
|
} else if (respRGeo.type === 'error') {
|
|
stts_reverse_geo = GpsTracksModels.STTS_REVERSE_GEO_ER;
|
|
}
|
|
// end reverse geo
|
|
|
|
// start get region_id
|
|
// if (!village_id) {
|
|
// const region = await LibCurl.getRegionId(postcode);
|
|
// if (typeof region.addrData !== 'undefined') {
|
|
// if (region.addrData.state_id) state_id = region.addrData.state_id;
|
|
// if (region.addrData.state_text) state_text = region.addrData.state_text.toUpperCase();
|
|
// if (region.addrData.city_id) city_id = region.addrData.city_id;
|
|
// if (region.addrData.city_text) city_text = region.addrData.city_text.toUpperCase();
|
|
// if (region.addrData.district_id) district_id = region.addrData.district_id;
|
|
// if (region.addrData.district_text) district_text = region.addrData.district_text.toUpperCase();
|
|
// if (region.addrData.village_id) village_id = region.addrData.village_id;
|
|
// if (region.addrData.village_text) village_text = region.addrData.village_text.toUpperCase();
|
|
// }
|
|
// }
|
|
// // end get region_id
|
|
|
|
// start geotagging image
|
|
const tempFileName = moment().valueOf() + '.jpeg';
|
|
const tempFileNamePath = path.resolve(__dirname, '../files/storage') + '/' + tempFileName;
|
|
await LibImgGeotagging.create(tempFileName, tempFileNamePath, param.value, {fulladdress: fulladdress || '', lat: param.lat || '', lng: param.lng || '', photo_at: param.photo_at || ''});
|
|
|
|
const apiSavePhotos = process.env.FMS_URL + 'api/v1/storage/save_photos';
|
|
const namePhoto = `ords_pcks_drops/${ord_pck_drop_id}/drvs_logbooks/${did}/${now}.jpeg`;
|
|
const respSavePhotos = await LibCurl.formurlencoded(apiSavePhotos, {
|
|
names: [namePhoto],
|
|
photos: [fs.readFileSync(tempFileNamePath, {encoding: 'base64'})],
|
|
});
|
|
|
|
LibFile.remove(tempFileName);
|
|
if (respSavePhotos.type !== 'sc') {
|
|
apiRes = JSON.parse(JSON.stringify(response[400]));
|
|
apiRes.meta.code += '_1';
|
|
apiRes.meta.message = 'fail upload photo';
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
// end geotagging image
|
|
|
|
param.value = process.env.FMS_URL + `storage/${namePhoto}`;
|
|
}
|
|
|
|
// start dy_cols
|
|
dy_cols += "'" + param.key + "', '" + param.value + "',";
|
|
values.push(param.value);
|
|
// end dy_cols
|
|
}
|
|
dy_cols = dy_cols.slice(0, -1) + "))";
|
|
dy_cols = mysql.raw(dy_cols);
|
|
|
|
const insOrdLogbook = {
|
|
ord_id,
|
|
ord_code: activeOrders[0].ord_code,
|
|
lgb_key_id: lgb_id,
|
|
lgb_key_name: listKeys[0].name,
|
|
lgb_type_id: listKeys[0].type,
|
|
lgb_type_name: listKeys[0].type_name,
|
|
vhc_id: activeOrders[0].vhc_id,
|
|
drv_id: did,
|
|
is_active: LogbookOrdersModels.IS_ACTIVE,
|
|
dy_cols,
|
|
keys: listKeys[0].keys,
|
|
units: listKeys[0].units,
|
|
dtypes: listKeys[0].dtypes,
|
|
values: JSON.stringify(values),
|
|
crt: now,
|
|
crt_by: did,
|
|
updt: now,
|
|
updt_by: did,
|
|
};
|
|
await LogbookOrdersModels.ins(insOrdLogbook);
|
|
|
|
apiRes = JSON.parse(JSON.stringify(response[200]));
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
} catch (e) {
|
|
apiRes = JSON.parse(JSON.stringify(response[500]));
|
|
apiRes.meta.message += Helper.setErrMsg(': ' + e.message);
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(500).json(apiRes);
|
|
}
|
|
}
|
|
|
|
async listOrdLogBooks(req, res) {
|
|
let apiRes = {}
|
|
try {
|
|
const now = moment().unix();
|
|
|
|
const { did, device_id, phone } = req.auth;
|
|
|
|
const filter = {
|
|
is_active: LogbookOrdersModels.IS_ACTIVE,
|
|
};
|
|
const listKeys = await LogbookOrdersModels.list(filter);
|
|
if (listKeys.length < 1) {
|
|
apiRes = JSON.parse(JSON.stringify(response[404]));
|
|
apiRes.meta.code = '200'; // += '_1';
|
|
apiRes.meta.message = 'there are no list orders logbooks';
|
|
apiRes.data = [];
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
|
|
const formattedListKeys = [], includedLogbookId = [];
|
|
for (const row of listKeys) {
|
|
if (includedLogbookId.includes(row.ord_lgb_id)) continue;
|
|
includedLogbookId.push(row.ord_lgb_id);
|
|
|
|
// https://stackoverflow.com/questions/23299950/convert-date-to-utc-using-moment-js
|
|
formattedListKeys.push({
|
|
ord_lgb_id: row.ord_lgb_id,
|
|
lgb_key_id: row.lgb_key_id,
|
|
lgb_key_name: row.lgb_key_name,
|
|
lgb_type_id: row.lgb_type_id,
|
|
lgb_type_name: row.lgb_type_name,
|
|
dy_cols: (row.dy_cols_json == null) ? '' : JSON.parse(row.dy_cols_json),
|
|
keys: JSON.parse(row.keys),
|
|
units: JSON.parse(row.units),
|
|
dtypes: JSON.parse(row.dtypes),
|
|
values: JSON.parse(row.values),
|
|
crt_at: row.crt,
|
|
crt_at_raw: (row.crt != 0) ? moment.unix(row.crt).utc().format('YYYY-MM-DDTHH:mm:ss.SSS') + 'Z' : '',
|
|
updt_at: row.updt,
|
|
updt_at_raw: (row.updt != 0) ? moment.unix(row.updt).utc().format('YYYY-MM-DDTHH:mm:ss.SSS') + 'Z' : '',
|
|
});
|
|
}
|
|
|
|
apiRes = JSON.parse(JSON.stringify(response[200]));
|
|
apiRes.data = formattedListKeys;
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
} catch (e) {
|
|
apiRes = JSON.parse(JSON.stringify(response[500]));
|
|
apiRes.meta.message += Helper.setErrMsg(': ' + e.message);
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(500).json(apiRes);
|
|
}
|
|
}
|
|
|
|
async detailOrdLogBook(req, res) {
|
|
let apiRes = {}
|
|
try {
|
|
const now = moment().unix();
|
|
|
|
const { did, device_id, phone } = req.auth;
|
|
const { ord_lgb_id } = req.params;
|
|
|
|
// input validation
|
|
const input = {
|
|
ord_lgb_id,
|
|
};
|
|
const rulesInput = {
|
|
'ord_lgb_id': 'required|integer',
|
|
};
|
|
const isInputValid = new Validator(input, rulesInput);
|
|
if (isInputValid.fails()) {
|
|
apiRes = JSON.parse(JSON.stringify(response[422]));
|
|
apiRes.meta.message += Helper.setErrMsg(': ' + Object.values(isInputValid.errors.all())[0][0]); // get first message
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
|
|
const filter = {
|
|
ord_lgb_id,
|
|
is_active: LogbookOrdersModels.IS_ACTIVE,
|
|
limit: 1,
|
|
};
|
|
const listKeys = await LogbookOrdersModels.list(filter);
|
|
if (listKeys.length < 1) {
|
|
apiRes = JSON.parse(JSON.stringify(response[404]));
|
|
apiRes.meta.code += '_4';
|
|
apiRes.meta.message = 'order logbook not found';
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
|
|
const formattedListKeys = [], includedLogbookId = [];
|
|
for (const row of listKeys) {
|
|
if (includedLogbookId.includes(row.ord_lgb_id)) continue;
|
|
includedLogbookId.push(row.ord_lgb_id);
|
|
|
|
// https://stackoverflow.com/questions/23299950/convert-date-to-utc-using-moment-js
|
|
formattedListKeys.push({
|
|
ord_lgb_id: row.ord_lgb_id,
|
|
lgb_key_id: row.lgb_key_id,
|
|
lgb_key_name: row.lgb_key_name,
|
|
lgb_type_id: row.lgb_type_id,
|
|
lgb_type_name: row.lgb_type_name,
|
|
dy_cols: (row.dy_cols_json == null) ? '' : JSON.parse(row.dy_cols_json),
|
|
keys: JSON.parse(row.keys),
|
|
units: JSON.parse(row.units),
|
|
dtypes: JSON.parse(row.dtypes),
|
|
values: JSON.parse(row.values),
|
|
crt_at: row.crt,
|
|
crt_at_raw: (row.crt != 0) ? moment.unix(row.crt).utc().format('YYYY-MM-DDTHH:mm:ss.SSS') + 'Z' : '',
|
|
updt_at: row.updt,
|
|
updt_at_raw: (row.updt != 0) ? moment.unix(row.updt).utc().format('YYYY-MM-DDTHH:mm:ss.SSS') + 'Z' : '',
|
|
});
|
|
}
|
|
|
|
apiRes = JSON.parse(JSON.stringify(response[200]));
|
|
apiRes.data = formattedListKeys[0];
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
} catch (e) {
|
|
apiRes = JSON.parse(JSON.stringify(response[500]));
|
|
apiRes.meta.message += Helper.setErrMsg(': ' + e.message);
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(500).json(apiRes);
|
|
}
|
|
}
|
|
|
|
// RUNNING BACKGROUD
|
|
// up lat,long data per 1 minute
|
|
async upLocation(req, res) {
|
|
let apiRes = {}
|
|
try {
|
|
const now = moment().unix();
|
|
|
|
const { did, device_id, phone, phone_device_id } = req.auth;
|
|
const { lat, lng, req_at } = req.body;
|
|
|
|
// input validation
|
|
const input = {
|
|
lat,
|
|
lng,
|
|
req_at,
|
|
};
|
|
const rulesInput = {
|
|
lat: 'required|string|max:125',
|
|
lng: 'required|string|max:125',
|
|
req_at: 'required|numeric',
|
|
};
|
|
const isInputValid = new Validator(input, rulesInput);
|
|
if (isInputValid.fails()) {
|
|
apiRes = JSON.parse(JSON.stringify(response[422]));
|
|
apiRes.meta.message += Helper.setErrMsg(': ' + Object.values(isInputValid.errors.all())[0][0]); // get first message
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
|
|
const filter = {
|
|
did,
|
|
// order_status: [OrdersModels.STTS_HAVE_GET_VHC,OrdersModels.STTS_PCK,OrdersModels.STTS_GO,OrdersModels.STTS_ARV,OrdersModels.STTS_DROP],
|
|
is_active: OrdersModels.IS_ACTIVE,
|
|
delivery_statuses: [
|
|
OrdersPckDropsModels.STTS_DELIVERY_OTW_PICKUP,OrdersPckDropsModels.STTS_DELIVERY_ARRIVED_PICKUP,OrdersPckDropsModels.STTS_DELIVERY_PROCESS_PICKUP
|
|
,OrdersPckDropsModels.STTS_DELIVERY_FINISH_PICKUP,OrdersPckDropsModels.STTS_DELIVERY_TRAVEL_DOC,OrdersPckDropsModels.STTS_DELIVERY_OTW_DROP
|
|
,OrdersPckDropsModels.STTS_DELIVERY_ARRIVED_DROP,OrdersPckDropsModels.STTS_DELIVERY_PROCESS_DROP,OrdersPckDropsModels.STTS_DELIVERY_FINISH_DROP
|
|
// ,OrdersPckDropsModels.STTS_DELIVERY_HANDOVER_DOC
|
|
],
|
|
couple_pck_drop: 1,
|
|
};
|
|
// kalo mau track yang nonactive, gausah ngeget vhc, lansung insert aja dengan vhc_id: 0
|
|
// const updtToOrders = await OrdersModels.listActiveOrdVhc(filter);
|
|
const updtToOrders = await OrdersModels.listOrders(filter);
|
|
|
|
/**
|
|
* get lat, lng to all checkpoints paid = 0, sort != 1, order.dlt is null,
|
|
* kenakan ke checkpoints yang order stts_deliverynya lebih dari travel dokumen
|
|
* jika ada case negative di inCircle ada dan di di inShape ada maka mana yang didahulukan ? langsung dikenain aja 2-2nya
|
|
* pastikan dulu ada di activeOrder
|
|
* kenakan yang ord_pck_id lebih awal
|
|
*/
|
|
// BISA BUAT DEBUGGING: where_not_pocket_is_paid: OrdersCheckpointsModels.IS_PAID_OFF
|
|
// BUAT PRODUCTION: pocket_is_paid: OrdersCheckpointsModels.IS_UNPAID
|
|
const inCircle = await ZoneModels.getCheckpointsInCircle(lat, lng, {drv_id: did, pocket_is_paid: OrdersCheckpointsModels.IS_UNPAID, pocket_sort: '!= 1', stts_delivery: [OrdersPckDropsModels.STTS_DELIVERY_OTW_DROP,OrdersPckDropsModels.STTS_DELIVERY_ARRIVED_DROP,OrdersPckDropsModels.STTS_DELIVERY_PROCESS_DROP,OrdersPckDropsModels.STTS_DELIVERY_FINISH_DROP,OrdersPckDropsModels.STTS_DELIVERY_HANDOVER_DOC]});
|
|
const inShape = await ZoneModels.getCheckpointsInShape(lat, lng, {drv_id: did, pocket_is_paid: OrdersCheckpointsModels.IS_UNPAID, pocket_sort: '!= 1', stts_delivery: [OrdersPckDropsModels.STTS_DELIVERY_OTW_DROP,OrdersPckDropsModels.STTS_DELIVERY_ARRIVED_DROP,OrdersPckDropsModels.STTS_DELIVERY_PROCESS_DROP,OrdersPckDropsModels.STTS_DELIVERY_FINISH_DROP,OrdersPckDropsModels.STTS_DELIVERY_HANDOVER_DOC]});
|
|
let insideZones = [];
|
|
if (inCircle.length > 0 || inShape.length > 0) {
|
|
for (const circle of inCircle) {
|
|
// hit api disbure
|
|
if (circle.drv_bank_id == 0 || circle.drv_bank_acc_number == null) continue;
|
|
insideZones.push(circle);
|
|
}
|
|
for (const shape of inShape) {
|
|
// hit api disbure
|
|
if (shape.drv_bank_id == 0 || shape.drv_bank_acc_number == null) continue;
|
|
insideZones.push(shape);
|
|
}
|
|
}
|
|
// checkpoints
|
|
if (insideZones.length > 0) {
|
|
const UNIT_TYPE_UNIT = 3;
|
|
|
|
let admins = await UsersModels.getUsersActiveByRole(UsersModels.ROLE_FINANCE);
|
|
let admins_data = [];
|
|
for (const admin of admins) {
|
|
admins_data.push({
|
|
'admin_id': admin.id,
|
|
'admin_name': admin.first_name,
|
|
'admin_phone': admin.phone_code + ' ' + admin.phone,
|
|
'admin_mail': admin.email,
|
|
'admin_addr': ''
|
|
});
|
|
}
|
|
|
|
for (const insideZone of insideZones) {
|
|
const insOrdAItems = {
|
|
'ord_id': insideZone.ord_id,
|
|
'ord_code': insideZone.ord_code,
|
|
'flow_type': OrdersAItemsModels.FLOW_TYPE_PAYMENT,
|
|
'cash_type': OrdersAItemsModels.TYPE_CASH_OUT,
|
|
'a_item_type': OrdersAItemsModels.A_TYPE_SECONDARY,
|
|
'unit_id': 0,
|
|
'unit_type': UNIT_TYPE_UNIT,
|
|
'amt_base_flat': insideZone.pocket_total,
|
|
'unit_qty': 0,
|
|
'amt_tax_type': 0,
|
|
'amt_tax_ppn_percent': 0,
|
|
'amt_tax_ppn_flat': 0,
|
|
'amt_tax_pph_percent': 0,
|
|
'amt_tax_pph_flat': 0,
|
|
'amt_total_tax_flat': 0,
|
|
'amt_result_flat': insideZone.pocket_total,
|
|
'amt_total_flat': insideZone.pocket_total,
|
|
'only_vdr': OrdersAItemsModels.ONLY_VDR_YES,
|
|
'bank_id': insideZone.drv_bank_id,
|
|
'bank_name': insideZone.drv_bank_name,
|
|
'bank_code': insideZone.drv_bank_code,
|
|
'bank_short_name': insideZone.drv_bank_short_name,
|
|
'bank_branch_name': insideZone.drv_bank_branch_name || null,
|
|
'bank_acc_name': insideZone.drv_bank_acc_name,
|
|
'bank_acc_number': insideZone.drv_bank_acc_number,
|
|
'ref_ord_id': insideZone.ord_id,
|
|
'ref_ord_code': insideZone.ord_code,
|
|
'crt': now,
|
|
'crt_by': 0,
|
|
'updt': now,
|
|
'updt_by': 0,
|
|
'desc': 'Uang Saku Driver di ' + insideZone.name,
|
|
};
|
|
|
|
insOrdAItems.calc_to_vdr = OrdersAItemsModels.CALC_TO_VDR_YES;
|
|
let termins = [];
|
|
termins = await OrdersTerminsModels.listWithFilter({
|
|
'ord_id': insideZone.ord_id,
|
|
'termin_for': OrdersTerminsModels.TERMIN_FOR_VENDOR,
|
|
'termin_is_paid': OrdersTerminsModels.IS_PAID_NO,
|
|
'in_stts_merge': [
|
|
OrdersAItemsModels.STTS_MERGE_NO,
|
|
OrdersAItemsModels.STTS_MERGE_RESULT,
|
|
],
|
|
});
|
|
insOrdAItems.v_termin_id = 0;
|
|
insOrdAItems.ref_v_termin_id = 0;
|
|
if (termins.length > 0) {
|
|
insOrdAItems.v_termin_id = termins[0].id;
|
|
insOrdAItems.ref_v_termin_id = termins[0].id;
|
|
}
|
|
if (insOrdAItems.v_termin_id === 0) {
|
|
termins = await OrdersTerminsModels.listWithFilter({
|
|
'ord_id': insideZone.ord_id,
|
|
'termin_for': OrdersTerminsModels.TERMIN_FOR_VENDOR,
|
|
'in_stts_merge': [
|
|
OrdersAItemsModels.STTS_MERGE_NO,
|
|
OrdersAItemsModels.STTS_MERGE_RESULT,
|
|
],
|
|
});
|
|
insOrdAItems.v_termin_id = termins[termins.length - 1].id;
|
|
insOrdAItems.ref_v_termin_id = termins[termins.length - 1].id;
|
|
}
|
|
|
|
const mailData = {
|
|
trx_code: insideZone.ord_code,
|
|
drv_name: insideZone.drv_name,
|
|
// pickup_zone_title,
|
|
// pickup_zone_addr,
|
|
// drop_zone_title,
|
|
// drop_zone_addr,
|
|
pocket_total: 'Rp'+((new Intl.NumberFormat('id-ID')).format(insideZone.pocket_total)).split('.').join('-').split(',').join('.').split('-').join(','), // yang . => - || , => . || - => ,
|
|
bank_name: insideZone.drv_bank_name,
|
|
bank_code: insideZone.drv_bank_code,
|
|
bank_branch_name: insideZone.drv_bank_branch_name || '',
|
|
bank_acc_name: insideZone.drv_bank_acc_name,
|
|
bank_acc_no: insideZone.drv_bank_acc_number,
|
|
};
|
|
for (const updtOrd of updtToOrders) {
|
|
if (updtOrd.id === insideZone.ord_id) {
|
|
mailData.pickup_zone_title = updtOrd.pck_name;
|
|
mailData.pickup_zone_addr = updtOrd.pck_addr;
|
|
mailData.drop_zone_title = updtOrd.drop_name;
|
|
mailData.drop_zone_addr = updtOrd.drop_addr;
|
|
}
|
|
}
|
|
|
|
const danas = await DanaModels.list({'id': DanaModels.PK_ID, 'limit': 1});
|
|
if (danas.length < 1) {
|
|
apiRes = JSON.parse(JSON.stringify(response[400]));
|
|
apiRes.meta.message = 'dana error';
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
const dana = danas[0];
|
|
|
|
const payloadDana = {
|
|
'ord_id': insideZone.ord_id,
|
|
'ord_code': insideZone.ord_code,
|
|
'checkpoint_id': insideZone.checkpoint_id,
|
|
'bank_code': insideZone.drv_bank_code,
|
|
'bank_name': insideZone.drv_bank_name,
|
|
'bank_branch': insideZone.drv_bank_branch_name || null,
|
|
'amt': insideZone.pocket_total,
|
|
'acc_name': insideZone.drv_bank_acc_name,
|
|
'acc_number': insideZone.drv_bank_acc_number,
|
|
'device_id': device_id,
|
|
};
|
|
|
|
if (dana.amt > insideZone.pocket_total && dana.amt > DanaModels.MINIMUM_AMT) {
|
|
const axInstance = axios.create();
|
|
axios.defaults.timeout = 3000;
|
|
axios.defaults.crossDomain = true;
|
|
const respDana = await axInstance.post(process.env.API_DANA_BINGCORP + 'order/create', payloadDana, {
|
|
timeout: 3000,
|
|
headers: {
|
|
// 'Host': '127.0.0.1',
|
|
'Content-Type': 'application/json',
|
|
}
|
|
});
|
|
const respDataDana = respDana.data || {};
|
|
if (respDana.status != 200 || respDataDana.meta.code != 200) {
|
|
const insLogsTf = {
|
|
'ord_id': insideZone.ord_id,
|
|
'ord_code': insideZone.ord_code,
|
|
'type': OrdersLogsTfModels.TYPE_TF_CHECKPOINT,
|
|
'checkpoint_id': insideZone.checkpoint_id,
|
|
'amount': insideZone.pocket_total,
|
|
'stts': OrdersLogsTfModels.STTS_FAIL,
|
|
'fail_at': moment().unix(),
|
|
'note': respDataDana.data.note || 0,
|
|
'bank_id': insideZone.drv_bank_id,
|
|
'bank_name': insideZone.drv_bank_name,
|
|
'bank_code': insideZone.drv_bank_code,
|
|
'bank_short_name': insideZone.drv_bank_short_name,
|
|
'bank_branch_name': insideZone.drv_bank_branch_name || null,
|
|
'bank_acc_name': insideZone.drv_bank_acc_name,
|
|
'bank_acc_number': insideZone.drv_bank_acc_number,
|
|
'method': OrdersLogsTfModels.METHOD_DANA,
|
|
'url': process.env.API_DANA_BINGCORP + 'order/create',
|
|
'ref_code': respDataDana.data.dana_reference_no || 0,
|
|
'req_data': JSON.stringify(payloadDana),
|
|
'resp_data': JSON.stringify(respDataDana),
|
|
'crt': moment().unix(),
|
|
'updt': moment().unix(),
|
|
};
|
|
const updtOrdCheckpoint = {
|
|
'id': insideZone.checkpoint_id,
|
|
'pocket_is_paid': OrdersCheckpointsModels.IS_TF_FAIL,
|
|
'pocket_paid_note': respDataDana.data.note,
|
|
'pocket_paid_at': now,
|
|
'pocket_paid_by': 0,
|
|
'bank_id': insideZone.drv_bank_id,
|
|
'bank_name': insideZone.drv_bank_name,
|
|
'bank_code': insideZone.drv_bank_code,
|
|
'bank_short_name': insideZone.drv_bank_short_name,
|
|
'bank_branch_name': insideZone.drv_bank_branch_name || null,
|
|
'bank_acc_name': insideZone.drv_bank_acc_name,
|
|
'bank_acc_number': insideZone.drv_bank_acc_number,
|
|
'tf_method': OrdersCheckpointsModels.TF_METHOD_DANA,
|
|
'tf_at': now,
|
|
'tf_url': process.env.API_DANA_BINGCORP + 'order/create',
|
|
'tf_ref_code': respDataDana.data.dana_reference_no || 0,
|
|
'tf_note': respDataDana.data.note || 0,
|
|
'tf_req_data': JSON.stringify(payloadDana),
|
|
'tf_resp_data': JSON.stringify(respDataDana),
|
|
};
|
|
await OrdersCheckpointsModels.bundleUpdt(updtOrdCheckpoint, {}, insLogsTf);
|
|
continue;
|
|
}
|
|
|
|
const insLogsTf = {
|
|
'ord_id': insideZone.ord_id,
|
|
'ord_code': insideZone.ord_code,
|
|
'type': OrdersLogsTfModels.TYPE_TF_CHECKPOINT,
|
|
'checkpoint_id': insideZone.checkpoint_id,
|
|
'amount': insideZone.pocket_total,
|
|
'stts': OrdersLogsTfModels.STTS_PAID,
|
|
'paid_at': moment().unix(),
|
|
'note': respDataDana.data.note || 0,
|
|
'bank_id': insideZone.drv_bank_id,
|
|
'bank_name': insideZone.drv_bank_name,
|
|
'bank_code': insideZone.drv_bank_code,
|
|
'bank_short_name': insideZone.drv_bank_short_name,
|
|
'bank_branch_name': insideZone.drv_bank_branch_name || null,
|
|
'bank_acc_name': insideZone.drv_bank_acc_name,
|
|
'bank_acc_number': insideZone.drv_bank_acc_number,
|
|
'method': OrdersLogsTfModels.METHOD_DANA,
|
|
'url': process.env.API_DANA_BINGCORP + 'order/create',
|
|
'ref_code': respDataDana.data.dana_reference_no || 0,
|
|
'req_data': JSON.stringify(payloadDana),
|
|
'resp_data': JSON.stringify(respDataDana),
|
|
'crt': moment().unix(),
|
|
'updt': moment().unix(),
|
|
};
|
|
const updtOrdCheckpoint = {
|
|
'id': insideZone.checkpoint_id,
|
|
'pocket_is_paid': OrdersCheckpointsModels.IS_PAID_OFF,
|
|
'pocket_paid_at': now,
|
|
'pocket_paid_by': 0,
|
|
'bank_id': insideZone.drv_bank_id,
|
|
'bank_name': insideZone.drv_bank_name,
|
|
'bank_code': insideZone.drv_bank_code,
|
|
'bank_short_name': insideZone.drv_bank_short_name,
|
|
'bank_branch_name': insideZone.drv_bank_branch_name || null,
|
|
'bank_acc_name': insideZone.drv_bank_acc_name,
|
|
'bank_acc_number': insideZone.drv_bank_acc_number,
|
|
'tf_method': OrdersCheckpointsModels.TF_METHOD_DANA,
|
|
'tf_at': now,
|
|
'tf_url': process.env.API_DANA_BINGCORP + 'order/create',
|
|
'tf_ref_code': respDataDana.data.dana_reference_no || 0,
|
|
'tf_note': respDataDana.data.note || 0,
|
|
'tf_req_data': JSON.stringify(payloadDana),
|
|
'tf_resp_data': JSON.stringify(respDataDana),
|
|
};
|
|
const updtDana = {
|
|
'id': dana.id,
|
|
'amt': mysql.raw('amt-'+insideZone.pocket_total),
|
|
};
|
|
|
|
await OrdersCheckpointsModels.bundleUpdt(updtOrdCheckpoint, insOrdAItems, insLogsTf, updtDana);
|
|
} else {
|
|
for (const admin of admins_data) {
|
|
mailData.admin_name = admin.admin_name;
|
|
mailData.dana_current = 'Rp'+((new Intl.NumberFormat('id-ID')).format(dana.amt)).split('.').join('-').split(',').join('.').split('-').join(','); // yang . => - || , => . || - => ,,
|
|
mailData.dana_minimum = 'Rp'+((new Intl.NumberFormat('id-ID')).format(DanaModels.MINIMUM_AMT)).split('.').join('-').split(',').join('.').split('-').join(','); // yang . => - || , => . || - => ,,
|
|
LibMail.sendFinanceInfoDanaAmount('Saldo Dana Tidak Mencukupi', admin.admin_mail, mailData);
|
|
}
|
|
}
|
|
|
|
for (const admin of admins_data) {
|
|
mailData.admin_name = admin.admin_name;
|
|
LibMail.sendFinanceInfoTfPocket('Transfer uang saku order ' + mailData.trx_code, admin.admin_mail, mailData);
|
|
}
|
|
}
|
|
}
|
|
|
|
// spawn zone
|
|
const inSpawnCircle = await ZoneModels.getCheckpointsInCircle(lat, lng, {drv_id: did});
|
|
const inSpawnShape = await ZoneModels.getCheckpointsInShape(lat, lng, {drv_id: did});
|
|
let insideSpawnZone = [];
|
|
if (inSpawnCircle.length > 0 || inSpawnShape.length > 0) {
|
|
for (const circle of inSpawnCircle) {
|
|
// hit api disbure
|
|
if (circle.drv_bank_id == 0 || circle.drv_bank_acc_number == null) continue;
|
|
insideSpawnZone.push(circle);
|
|
}
|
|
for (const shape of inSpawnShape) {
|
|
// hit api disbure
|
|
if (shape.drv_bank_id == 0 || shape.drv_bank_acc_number == null) continue;
|
|
insideSpawnZone.push(shape);
|
|
}
|
|
}
|
|
|
|
let logDevices = [];
|
|
|
|
if (updtToOrders.length > 0) {
|
|
const includedVhcId = [];
|
|
for (const updtOrd of updtToOrders) {
|
|
if (includedVhcId.includes(updtOrd.vhc_id)) continue;
|
|
includedVhcId.push(updtOrd.vhc_id);
|
|
|
|
const logDevice = {
|
|
original_hex: null,
|
|
protocol: GpsTracksModels.PROTOCOL_SMARTPHONE,
|
|
action: GpsTracksModels.ACT_LOCATION,
|
|
device_id,
|
|
latitude: lat,
|
|
longitude: lng,
|
|
speed: null,
|
|
orientation: 0,
|
|
stts_engine: GpsTracksModels.STTS_EN_MOVING,
|
|
stts_gps: GpsTracksModels.STTS_GPS_ON,
|
|
stts_gsm: GpsTracksModels.STTS_GSM_STRONG_SIGNAL,
|
|
stts_reverse_geo: GpsTracksModels.STTS_REVERSE_GEO_NOT,
|
|
pre_milleage: 0, // dari jarak sebelumnya ke sekarang
|
|
sum_milleage: 0, // calculated on device_id (IMEI)
|
|
vhc_milleage: 0, // calucalted on vhc_id
|
|
drv_milleage: 0, // calucalted on drv_id
|
|
vhc_id: updtOrd.vhc_id,
|
|
drv_id: did,
|
|
source: GpsTracksModels.SOURCE_SMARTPHONE,
|
|
crt: now,
|
|
crt_format: moment.unix(now).format('YYYY-MM-DD HH:mm:ss'),
|
|
crt_d: req_at,
|
|
crt_d_format: moment.unix(req_at).format('YYYY-MM-DD HH:mm:ss'),
|
|
crt_s: now,
|
|
crt_s_format: moment.unix(now).format('YYYY-MM-DD HH:mm:ss'),
|
|
};
|
|
|
|
const lastTrack = await GpsTracksModels.get2LastLoc({vhc_id: updtOrd.vhc_id});
|
|
// const lastTrack = await GpsTracksModels.get2LastLoc({device_id}); // kurang cocok by device_id, karena ada case update lokasi tanpa orderan yang sedang aktif
|
|
// count milleage
|
|
if (logDevice.latitude != null && logDevice.longitude != null && lastTrack.length > 0) {
|
|
const distance = LibHelper.haversineGreatCircleDistance(lastTrack[0].latitude, lastTrack[0].longitude, logDevice.latitude, logDevice.longitude, LibHelper.EARTH_RADIUS_KM);
|
|
const distance_km = LibHelper.kmToKm(distance, 100000000);
|
|
console.log(`DRIVER UP LOCATION => vhc_id:${updtOrd.vhc_id}, did:${did}, distance_km:${distance_km}`);
|
|
if (distance_km < 3) {
|
|
const vhc = await VhcModels.getVhcById(logDevice.vhc_id);
|
|
if (vhc.length > 0) {
|
|
logDevice.pre_milleage = distance_km;
|
|
logDevice.sum_milleage = (lastTrack[0].sum_milleage + logDevice.pre_milleage).toFixed(8);
|
|
if (lastTrack[0].vhc_id == logDevice.vhc_id) {
|
|
logDevice.vhc_milleage = (lastTrack[0].vhc_milleage + logDevice.pre_milleage).toFixed(8);
|
|
} else {
|
|
logDevice.vhc_milleage = (vhc[0].sum_milleage + logDevice.pre_milleage).toFixed(8);
|
|
}
|
|
const drv = await DriversModels.find(did);
|
|
if (drv.length > 0) {
|
|
if (lastTrack[0].did == logDevice.did) {
|
|
logDevice.drv_milleage = (lastTrack[0].drv_milleage + logDevice.pre_milleage).toFixed(8);
|
|
} else {
|
|
logDevice.drv_milleage = (drv[0].sum_milleage + logDevice.pre_milleage).toFixed(8);
|
|
}
|
|
DriversModels.update({ sum_milleage: logDevice.drv_milleage }, did);
|
|
}
|
|
// VhcModels.update(updtOrd.vhc_id, { sum_milleage: logDevice.vhc_milleage });
|
|
}
|
|
}
|
|
}
|
|
|
|
logDevices.push(logDevice);
|
|
const currTrack = await GpsTracksModels.bundleCreate2(logDevice, {});
|
|
|
|
/**
|
|
* get lastSpawn desc index 0, where leave_at = 0
|
|
* kalo gaada create, dengan isi field enter_at aja, kalo ada didalam zona
|
|
* kalo ada update, dengan isi field leave_at aja, kalo udah diluar zona
|
|
*/
|
|
const lastSpawn = await GpsTracksModels.listSpawnZone({
|
|
source: GpsTracksModels.SOURCE_SMARTPHONE,
|
|
vhc_id: updtOrd.vhc_id,
|
|
drv_id: did,
|
|
ord_id: updtOrd.ord_id,
|
|
// ord_code: updtOrd.ord_code,
|
|
leave_at_d: 0,
|
|
order_by: 'ORDER BY id DESC',
|
|
limit: 1,
|
|
});
|
|
|
|
if (lastSpawn.length > 0) {
|
|
let is_leave_zone = 1, is_leave_zone_pck = 1, is_leave_zone_drop = 1;
|
|
for (const insideZone of insideSpawnZone) {
|
|
if (insideZone.ord_id === updtOrd.ord_id && insideZone.zid === lastSpawn[0].zone_id) is_leave_zone = 0;
|
|
if (insideZone.zid === updtOrd.pck_id) is_leave_zone_pck = 0;
|
|
if (insideZone.zid === updtOrd.drop_id) is_leave_zone_drop = 0;
|
|
}
|
|
if (is_leave_zone === 1 && lastSpawn[0].ord_id === updtOrd.ord_id) {
|
|
GpsTracksModels.updt2SpawnZone({
|
|
leave_lat: lat,
|
|
leave_lng: lng,
|
|
leave_at_d: req_at,
|
|
leave_at_d_format: moment.unix(req_at).format('YYYY-MM-DD HH:mm:ss'),
|
|
leave_at_s: now,
|
|
leave_at_s_format: moment.unix(now).format('YYYY-MM-DD HH:mm:ss'),
|
|
updt: now,
|
|
updt_format: moment.unix(now).format('YYYY-MM-DD HH:mm:ss'),
|
|
}, lastSpawn[0].id);
|
|
}
|
|
if (is_leave_zone_pck === 1 && updtOrd.pck_leave_at === 0) {
|
|
OrdersPickupsModels.updt({
|
|
id: updtOrd.ord_pck_id,
|
|
pck_leave_at: req_at,
|
|
});
|
|
}
|
|
if (is_leave_zone_drop === 1 && is_leave_zone_pck === 0 && updtOrd.pck_leave_at !== 0 && updtOrd.drop_leave_at === 0) {
|
|
OrdersDropsModels.updt({
|
|
id: updtOrd.ord_drop_id,
|
|
drop_leave_at: req_at,
|
|
});
|
|
}
|
|
} else {
|
|
for (const insideZone of insideSpawnZone) {
|
|
if (insideZone.ord_id === updtOrd.ord_id) {
|
|
GpsTracksModels.create2SpawnZone({
|
|
device_id: device_id,
|
|
master_id: Number(currTrack.result.insertId),
|
|
enter_lat: lat,
|
|
enter_lng: lng,
|
|
enter_at_d: req_at,
|
|
enter_at_d_format: moment.unix(req_at).format('YYYY-MM-DD HH:mm:ss'),
|
|
enter_at_s: now,
|
|
enter_at_s_format: moment.unix(now).format('YYYY-MM-DD HH:mm:ss'),
|
|
zone_id: insideZone.zid,
|
|
zone_name: insideZone.name,
|
|
vhc_id: updtOrd.vhc_id,
|
|
drv_id: did,
|
|
ord_id: insideZone.ord_id,
|
|
ord_pck_drop_id: insideZone.ord_pck_drop_id,
|
|
// ord_code: insideZone.ord_code,
|
|
source: GpsTracksModels.SOURCE_SMARTPHONE,
|
|
crt: now,
|
|
crt_format: moment.unix(now).format('YYYY-MM-DD HH:mm:ss'),
|
|
});
|
|
}
|
|
if (insideZone.zid === updtOrd.pck_id && updtOrd.pck_enter_at === 0) {
|
|
OrdersPickupsModels.updt({
|
|
id: updtOrd.ord_pck_id,
|
|
pck_enter_at: req_at,
|
|
});
|
|
}
|
|
if (insideZone.zid === updtOrd.drop_id && updtOrd.drop_enter_at === 0) {
|
|
OrdersDropsModels.updt({
|
|
id: updtOrd.ord_drop_id,
|
|
drop_enter_at: req_at,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
const logDevice = {
|
|
original_hex: null,
|
|
protocol: GpsTracksModels.PROTOCOL_SMARTPHONE,
|
|
action: GpsTracksModels.ACT_LOCATION,
|
|
device_id,
|
|
latitude: lat,
|
|
longitude: lng,
|
|
speed: null,
|
|
orientation: 0,
|
|
stts_engine: GpsTracksModels.STTS_EN_MOVING,
|
|
stts_gps: GpsTracksModels.STTS_GPS_ON,
|
|
stts_gsm: GpsTracksModels.STTS_GSM_STRONG_SIGNAL,
|
|
stts_reverse_geo: GpsTracksModels.STTS_REVERSE_GEO_NOT,
|
|
pre_milleage: 0, // dari jarak sebelumnya ke sekarang
|
|
sum_milleage: 0, // calculated on device_id (IMEI)
|
|
vhc_milleage: 0, // calucalted on vhc_id
|
|
drv_milleage: 0, // calucalted on drv_id
|
|
vhc_id: 0,
|
|
drv_id: did,
|
|
source: GpsTracksModels.SOURCE_SMARTPHONE,
|
|
crt: now,
|
|
crt_format: moment.unix(now).format('YYYY-MM-DD HH:mm:ss'),
|
|
crt_d: req_at,
|
|
crt_d_format: moment.unix(req_at).format('YYYY-MM-DD HH:mm:ss'),
|
|
crt_s: now,
|
|
crt_s_format: moment.unix(now).format('YYYY-MM-DD HH:mm:ss'),
|
|
};
|
|
|
|
const lastTrack = await GpsTracksModels.get2LastLoc({drv_id: did});
|
|
// count milleage
|
|
if (logDevice.latitude != null && logDevice.longitude != null && lastTrack.length > 0) {
|
|
const distance = LibHelper.haversineGreatCircleDistance(lastTrack[0].latitude, lastTrack[0].longitude, logDevice.latitude, logDevice.longitude, LibHelper.EARTH_RADIUS_KM);
|
|
const distance_km = LibHelper.kmToKm(distance, 100000000);
|
|
console.log(`DRIVER UP LOCATION => did:${did}, distance_km:${distance_km}`);
|
|
if (distance_km < 3) {
|
|
const drv = await DriversModels.find(did);
|
|
if (drv.length > 0) {
|
|
logDevice.pre_milleage = distance_km;
|
|
logDevice.sum_milleage = (lastTrack[0].sum_milleage + logDevice.pre_milleage).toFixed(8);
|
|
if (lastTrack[0].did == logDevice.did) {
|
|
logDevice.drv_milleage = (lastTrack[0].drv_milleage + logDevice.pre_milleage).toFixed(8);
|
|
} else {
|
|
logDevice.drv_milleage = (drv[0].sum_milleage + logDevice.pre_milleage).toFixed(8);
|
|
}
|
|
DriversModels.update({ sum_milleage: logDevice.drv_milleage }, did);
|
|
}
|
|
}
|
|
}
|
|
|
|
logDevices.push(logDevice);
|
|
const currTrack = await GpsTracksModels.bundleCreate2(logDevice, {});
|
|
|
|
/**
|
|
* get lastSpawn desc index 0, where leave_at = 0
|
|
* kalo gaada create, dengan isi field enter_at aja, kalo ada didalam zona
|
|
* kalo ada update, dengan isi field leave_at aja, kalo udah diluar zona
|
|
*/
|
|
const lastSpawn = await GpsTracksModels.listSpawnZone({
|
|
source: GpsTracksModels.SOURCE_SMARTPHONE,
|
|
vhc_id: 0,
|
|
drv_id: did,
|
|
ord_id: 0,
|
|
// ord_code: 0,
|
|
leave_at_d: 0,
|
|
order_by: 'ORDER BY id DESC',
|
|
limit: 1,
|
|
});
|
|
if (lastSpawn.length > 0) {
|
|
let is_leave_zone = 1;
|
|
for (const insideZone of insideSpawnZone) {
|
|
if (insideZone.zid === lastSpawn[0].zone_id) is_leave_zone = 0;
|
|
}
|
|
if (is_leave_zone === 1) {
|
|
GpsTracksModels.updt2SpawnZone({
|
|
leave_lat: lat,
|
|
leave_lng: lng,
|
|
leave_at_d: req_at,
|
|
leave_at_d_format: moment.unix(req_at).format('YYYY-MM-DD HH:mm:ss'),
|
|
leave_at_s: now,
|
|
leave_at_s_format: moment.unix(now).format('YYYY-MM-DD HH:mm:ss'),
|
|
updt: now,
|
|
updt_format: moment.unix(now).format('YYYY-MM-DD HH:mm:ss'),
|
|
}, lastSpawn[0].id);
|
|
}
|
|
} else {
|
|
for (const insideZone of insideSpawnZone) {
|
|
GpsTracksModels.create2SpawnZone({
|
|
device_id: device_id,
|
|
master_id: Number(currTrack.result.insertId),
|
|
enter_lat: lat,
|
|
enter_lng: lng,
|
|
enter_at_d: req_at,
|
|
enter_at_d_format: moment.unix(req_at).format('YYYY-MM-DD HH:mm:ss'),
|
|
enter_at_s: now,
|
|
enter_at_s_format: moment.unix(now).format('YYYY-MM-DD HH:mm:ss'),
|
|
zone_id: insideZone.zid,
|
|
zone_name: insideZone.name,
|
|
vhc_id: 0,
|
|
drv_id: did,
|
|
ord_id: 0,
|
|
// ord_code: 0,
|
|
source: GpsTracksModels.SOURCE_SMARTPHONE,
|
|
crt: now,
|
|
crt_format: moment.unix(now).format('YYYY-MM-DD HH:mm:ss'),
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
apiRes = JSON.parse(JSON.stringify(response[200]));
|
|
// apiRes.raw = updtToOrders;
|
|
// apiRes.logDevices = logDevices;
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
} catch (e) {
|
|
apiRes = JSON.parse(JSON.stringify(response[500]));
|
|
apiRes.meta.message += Helper.setErrMsg(': ' + e.message);
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(500).json(apiRes);
|
|
}
|
|
}
|
|
|
|
// OTHERS
|
|
async notif(req, res) {
|
|
let apiRes = {}
|
|
try {
|
|
const now = moment().unix();
|
|
const { did, title, body, type, fcm_token, silent_notif } = req.body;
|
|
|
|
// input validation
|
|
const input = {
|
|
did,
|
|
fcm_token,
|
|
title,
|
|
body,
|
|
type,
|
|
silent_notif,
|
|
};
|
|
const rulesInput = {
|
|
did: 'required|integer',
|
|
fcm_token: 'required|string',
|
|
title: 'string|max:255',
|
|
body: 'string',
|
|
type: 'required|integer',
|
|
silent_notif: 'boolean',
|
|
};
|
|
const isInputValid = new Validator(input, rulesInput);
|
|
if (isInputValid.fails()) {
|
|
apiRes = JSON.parse(JSON.stringify(response[422]));
|
|
apiRes.meta.message += Helper.setErrMsg(': ' + Object.values(isInputValid.errors.all())[0][0]); // get first message
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
|
|
const optFirebase = {
|
|
priority: 'normal',
|
|
android: {
|
|
priority: 'high',
|
|
},
|
|
click_action: 'FLUTTER_NOTIFICATION_CLICK',
|
|
};
|
|
let content_available = 'false';
|
|
if (silent_notif === 'true' || silent_notif === true) {
|
|
optFirebase.content_available = true; // ios
|
|
content_available = 'true';
|
|
}
|
|
|
|
// const phoneDevice = await DriversModels.getDeviceByDid(did);
|
|
// if (phoneDevice.length < 1) {
|
|
// apiRes = JSON.parse(JSON.stringify(response[404]));
|
|
// apiRes.meta.code += '_1';
|
|
// apiRes.meta.message = 'account not found, driver not login';
|
|
LibLogReqResApi.log(req, apiRes);
|
|
// return res.status(200).json(apiRes);
|
|
// }
|
|
// if (phoneDevice[0].is_login !== DriversModels.IS_LOGIN) {
|
|
// apiRes = JSON.parse(JSON.stringify(response[404]));
|
|
// apiRes.meta.code += '_1';
|
|
// apiRes.meta.message = 'account not found, driver not login';
|
|
LibLogReqResApi.log(req, apiRes);
|
|
// return res.status(200).json(apiRes);
|
|
// }
|
|
|
|
// phoneDevice[0].fcm_token
|
|
const libFirebase = new LibFirebase();
|
|
let notifTitle = title || '';
|
|
let notifBody = body || '';
|
|
if (silent_notif === 'true' || silent_notif === true) {
|
|
optFirebase.priority = 'high';
|
|
await libFirebase.sendToDevice(fcm_token, {
|
|
notification: {
|
|
title: 'Notifikasi Cek Lokasi', // notifTitle,
|
|
body: 'Harap Dihiraukan', // notifBody,
|
|
},
|
|
data: {
|
|
title: notifTitle,
|
|
body: notifBody,
|
|
type: '' + type,
|
|
detail_id: '',
|
|
content_available,
|
|
}
|
|
}, optFirebase);
|
|
} else {
|
|
await libFirebase.sendToDevice(fcm_token, {
|
|
notification: {
|
|
title: notifTitle,
|
|
body: notifBody,
|
|
},
|
|
data: {
|
|
title: notifTitle,
|
|
body: notifBody,
|
|
type: '' + type,
|
|
detail_id: '',
|
|
content_available,
|
|
}
|
|
}, optFirebase);
|
|
}
|
|
|
|
apiRes = JSON.parse(JSON.stringify(response[200]));
|
|
apiRes.meta.message = 'success send notification';
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
} catch (e) {
|
|
apiRes = JSON.parse(JSON.stringify(response[500]));
|
|
apiRes.meta.message += Helper.setErrMsg(': ' + e.message);
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(500).json(apiRes);
|
|
}
|
|
}
|
|
|
|
// DEV ONLY
|
|
async lastLatLng(req, res) {
|
|
let apiRes = {}
|
|
try {
|
|
const now = moment().unix();
|
|
const { did } = req.query;
|
|
|
|
// input validation
|
|
const input = {
|
|
did,
|
|
};
|
|
const rulesInput = {
|
|
did: 'required|integer',
|
|
};
|
|
const isInputValid = new Validator(input, rulesInput);
|
|
if (isInputValid.fails()) {
|
|
apiRes = JSON.parse(JSON.stringify(response[422]));
|
|
apiRes.meta.message += Helper.setErrMsg(': ' + Object.values(isInputValid.errors.all())[0][0]); // get first message
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
}
|
|
|
|
const getLastLoc = await GpsTracksModels.getLastLocAndAddrByDid({did, limit: 100});
|
|
const formatLastLoc = [];
|
|
|
|
for (const lst of getLastLoc) {
|
|
formatLastLoc.push({
|
|
id: lst.id,
|
|
did: lst.drv_id,
|
|
device_id: lst.device_id,
|
|
latitude: lst.latitude,
|
|
longitude: lst.longitude,
|
|
state_text: lst.state_text,
|
|
city_text: lst.city_text,
|
|
district_text: lst.district_text,
|
|
village_text: lst.village_text,
|
|
streets_text: lst.streets_text,
|
|
fulladdress: lst.fulladdress,
|
|
crt_device_unix: lst.crt_d,
|
|
crt_dvice_raw: lst.crt_d_format,
|
|
crt_server_unix: lst.crt_s,
|
|
crt_server_raw: lst.crt_s_format,
|
|
});
|
|
}
|
|
|
|
apiRes = JSON.parse(JSON.stringify(response[200]));
|
|
apiRes.data = formatLastLoc;
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(200).json(apiRes);
|
|
} catch (e) {
|
|
apiRes = JSON.parse(JSON.stringify(response[500]));
|
|
apiRes.meta.message += Helper.setErrMsg(': ' + e.message);
|
|
LibLogReqResApi.log(req, apiRes);
|
|
return res.status(500).json(apiRes);
|
|
}
|
|
}
|
|
}
|
|
|
|
const object = new ServiceDriverController();
|
|
|
|
module.exports = object; |