Initial commit

This commit is contained in:
meusinfirmary
2025-04-22 14:31:37 +07:00
commit b7e852126c
115 changed files with 23188 additions and 0 deletions

137
workers/BlastOrderWorker.js Normal file
View File

@ -0,0 +1,137 @@
const SandboxedJobMQ = require('bullmq').SandboxedJob;
const LibWinston = require('../library/LibWinston');
const LibMail = require('../library/LibMail');
const moment = require('moment');
const GpsTracksModels = require('../models/GpsTracksModels');
const OrdersModels = require('../models/OrdersModels');
const OrdersVendorsModels = require('../models/OrdersVendorsModels');
const UsersModels = require('../models/UsersModels');
const queueName = process.env.REDIS_QUEUE_BLAST_ORDER;
const Logger = LibWinston.initialize(queueName);
module.exports = async (job) => {
try {
Logger.log('info', `${queueName} running: ${JSON.stringify(job.opts)}`);
const now = moment().unix();
const { ord_id, ord_code, base_link } = job.data;
if (!ord_id || !ord_code || !base_link) {
Logger.log('info', `${queueName} running_fail: data not valid`);
return {
type: 'fail',
message: 'data not valid',
data: null,
};
}
const order = await OrdersModels.showOrder({
'id': ord_id,
});
if (order.length < 1) {
Logger.log('info', `${queueName} running_fail: order not found on order_id ${ord_id}`);
return {
type: 'fail',
message: `order not found on order_id ${ord_id}`,
data: null,
};
}
++order[0].count_sch_blast_order;
// check is accepted
if (order[0].ord_vdr_id) {
Logger.log('info', `${queueName} running_info: order have been accepted by another vendor ${order[0].ord_vdr_id} on order_id ${ord_id}`);
return {
type: 'success',
message: 'order have been accepted by another vendor',
data: null,
};
}
// Kirim ke admin bahwa tidak ada vendor yang acc 3x10 menit
if (order[0].count_sch_blast_order >= 3) {
Logger.log('info', `${queueName} running_info: No vendor accept this order on order_id ${ord_id} in 3x10 minutes`);
let admins = await UsersModels.getUsersActiveByRole(UsersModels.ROLE_ADMIN);
for (let admin of admins) {
LibMail.sendAdminInfoNoVdrAccOrd('Order Diabaikan oleh Vendor', admin.email, {
trx_code: order[0].ord_code,
trx_at: moment.unix(order[0].crt).format('DD MMM YYYY'),
admin_id: admin.id,
admin_name: admin.first_name,
admin_phone: '0' + admin.phone,
admin_mail: admin.email,
admin_addr: admin.fulladdress,
client_id: order[0].c_id,
client_name: order[0].c_name,
client_phone: '0' + order[0].c_phone_val,
client_mail: order[0].c_mail,
client_addr: '',
client_prefer_type_truck: '',
pickup_zone_title: order[0].pck_name,
pickup_zone_addr: order[0].pck_addr,
pickup_at: order[0].set_pck_at,
drop_zone_title: order[0].drop_name,
drop_zone_addr: order[0].drop_addr,
});
}
return {
type: 'fail',
message: `No vendor accept this order on order_id ${ord_id} in 3x10 minutes`,
data: null,
};
}
OrdersModels.updt(order[0].ord_id, {
count_sch_blast_order: order[0].count_sch_blast_order,
});
// blast to other vendor
const nextVendors = await OrdersVendorsModels.getNextVendorsByOrdId(ord_id);
if (nextVendors.length > 0) {
for (let key in nextVendors) {
const blastToVendor = await OrdersVendorsModels.getById(nextVendors[key].id);
if (blastToVendor.length < 1) {
Logger.log('info', `${queueName} running_fail: vendor ${nextVendors[key].vdr_id} want to blast not found on order_id ${ord_id[key]}`);
continue;
}
// kalau expirednya mau diupdate
if (blastToVendor[0].status === OrdersVendorsModels.STTS_WAIT && blastToVendor[0].is_want === OrdersVendorsModels.IS_WANT_IGNORE) {
await OrdersVendorsModels.updt(nextVendors[key].id, {
is_exp: OrdersVendorsModels.LINK_WILL_EXP,
exp_at: moment.unix(now).add(10, 'minutes').unix(),
// exp_at: moment.unix(now).add(1, 'day').unix(),
});
}
const bidOrderMailData = {
trx_code: order[0].ord_code,
// client_id: order[0].ord_client_id,
client_name: order[0].c_name,
client_phone: '0' + order[0].c_phone_val,
client_mail: order[0].c_mail,
// client_addr,
client_prefer_type_truck: order[0].prefer_type_truck,
pickup_zone_title: order[0].pck_name,
pickup_zone_addr: order[0].pck_addr,
pickup_at: moment.unix(order[0].set_pck_at).format('DD MMM YYYY HH:mm') + ' WIB',
drop_zone_title: order[0].drop_name,
drop_zone_addr: order[0].drop_addr,
// vendor_id: blastToVendor[0].vdr_id,
vendor_name: blastToVendor[0].vdr_name,
vendor_phone: '0' + blastToVendor[0].vdr_phone_val,
vendor_mail: blastToVendor[0].vdr_mail,
vendor_addr: blastToVendor[0].vdr_addr,
vendor_acc_link: base_link + blastToVendor[0].bid_token,
};
LibMail.sendBidOrderMail('Ada Order Masuk', blastToVendor[0].vdr_mail, bidOrderMailData);
}
} else {
Logger.log('info', `${queueName} running_info: No next vendors, mean all vendors want but no accepted on order_id ${ord_id} in 3x10 minutes`);
}
// Logger.log('error', `${queueName} running_error: ${JSON.stringify(e, Object.getOwnPropertyNames(e))}`);
return {
type: 'success',
message: 'success do blast order to vendor',
data: null,
};
} catch (e) {
return {
type: 'error',
message: e.message,
e: e,
};
}
};

