const db = require(`../config/dbMysqlConn`); const defaultSelectGetInZone = ` z.id as zid,z.name,z.desc,z.type,zt.name as type_name,z.workflow_type,zw.name as workflow_type_name ,z.shiptocode,z.fulladdress,z.boundary_type,z.boundary_radius,z.boundary_latlngs,ST_AsText(boundary_points) as points ,z.client_group_id,c.c_name,c_mail,c.pic_name,c.pic_mail `; class ZoneModels { static STTS_ACTIVE = 1; static STTS_INACTIVE = 2; static ZONE_BOUNDARY_CIRCLE = 'circle'; static ZONE_BOUNDARY_POLYGON = 'polygon'; static ZONE_BOUNDARY_RECTANGLE = 'rectangle'; static async getNearest(lat, lng, meters) { return new Promise((resolve, reject) => { let params = []; let query = 'SELECT'; query += defaultSelectGetInZone; query += ` ,ST_Distance_Sphere( ST_GeomFromText('POINT(${lng} ${lat})'), z.boundary_points) AS distance_meters`; // params.push(lng, lat); query += ' FROM t_zones AS z'; query += ' INNER JOIN t_zones_types AS zt ON z.type = zt.id'; query += ' INNER JOIN t_zones_workflows AS zw ON z.workflow_type = zw.id'; query += ' LEFT JOIN t_clients AS c ON z.client_group_id = c.id'; query += ' WHERE z.dlt is null AND z.status = ?'; params.push(ZoneModels.STTS_ACTIVE); query += ' HAVING distance_meters <= ?'; params.push(meters); db.query(query, params, function (err, resp) { if (err) { reject(err); return false; } resolve(resp); return true; }); }); } static async getInCircle(lat, lng, filter = {}) { return new Promise((resolve, reject) => { let params = []; let query = 'SELECT'; query += defaultSelectGetInZone; query += ` ,ST_Distance_Sphere( ST_GeomFromText('POINT(${lng} ${lat})'), z.boundary_points) AS distance_meters`; // params.push(lng, lat); query += ' FROM t_zones AS z'; query += ' INNER JOIN t_zones_types AS zt ON z.type = zt.id'; query += ' INNER JOIN t_zones_workflows AS zw ON z.workflow_type = zw.id'; query += ' LEFT JOIN t_clients AS c ON z.client_group_id = c.id'; query += ' WHERE z.dlt is null AND z.status = ? AND z.boundary_type = ?'; params.push(ZoneModels.STTS_ACTIVE, ZoneModels.ZONE_BOUNDARY_CIRCLE); if (filter['zid']) { query += ' AND z.id = ?'; params.push(filter['zid']); } query += ' HAVING boundary_radius >= distance_meters'; db.query(query, params, function (err, resp) { if (err) { reject(err); return false; } resolve(resp); return true; }); }); } static async getInShape(lat, lng, filter = {}) { return new Promise((resolve, reject) => { let params = []; let query = 'SELECT'; query += defaultSelectGetInZone; query += ` ,ST_Distance_Sphere( ST_GeomFromText('POINT(${lng} ${lat})'), z.boundary_points) AS distance_meters`; query += ` ,MBRContains( boundary_points, ST_GeomFromText('POINT(${lng} ${lat})') ) as is_contain`; query += ` ,MBRWithin( ST_GeomFromText('POINT(${lng} ${lat})'), boundary_points ) as is_within`; // params.push(lng, lat); query += ' FROM t_zones AS z'; query += ' INNER JOIN t_zones_types AS zt ON z.type = zt.id'; query += ' INNER JOIN t_zones_workflows AS zw ON z.workflow_type = zw.id'; query += ' LEFT JOIN t_clients AS c ON z.client_group_id = c.id'; query += ' WHERE z.dlt is null AND z.status = ? AND z.boundary_type IN (?,?)'; params.push(ZoneModels.STTS_ACTIVE, ZoneModels.ZONE_BOUNDARY_POLYGON, ZoneModels.ZONE_BOUNDARY_RECTANGLE); if (filter['zid']) { query += ' AND z.id = ?'; params.push(filter['zid']); } query += ' HAVING is_within = 1'; query += ' AND is_contain = 1'; db.query(query, params, function (err, resp) { if (err) { reject(err); return false; } resolve(resp); return true; }); }); } static async getOrdInCircle(lat, lng, filter = {}) { return new Promise((resolve, reject) => { let params = []; let query = 'SELECT'; query += defaultSelectGetInZone; query += ` ,ST_Distance_Sphere( ST_GeomFromText('POINT(${lng} ${lat})'), z.boundary_points) AS distance_meters`; // params.push(lng, lat); query += ' FROM t_zones AS z'; query += ' INNER JOIN t_zones_types AS zt ON z.type = zt.id'; query += ' INNER JOIN t_zones_workflows AS zw ON z.workflow_type = zw.id'; query += ' LEFT JOIN t_clients AS c ON z.client_group_id = c.id'; query += ' WHERE z.boundary_type = ?'; params.push(ZoneModels.ZONE_BOUNDARY_CIRCLE); if (filter['zid']) { query += ' AND z.id = ?'; params.push(filter['zid']); } query += ' HAVING boundary_radius >= distance_meters'; db.query(query, params, function (err, resp) { if (err) { reject(err); return false; } resolve(resp); return true; }); }); } static async getOrdInShape(lat, lng, filter = {}) { return new Promise((resolve, reject) => { let params = []; let query = 'SELECT'; query += defaultSelectGetInZone; query += ` ,ST_Distance_Sphere( ST_GeomFromText('POINT(${lng} ${lat})'), z.boundary_points) AS distance_meters`; query += ` ,MBRContains( boundary_points, ST_GeomFromText('POINT(${lng} ${lat})') ) as is_contain`; query += ` ,MBRWithin( ST_GeomFromText('POINT(${lng} ${lat})'), boundary_points ) as is_within`; // params.push(lng, lat); query += ' FROM t_zones AS z'; query += ' INNER JOIN t_zones_types AS zt ON z.type = zt.id'; query += ' INNER JOIN t_zones_workflows AS zw ON z.workflow_type = zw.id'; query += ' LEFT JOIN t_clients AS c ON z.client_group_id = c.id'; query += ' WHERe z.boundary_type IN (?,?)'; params.push(ZoneModels.ZONE_BOUNDARY_POLYGON, ZoneModels.ZONE_BOUNDARY_RECTANGLE); if (filter['zid']) { query += ' AND z.id = ?'; params.push(filter['zid']); } query += ' HAVING is_within = 1'; query += ' AND is_contain = 1'; db.query(query, params, function (err, resp) { if (err) { reject(err); return false; } resolve(resp); return true; }); }); } static async testZoning() { return new Promise((resolve, reject) => { ` -- in mysql using x,y => longitude,latitude -- ST_GeomFromText(col) => convert text to blob, ST_AsText(col) convert blob to text SELECT id,name,boundary_type,boundary_radius,ST_AsText(boundary_points) FROM db_trucking.t_zones; -- nearest zone from this latLng for circle. if radius less than meters, it mean this loc in this zone SELECT id,name,boundary_type,boundary_radius as radius,ST_AsText(boundary_points) AS zonasi ,ST_Distance_Sphere( ST_GeomFromText('POINT(106.834916 -6.161736)'), boundary_points) AS meters FROM db_trucking.t_zones WHERE boundary_type='circle' HAVING radius >= meters; -- id:3 => -6.57538126,106.63426234 -- id:5 => -6.244811,106.865669 -- nearest zone from this latLng for polygon,rectangle SELECT id,name,boundary_type ,MBRContains( boundary_points, ST_GeomFromText('POINT(106.865669 -6.244811)') ) as contain ,MBRWithin( ST_GeomFromText('POINT(106.865669 -6.244811)'), boundary_points ) as within ,ST_AsText(boundary_points) as zonasi ,ST_Distance_Sphere( ST_GeomFromText('POINT(106.865669 -6.244811)'), boundary_points) AS meters FROM db_trucking.t_zones WHERE boundary_type IN ('polygon','rectangle') HAVING within >= 1; ` let params = []; let query = 'SELECT * FROM t_zones'; db.query(query, params, function (err, resp) { if (err) { reject(err); return false; } resolve(resp); return true; }); }); } static async getCheckpointsInCircle(lat, lng, filter = {}) { return new Promise((resolve, reject) => { let params = []; let where = ''; let query = 'SELECT'; query += defaultSelectGetInZone; query += ` ,ord.id as ord_id,ord.code as ord_code,ord_pck_drop.id as ord_pck_drop_id ,ord.status as stts_order,ord_pck_drop.stts as stts_delivery ,ord.crt as ord_crt,ord_pck_drop.crt as ord_pck_drop_crt ,checkpoint.id as checkpoint_id,checkpoint.pocket_sort,checkpoint.pocket_is_paid,checkpoint.pocket_total ,ord_drv.drv_id,ord_drv.drv_name,ord_drv.drv_bank_id,ord_drv.drv_bank_code,ord_drv.drv_bank_name,ord_drv.drv_bank_short_name,ord_drv.drv_bank_acc_number,ord_drv.drv_bank_acc_name `; query += ` ,ST_Distance_Sphere( ST_GeomFromText('POINT(${lng} ${lat})'), z.boundary_points) AS distance_meters`; // params.push(lng, lat); query += ' FROM t_zones AS z'; query += ' INNER JOIN t_zones_types AS zt ON z.type = zt.id'; query += ' INNER JOIN t_zones_workflows AS zw ON z.workflow_type = zw.id'; query += ' LEFT JOIN t_clients AS c ON z.client_group_id = c.id'; query += ' INNER JOIN t_orders_checkpoints AS checkpoint ON z.id = checkpoint.pck_id'; query += ' INNER JOIN t_orders AS ord ON checkpoint.ord_id = ord.id'; query += ' INNER JOIN t_orders_pck_drop AS ord_pck_drop ON checkpoint.ord_id = ord_pck_drop.ord_id'; query += ' INNER JOIN t_orders_drivers AS ord_drv ON checkpoint.ord_id = ord_drv.ord_id'; query += ' WHERE ord.dlt is null AND checkpoint.dlt is null AND z.boundary_type = ?'; params.push(ZoneModels.ZONE_BOUNDARY_CIRCLE); if (typeof filter['pocket_is_paid'] !== 'undefined') query += ' AND checkpoint.pocket_is_paid = ' + filter['pocket_is_paid']; if (typeof filter['where_not_pocket_is_paid'] !== 'undefined') query += ' AND checkpoint.pocket_is_paid != ' + filter['where_not_pocket_is_paid']; if (typeof filter['pocket_sort'] !== 'undefined') query += ' AND checkpoint.pocket_sort != 1'; if (typeof filter['drv_id'] !== 'undefined') query += ' AND ord_drv.drv_id = ' + filter['drv_id']; if (filter['stts_delivery'] && filter['stts_delivery'].length > 0) { where += ' AND ord_pck_drop.stts IN ('; for (const stts_delivery of filter['stts_delivery']) { where += '?,'; params.push(stts_delivery); } where = where.slice(0, -1) + ')'; } query += where; query += ' HAVING boundary_radius >= distance_meters'; db.query(query, params, function (err, resp) { if (err) { reject(err); return false; } resolve(resp); return true; }); }); } static async getCheckpointsInShape(lat, lng, filter = {}) { return new Promise((resolve, reject) => { let params = []; let where = ''; let query = 'SELECT'; query += defaultSelectGetInZone; query += ` ,ord.id as ord_id,ord.code as ord_code,ord_pck_drop.id as ord_pck_drop_id ,ord.status as stts_order,ord_pck_drop.stts as stts_delivery ,ord.crt as ord_crt,ord_pck_drop.crt as ord_pck_drop_crt ,checkpoint.id as checkpoint_id,checkpoint.pocket_sort,checkpoint.pocket_is_paid,checkpoint.pocket_total ,ord_drv.drv_id,ord_drv.drv_name,ord_drv.drv_bank_id,ord_drv.drv_bank_code,ord_drv.drv_bank_name,ord_drv.drv_bank_short_name,ord_drv.drv_bank_branch_name,ord_drv.drv_bank_acc_number,ord_drv.drv_bank_acc_name `; query += ` ,ST_Distance_Sphere( ST_GeomFromText('POINT(${lng} ${lat})'), z.boundary_points) AS distance_meters`; query += ` ,MBRContains( boundary_points, ST_GeomFromText('POINT(${lng} ${lat})') ) as is_contain`; query += ` ,MBRWithin( ST_GeomFromText('POINT(${lng} ${lat})'), boundary_points ) as is_within`; // params.push(lng, lat); query += ' FROM t_zones AS z'; query += ' INNER JOIN t_zones_types AS zt ON z.type = zt.id'; query += ' INNER JOIN t_zones_workflows AS zw ON z.workflow_type = zw.id'; query += ' LEFT JOIN t_clients AS c ON z.client_group_id = c.id'; query += ' INNER JOIN t_orders_checkpoints AS checkpoint ON z.id = checkpoint.pck_id'; query += ' INNER JOIN t_orders AS ord ON checkpoint.ord_id = ord.id'; query += ' INNER JOIN t_orders_pck_drop AS ord_pck_drop ON checkpoint.ord_id = ord_pck_drop.ord_id'; query += ' INNER JOIN t_orders_drivers AS ord_drv ON checkpoint.ord_id = ord_drv.ord_id'; query += ' WHERE ord.dlt is null AND checkpoint.dlt is null AND z.boundary_type IN (?,?)'; params.push(ZoneModels.ZONE_BOUNDARY_POLYGON, ZoneModels.ZONE_BOUNDARY_RECTANGLE); if (typeof filter['pocket_is_paid'] !== 'undefined') query += ' AND checkpoint.pocket_is_paid = ' + filter['pocket_is_paid']; if (typeof filter['where_not_pocket_is_paid'] !== 'undefined') query += ' AND checkpoint.pocket_is_paid != ' + filter['where_not_pocket_is_paid']; if (typeof filter['pocket_sort'] !== 'undefined') query += ' AND checkpoint.pocket_sort != 1'; if (typeof filter['drv_id'] !== 'undefined') query += ' AND ord_drv.drv_id = ' + filter['drv_id']; if (filter['stts_delivery'] && filter['stts_delivery'].length > 0) { where += ' AND ord_pck_drop.stts IN ('; for (const stts_delivery of filter['stts_delivery']) { where += '?,'; params.push(stts_delivery); } where = where.slice(0, -1) + ')'; } query += where; query += ' HAVING is_within = 1'; query += ' AND is_contain = 1'; db.query(query, params, function (err, resp) { if (err) { reject(err); return false; } resolve(resp); return true; }); }); } } module.exports = ZoneModels;