View File

@ -0,0 +1,117 @@
const SandboxedJobMQ = require('bullmq').SandboxedJob;
const LibWinston = require('../library/LibWinston');
const LibMail = require('../library/LibMail');
const moment = require('moment');
const GpsTracksModels = require('../models/GpsTracksModels');
const OrdersModels = require('../models/OrdersModels');
const OrdersVendorsModels = require('../models/OrdersVendorsModels');
const queueName = process.env.REDIS_QUEUE_BLAST_ORDER;
const Logger = LibWinston.initialize(queueName);
module.exports = async (job) => {
try {
Logger.log('info', `${queueName} running: ${JSON.stringify(job.opts)}`);
const now = moment().unix();
const data = job.data;
if (!data.ord_id || !data.ord_code) {
Logger.log('info', `${queueName} running_fail: data not valid`);
return {
type: 'fail',
message: 'data not valid',
data: null,
};
}
const order = await OrdersModels.showOrder({
'id': data.ord_id,
});
if (order.length < 1) {
Logger.log('info', `${queueName} running_fail: order not found on order_id ${data.ord_id}`);
return {
type: 'fail',
message: `order not found on order_id ${data.ord_id}`,
data: null,
};
}
// check is accepted
if (order[0].ord_vdr_id) {
Logger.log('info', `${queueName} running_info: order have been accepted by another vendor ${order[0].ord_vdr_id} on order_id ${data.ord_id}`);
return {
type: 'success',
message: 'order have been accepted by another vendor',
data: null,
};
} else {
await OrdersVendorsModels.updt(data.current_ord_vdr_id, {
status: OrdersVendorsModels.STTS_NOT_READY,
});
}
// blast to other vendor
if (data.next_ord_vdr_id.length > 0) {
for (let key in data.next_ord_vdr_id) {
// get by vendor_id not bid token
// let blastToVendor = await OrdersVendorsModels.getByBidToken(data.next_vdr_bid_token[key].tkn);
let blastToVendor = await OrdersVendorsModels.getById(data.next_ord_vdr_id[key].id);
if (blastToVendor.length < 1) {
Logger.log('info', `${queueName} running_fail: vendor want to blast not found on order_id ${data.ord_id[key]} and bid_token ${data.next_vdr_bid_token[key].tkn}`);
// return {
// type: 'fail',
// message: `vendor want to blast not found on order_id ${data.ord_id[key]} and bid_token ${data.next_vdr_bid_token[key].tkn}`,
// data: null,
// };
continue;
}
// kalau expirednya mau diupdate
// if (blastToVendor[0].status === OrdersVendorsModels.STTS_WAIT && blastToVendor[0].is_want === OrdersVendorsModels.IS_WANT_IGNORE) {
// await OrdersVendorsModels.updt(data.next_ord_vdr_id[key].id, {
// is_exp: OrdersVendorsModels.LINK_WILL_EXP,
// // exp_at: moment.unix(now).add(10, 'minutes').unix(),
// exp_at: moment.unix(now).add(1, 'day').unix(),
// });
// }
let bidOrderMailData = {
trx_code: order[0].ord_code,
// client_id: order[0].ord_client_id,
client_name: order[0].c_name,
client_phone: '0' + order[0].c_phone_val,
client_mail: order[0].c_mail,
// client_addr,
client_prefer_type_truck: order[0].prefer_type_truck,
// weight: Number(order[0].weight),
// cbm: Number(order[0].cbm),
// koli: Number(order[0].koli),
pickup_zone_title: order[0].pck_name,
pickup_zone_addr: order[0].pck_addr,
pickup_at: moment.unix(order[0].set_pck_at).format('DD MMM YYYY HH:mm') + ' WIB',
drop_zone_title: order[0].drop_name,
drop_zone_addr: order[0].drop_addr,
// vendor_id: blastToVendor[0].vdr_id,
vendor_name: blastToVendor[0].vdr_name,
vendor_phone: '0' + blastToVendor[0].vdr_phone_val,
vendor_mail: blastToVendor[0].vdr_mail,
vendor_addr: blastToVendor[0].vdr_addr,
vendor_acc_link: data.next_vdr_acc_link[key].link,
};
LibMail.sendBidOrderMail('Ada Order Masuk', blastToVendor[0].vdr_mail, bidOrderMailData);
}
} else {
await OrdersModels.updt(data.ord_id, {
status: OrdersModels.STTS_CANCEL,
cancel_type: OrdersModels.CANCEL_TYPE_VDR_NOT_READY,
cancel_at: now,
});
}
// Logger.log('error', `${queueName} running_error: ${JSON.stringify(e, Object.getOwnPropertyNames(e))}`);
return {
type: 'success',
message: 'success do blast order to vendor',
data: null,
};
} catch (e) {
return {
type: 'error',
message: e.message,
e: e,
};
}
};

View File

@ -0,0 +1,75 @@
const SandboxedJobMQ = require('bullmq').SandboxedJob;
const moment = require('moment');
const LibWinston = require('../library/LibWinston');
const LibFirebase = require('../library/LibFirebase');
const DriversModels = require('../models/DriversModels');
// const GpsTracksModels = require('../models/GpsTracksModels');
const schedulerName = process.env.REDIS_SCHEDULER_DRV_BLAST_NOTIF;
const Logger = LibWinston.initialize(schedulerName);
module.exports = async (job) => {
try {
Logger.log('info', `${schedulerName} running: ${JSON.stringify(job.opts)}`);
/**
* cek apakah ord_pck_drop.stts(status_delivery) === OrdersPckDropsModels.STTS_DELIVERY_FINISH_PICKUP
* jika iya dan sudah upload menu_travel_document maka kendaraan sedang dalam perjalanan ke lokasi drop
* cek apakah ord_pck_drop.stts(status_delivery) === OrdersPckDropsModels.STTS_DELIVERY_OTW_DROP
* jika iya dan ord_pck_drop.drv_app_lock_menu_otw_drop_at === 0 maka kendaraan masih dalam perjalanan ke lokasi drop
*/
const libFirebase = new LibFirebase();
let notifTitle = 'Pengecekan Aplikasi'; // cek app
let notifBody = 'Harap Dihiraukan'; // cek app
// (async function() {
try {
async function checkNotifNLogs(job) {
libFirebase.sendToDevice(job.drv_fcm_token, {
// notification: {
// title: notifTitle,
// body: notifBody,
// },
data: {
title: notifTitle,
body: notifBody,
type: '' + LibFirebase.blastNotif,
detail_id: '',
content_available: 'true',
}
}, {
priority: 'high', // to apple: normal(5), high(10)
android: {
priority: 'high', // to anroid: low(?). normal(5), high(10)
},
content_available: true,
click_action: 'FLUTTER_NOTIFICATION_CLICK',
});
}
let loop = process.env.SCHEDULE_DRV_BLAST_NOTIF_MAX_LOOP;
for (let x = 0; x < loop; x++) {
// all drivers login
const allDrvLogins = await DriversModels.getDriversLogin(DriversModels.IS_LOGIN);
for (const drv of allDrvLogins) {
await checkNotifNLogs({drv_fcm_token: drv.fcm_token});
}
}
} catch (e) {
console.error(e);
Logger.log('error', `${schedulerName} error: ${JSON.stringify(e)}`);
}
// })();
return {
type: 'success',
message: 'success run scheduler drv up photo',
data: null,
};
} catch (e) {
return {
type: 'error',
message: e.message,
e: e,
};
}
};

View File

@ -0,0 +1,116 @@
const SandboxedJobMQ = require('bullmq').SandboxedJob;
const moment = require('moment');
const LibWinston = require('../library/LibWinston');
const LibFirebase = require('../library/LibFirebase');
const OrdersModels = require('../models/OrdersModels');
const DriversModels = require('../models/DriversModels');
const OrdersPckDropsModels = require('../models/OrdersPckDropsModels');
// const GpsTracksModels = require('../models/GpsTracksModels');
const schedulerName = process.env.REDIS_SCHEDULER_DRV_UP_LOC_IDLE;
const Logger = LibWinston.initialize(schedulerName);
module.exports = async (job) => {
try {
Logger.log('info', `${schedulerName} running: ${JSON.stringify(job.opts)}`);
/**
* semua non-aktif order dan driver sedang login
* get last t_gps_tracks by drv_id
* jika crt_d > 2 hour => send notif
*/
const libFirebase = new LibFirebase();
let notifTitle = 'Notifikasi Cek Lokasi'; // up location
let notifBody = 'Harap Dihiraukan'; // up location
// (async function() {
try {
async function checkNotifNLogs(job) {
libFirebase.sendToDevice(job.drv_fcm_token, {
// notification: {
// title: notifTitle,
// body: notifBody,
// },
data: {
title: notifTitle,
body: notifBody,
type: '' + LibFirebase.upLocIdle,
detail_id: '',
content_available: 'true',
}
}, {
priority: 'high', // to apple: normal(5), high(10)
android: {
priority: 'high', // to anroid: low(?). normal(5), high(10)
},
content_available: true,
click_action: 'FLUTTER_NOTIFICATION_CLICK',
});
}
let loop = process.env.SCHEDULE_DRV_UP_LOC_IDLE_MAX_LOOP;
for (let x = 0; x < loop; x++) {
// all active order
const activeJobs = await OrdersModels.listOrders({
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,
inner_join_phone_devices: 1,
phone_devices_is_login: DriversModels.IS_LOGIN,
last_tracks_phone_drv: 1,
group_by: 'GROUP BY ord_drv.drv_id',
});
const drvs = [];
for (const job of activeJobs) {
drvs[job.drv_id] = job;
}
// all inactive order
const inactiveJobs = await OrdersModels.listOrders({
// is_active: OrdersModels.IS_ACTIVE,
delivery_statuses: [OrdersPckDropsModels.STTS_DELIVERY_HANDOVER_DOC],
couple_pck_drop: 1,
inner_join_phone_devices: 1,
phone_devices_is_login: DriversModels.IS_LOGIN,
last_tracks_phone_drv: 1,
group_by: 'GROUP BY ord_drv.drv_id',
});
for (const job of inactiveJobs) {
// baru ketembak notif, minimal ada 1x update lokasi
if (job.drv_fcm_token && job.tr_crt_d && job.tr_crt_d != 0) {
// if the driver id not in active order
if (typeof drvs[job.drv_id] === 'undefined') {
await checkNotifNLogs(job);
}
}
// ketembak notif jika belum pernah ada update lokasi samsek
else {
await checkNotifNLogs(job);
}
}
}
} catch (e) {
console.error(e);
Logger.log('error', `${schedulerName} error: ${JSON.stringify(e)}`);
}
// })();
return {
type: 'success',
message: 'success run scheduler drv up idle location',
data: null,
};
} catch (e) {
return {
type: 'error',
message: e.message,
e: e,
};
}
};

137
workers/DrvUpLocWorker.js Normal file
View File

@ -0,0 +1,137 @@
const SandboxedJobMQ = require('bullmq').SandboxedJob;
const moment = require('moment');
const LibWinston = require('../library/LibWinston');
const LibFirebase = require('../library/LibFirebase');
const OrdersModels = require('../models/OrdersModels');
const DriversModels = require('../models/DriversModels');
const OrdersPckDropsModels = require('../models/OrdersPckDropsModels');
const LogsSchNotifModels = require('../models/LogsSchNotifModels');
// const GpsTracksModels = require('../models/GpsTracksModels');
const schedulerName = process.env.REDIS_SCHEDULER_DRV_UP_LOC;
const Logger = LibWinston.initialize(schedulerName);
module.exports = async (job) => {
try {
// const now = moment().unix();
Logger.log('info', `${schedulerName} running: ${JSON.stringify(job.opts)}`);
/**
* semua aktif order dan driver sedang login
* get last t_gps_tracks by drv_id
* jika crt_d > 5 minute => send notif
*/
const libFirebase = new LibFirebase();
let notifTitle = 'Notifikasi Cek Lokasi'; // up location
let notifBody = 'Harap Dihiraukan'; // up location
// (async function() {
try {
async function checkNotifNLogs(job) {
// hapus logs notif jika lebih dari 3x dan lebih dari 1jam
const logs = await LogsSchNotifModels.list({ drv_id: job.drv_id, notif_type: LibFirebase.upLocActiveOrder, order_by: 'lognot.drv_id DESC', limit: 3 });
if (logs.length >= 3) {
let start = moment();
end = moment.unix(logs[0].crt);
duration = moment.duration(start.diff(end));
if (duration.asHours() >= 1) {
LogsSchNotifModels.delLogs({ drv_id: job.drv_id, notif_type: LibFirebase.upLocActiveOrder });
} else {
// continue;
return false;
}
}
// kirim notif
console.log('drvUpLocWorker driver id => ', job.drv_id, ' at ', moment().unix());
libFirebase.sendToDevice(job.drv_fcm_token, {
notification: {
title: notifTitle,
body: notifBody,
},
data: {
title: notifTitle,
body: notifBody,
type: '' + LibFirebase.upLocActiveOrder,
detail_id: '',
content_available: 'true',
}
}, {
priority: 'high', // to apple: normal(5), high(10)
android: {
priority: 'high', // to anroid: low(?). normal(5), high(10)
},
content_available: true,
click_action: 'FLUTTER_NOTIFICATION_CLICK',
});
LogsSchNotifModels.insLog({
fcm_token: job.drv_fcm_token,
device_id: job.drv_device_id,
drv_id: job.drv_id,
notif_type: LibFirebase.upLocActiveOrder,
crt: moment().unix(),
});
}
let loop = process.env.SCHEDULE_DRV_UP_LOC_MAX_LOOP;
for (let x = 0; x < loop; x++) {
// all active order
const activeJobs = await OrdersModels.listOrders({
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,
inner_join_phone_devices: 1,
phone_devices_is_login: DriversModels.IS_LOGIN,
last_tracks_phone_drv: 1,
group_by: 'GROUP BY ord_drv.drv_id',
});
/**
* jika telah mengirim notif lebih dari 3x, maka stop
* ngapusnya gimana ? permasalahnnya order yang didapet adalah ketika driver login
* ngapusnya pas driver sudah update data terbaru
* kalo misalkan pas ngirim notif masih ada log notif belum terhapus sebanyak 3x, maka check apakah sudah 1hari ? baru dihapus dan create log baru
*/
for (const job of activeJobs) {
// baru ketembak notif, minimal ada 1x update lokasi
if (job.drv_fcm_token && job.tr_crt_d && job.tr_crt_d != 0) {
// more than 5 minute
let start = moment();
let end = moment.unix(job.tr_crt_d);
let duration = moment.duration(start.diff(end));
if (duration.asMinutes() >= 4) {
await checkNotifNLogs(job);
} else {
LogsSchNotifModels.delLogs({ drv_id: job.drv_id, notif_type: LibFirebase.upLocActiveOrder });
}
}
// ketembak notif jika belum pernah ada update lokasi samsek
else {
await checkNotifNLogs(job);
}
}
}
} catch (e) {
console.error(e);
Logger.log('error', `${schedulerName} error: ${JSON.stringify(e)}`);
}
// })();
return {
type: 'success',
message: 'success run scheduler drv up location',
data: null,
};
} catch (e) {
return {
type: 'error',
message: e.message,
e: e,
};
}
};

107
workers/DrvUpPhotoWorker.js Normal file
View File

@ -0,0 +1,107 @@
const SandboxedJobMQ = require('bullmq').SandboxedJob;
const moment = require('moment');
const LibWinston = require('../library/LibWinston');
const LibFirebase = require('../library/LibFirebase');
const OrdersModels = require('../models/OrdersModels');
const DriversModels = require('../models/DriversModels');
const OrdersPckDropsModels = require('../models/OrdersPckDropsModels');
// const GpsTracksModels = require('../models/GpsTracksModels');
const schedulerName = process.env.REDIS_SCHEDULER_DRV_UP_PHOTO;
const Logger = LibWinston.initialize(schedulerName);
module.exports = async (job) => {
try {
Logger.log('info', `${schedulerName} running: ${JSON.stringify(job.opts)}`);
/**
* cek apakah ord_pck_drop.stts(status_delivery) === OrdersPckDropsModels.STTS_DELIVERY_FINISH_PICKUP
* jika iya dan sudah upload menu_travel_document maka kendaraan sedang dalam perjalanan ke lokasi drop
* cek apakah ord_pck_drop.stts(status_delivery) === OrdersPckDropsModels.STTS_DELIVERY_OTW_DROP
* jika iya dan ord_pck_drop.drv_app_lock_menu_otw_drop_at === 0 maka kendaraan masih dalam perjalanan ke lokasi drop
*/
const libFirebase = new LibFirebase();
let notifTitle = 'Notifikasi Cek Photo Saat diperjalanan'; // up location
let notifBody = 'Harap Dihiraukan'; // up location
// (async function() {
try {
async function checkNotifNLogs(job) {
libFirebase.sendToDevice(job.drv_fcm_token, {
// notification: {
// title: notifTitle,
// body: notifBody,
// },
data: {
title: notifTitle,
body: notifBody,
type: '' + LibFirebase.upPhotoOtwDrop,
detail_id: '' + job.detail_id,
content_available: 'true',
}
}, {
priority: 'high', // to apple: normal(5), high(10)
android: {
priority: 'high', // to anroid: low(?). normal(5), high(10)
},
content_available: true,
click_action: 'FLUTTER_NOTIFICATION_CLICK',
});
}
let loop = process.env.SCHEDULE_DRV_UP_PHOTO_MAX_LOOP;
for (let x = 0; x < loop; x++) {
// all active order
const activeJobs = await OrdersModels.listOrders({
is_active: OrdersModels.IS_ACTIVE,
delivery_statuses: [
OrdersPckDropsModels.STTS_DELIVERY_OTW_DROP
],
couple_pck_drop: 1,
inner_join_phone_devices: 1,
phone_devices_is_login: DriversModels.IS_LOGIN,
last_tracks_phone_drv: 1,
// group_by: 'GROUP BY ord_drv.drv_id',
});
let hadSends = [];
for (const job of activeJobs) {
// baru ketembak notif, minimal ada 1x update lokasi
if (job.drv_fcm_token && job.tr_crt_d && job.tr_crt_d != 0) {
if (job.drv_app_lock_menu_otw_drop_at !== 0) continue;
if (hadSends.includes(job.drv_id)) continue;
// more than 2 hour
let start = moment();
let end = moment.unix(job.tr_crt_d);
let duration = moment.duration(start.diff(end));
if (duration.asHours() >= 2) {
hadSends.push(job.drv_id);
job.detail_id = Buffer.from(`${job.ord_id}_${job.ord_pck_id}_${job.ord_drop_id}_${job.ord_pck_drop_id}`, 'ascii').toString('hex');
await checkNotifNLogs(job);
}
}
// ketembak notif jika belum pernah ada update lokasi samsek
else {
job.detail_id = Buffer.from(`${job.ord_id}_${job.ord_pck_id}_${job.ord_drop_id}_${job.ord_pck_drop_id}`, 'ascii').toString('hex');
await checkNotifNLogs(job);
}
}
}
} catch (e) {
console.error(e);
Logger.log('error', `${schedulerName} error: ${JSON.stringify(e)}`);
}
// })();
return {
type: 'success',
message: 'success run scheduler drv up photo',
data: null,
};
} catch (e) {
return {
type: 'error',
message: e.message,
e: e,
};
}
};

View File

@ -0,0 +1,258 @@
const SandboxedJobMQ = require('bullmq').SandboxedJob;
const LibWinston = require('../library/LibWinston');
const moment = require('moment');
const axios = require('axios').default;
const url = require('url');
const request = require('../config/request');
const GpsTracksModels = require('../models/GpsTracksModels');
const RegionModels = require('../models/RegionModels');
const schedulerName = process.env.REDIS_SCHEDULER_REVERSE_GEO;
const Logger = LibWinston.initialize(schedulerName);
module.exports = async (job) => {
try {
Logger.log('info', `${schedulerName} running: ${JSON.stringify(job.opts)}`);
// (async function() {
try {
let loop = process.env.SCHEDULE_REVERSE_GEO_MAX_LOOP;
for (let x = 0; x < loop; x++) {
// let tracks = [];
let tracks = await GpsTracksModels.get2ForReverseGeo(1);
for (let i = 0; i < tracks.length; i++) {
let now = moment().unix();
let updtData = {};
let respReverseGeo = null;
try {
const sameAddr = await GpsTracksModels.select2Address(tracks[i].latitude, tracks[i].longitude);
if (sameAddr.length > 0) {
let addrData = {
device_id: tracks[i].device_id,
master_id: tracks[i].id,
type: sameAddr[0].type,
lat: tracks[i].latitude,
lng: tracks[i].longitude,
country_id: sameAddr[0].country_id,
country_code: sameAddr[0].country_code,
country_text: sameAddr[0].country_text,
state_id: sameAddr[0].state_id,
state_text: sameAddr[0].state_text,
city_id: sameAddr[0].city_id,
city_text: sameAddr[0].city_text,
district_id: sameAddr[0].district_id,
district_text: sameAddr[0].district_text,
village_id: sameAddr[0].village_id,
village_text: sameAddr[0].village_text,
postcode: sameAddr[0].postcode,
streets: sameAddr[0].streets,
fulladdress: encodeURIComponent(decodeURIComponent(sameAddr[0].fulladdress)),
type_reverse_geo: sameAddr[0].type_reverse_geo,
stts_reverse_geo: GpsTracksModels.STTS_REVERSE_GEO_SC,
log_reverse_geo: sameAddr[0].log_reverse_geo,
crt: now,
crt_format: moment.unix(now).format('YYYY-MM-DD HH:mm:ss'),
};
GpsTracksModels.create2Address(addrData);
updtData.stts_reverse_geo = GpsTracksModels.STTS_REVERSE_GEO_SC;
await GpsTracksModels.update2(tracks[i].id, updtData);
continue;
}
let params = new url.URLSearchParams({
lat: tracks[i].latitude,
lon: tracks[i].longitude,
format: 'geojson',
});
const axInstance = axios.create();
axios.defaults.timeout = 3000;
axios.defaults.crossDomain = true;
// respReverseGeo = await axios({
// url: request.osm_reverse_geo.urlFull,
// method: request.osm_reverse_geo.method,
// params: params,
// responseType: 'json',
// });
respReverseGeo = await axInstance.get(request.osm_reverse_geo.urlFull + '?' + params.toString(), {
timeout: 3000,
});
let respData = respReverseGeo.data || {};
if (respReverseGeo.status == 200) {
if (respData.features.length < 1) {
GpsTracksModels.create2Address({
device_id: tracks[i].device_id,
master_id: tracks[i].id,
lat: tracks[i].latitude,
lng: tracks[i].longitude,
stts_reverse_geo: GpsTracksModels.STTS_REVERSE_GEO_LOST,
log_reverse_geo: JSON.stringify(respData),
crt: now,
crt_format: moment.unix(now).format('YYYY-MM-DD HH:mm:ss'),
});
updtData.stts_reverse_geo = GpsTracksModels.STTS_REVERSE_GEO_LOST;
await GpsTracksModels.update2(tracks[i].id, updtData);
} else {
let respAddr = respData.features[0].properties.address;
let addrData = {
device_id: tracks[i].device_id,
master_id: tracks[i].id,
lat: tracks[i].latitude,
lng: tracks[i].longitude,
country_id: GpsTracksModels.DEFAULT_COUNTRY_ID,
country_code: respAddr.country_code,
country_text: (respAddr.country) ? respAddr.country.toUpperCase() : respAddr.country || null,
state_id: null,
city_id: null,
district_id: null,
village_id: null,
postcode: respAddr.postcode,
fulladdress: encodeURIComponent(respData.features[0].properties.display_name),
stts_reverse_geo: GpsTracksModels.STTS_REVERSE_GEO_SC,
log_reverse_geo: (respData.features[0].properties) ? JSON.stringify(respData.features[0].properties) : null,
crt: now,
crt_format: moment.unix(now).format('YYYY-MM-DD HH:mm:ss'),
};
if (respAddr.state || respAddr.city) {
addrData.state_text = respAddr.region || respAddr.state || respAddr.state_district || respAddr.county || respAddr.city || '';
addrData.state_text = (addrData.state_text) ? addrData.state_text.toUpperCase() : addrData.state_text || null;
addrData.state_text = addrData.state_text || null;
}
if (respAddr.city_district || respAddr.city) {
addrData.city_text = respAddr.city_district || respAddr.city || '';
addrData.city_text = (addrData.city_text) ? addrData.city_text.toUpperCase() : addrData.city_text || null;
addrData.city_text = addrData.city_text || null;
}
if (respAddr.suburb || respAddr.subdistrict) {
addrData.district_text = respAddr.suburb || respAddr.subdistrict || respAddr.subdivision || '';
addrData.district_text = (addrData.district_text) ? addrData.district_text.toUpperCase() : addrData.district_text || null;
addrData.district_text = addrData.district_text || null;
}
if (respAddr.village) {
addrData.village_text = respAddr.village || respAddr.neighbourhood || '';
addrData.village_text = (addrData.village_text) ? addrData.village_text.toUpperCase() : addrData.village_text || null;
addrData.village_text = addrData.village_text || null;
}
if (respAddr.amenity || respAddr.road || respAddr.city_block) {
addrData.streets = '';
addrData.streets += (respAddr.amenity) ? respAddr.amenity + ', ' : '';
addrData.streets += (respAddr.road) ? respAddr.road + ', ' : '';
addrData.streets += (respAddr.house_number) ? respAddr.house_number + ', ' : '';
addrData.streets += (respAddr.house_name) ? respAddr.house_name + ', ' : '';
addrData.streets += (respAddr.city_block) ? respAddr.city_block + ', ' : '';
addrData.streets += addrData.streets || null;
if (addrData.streets) {
addrData.streets = encodeURIComponent(addrData.streets.slice(0, -2));
}
}
let byAll = await RegionModels.whereLike({
nmProvinsiKel: addrData.state_text,
nmKotamadyaKel: addrData.city_text,
nmKecamatanKel: addrData.district_text,
nmKelurahan: addrData.village_text,
});
if (byAll.length > 1) {
addrData.state_id = byAll[0].kodeProv;
addrData.city_id = byAll[0].kodeKab;
addrData.district_id = byAll[0].kodeKec;
addrData.village_id = byAll[0].kodeKel;
}
let byKel = await RegionModels.whereLike({
nmKelurahan: addrData.village_text,
});
if (byAll.length < 1 && byKel.length > 0) {
addrData.state_id = byKel[0].kodeProv;
addrData.city_id = byKel[0].kodeKab;
addrData.district_id = byKel[0].kodeKec;
addrData.village_id = byKel[0].kodeKel;
}
if (addrData.state_id === null) {
let byPr = await RegionModels.whereLike({ nmProvinsiKel: addrData.state_text });
if (byPr.length > 0) { addrData.state_id = byPr[0].kodeProv; }
}
if (addrData.state_id !== null && addrData.city_id === null) {
let byKt = await RegionModels.whereLike({ nmKotamadyaKel: addrData.city_text });
if (byKt.length > 0) { addrData.city_id = byKt[0].kodeKab; }
}
if (addrData.state_id !== null && addrData.city_id !== null && addrData.district_id === null) {
let byKc = await RegionModels.whereLike({ nmKecamatanKel: addrData.district_text });
if (byKc.length > 0) { addrData.district_id = byKc[0].kodeKec; }
}
if (addrData.state_id !== null && addrData.city_id !== null && addrData.district_id !== null && addrData.village_id === null) {
let byKl = await RegionModels.whereLike({ nmKelurahan: addrData.village_text });
if (byKl.length > 0) { addrData.village_id = byKl[0].kodeKel; }
}
GpsTracksModels.create2Address(addrData).catch((e) => {
Logger.log('error', `${schedulerName} running_error: ${JSON.stringify(e, Object.getOwnPropertyNames(e))}`);
});
updtData.stts_reverse_geo = GpsTracksModels.STTS_REVERSE_GEO_SC;
await GpsTracksModels.update2(tracks[i].id, updtData);
}
} else {
GpsTracksModels.create2Address({
device_id: tracks[i].device_id,
master_id: tracks[i].id,
lat: tracks[i].latitude,
lng: tracks[i].longitude,
stts_reverse_geo: GpsTracksModels.STTS_REVERSE_GEO_ER,
log_reverse_geo: JSON.stringify(respData),
crt: now,
crt_format: moment.unix(now).format('YYYY-MM-DD HH:mm:ss'),
});
updtData.stts_reverse_geo = GpsTracksModels.STTS_REVERSE_GEO_ER;
await GpsTracksModels.update2(tracks[i].id, updtData);
}
} catch (e) {
let respData = {}
if (respReverseGeo) {
if (respReverseGeo.status != 200) {
respData.data = respReverseGeo.data;
} else {
respData.msg = e.message;
}
} else if (typeof e.response != 'undefined') {
respData.data = e.response;
} else {
respData.msg = e.message;
}
GpsTracksModels.create2Address({
device_id: tracks[i].device_id,
master_id: tracks[i].id,
lat: tracks[i].latitude,
lng: tracks[i].longitude,
stts_reverse_geo: GpsTracksModels.STTS_REVERSE_GEO_ER,
log_reverse_geo: JSON.stringify(respData),
crt: now,
crt_format: moment.unix(now).format('YYYY-MM-DD HH:mm:ss'),
});
updtData.stts_reverse_geo = GpsTracksModels.STTS_REVERSE_GEO_ER;
await GpsTracksModels.update2(tracks[i].id, updtData);
}
job.updateProgress(1);
}
}
} catch (e) {
console.error(e);
Logger.log('error', `${schedulerName} error: ${JSON.stringify(e)}`);
}
// })();
return {
type: 'success',
message: 'success do reverse geocoding',
data: null,
};
} catch (e) {
return {
type: 'error',
message: e.message,
e: e,
};
}
};