Skip to content

Commit

Permalink
Merge pull request #94 from AplinkosMinisterija/91-leidimai-kirsti
Browse files Browse the repository at this point in the history
91 leidimai kirsti
  • Loading branch information
ambrazasp authored Jun 4, 2024
2 parents 648e1a2 + faffe1e commit 16e6b79
Show file tree
Hide file tree
Showing 9 changed files with 430 additions and 8 deletions.
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
"@types/qs": "^6.9.15",
"@types/showdown": "^2.0.6",
"@types/supercluster": "^7.1.3",
"@types/transform-coordinates": "^1.0.2",
"@types/unzipper": "^0.10.9",
"@typescript-eslint/eslint-plugin": "^5.11.0",
"@typescript-eslint/parser": "^5.11.0",
"eslint": "^8.8.0",
Expand All @@ -46,6 +48,7 @@
"@moleculer/database": "github:ambrazasp/moleculerjs-database",
"@r2d2bzh/moleculer-cron": "^0.1.4",
"@sentry/node": "^7.114.0",
"@turf/point-on-feature": "^6.5.0",
"biip-auth-nodejs": "github:DadPatch/biip-auth-nodejs",
"date-fns": "^3.3.1",
"dotenv": "^16.0.0",
Expand Down Expand Up @@ -73,6 +76,7 @@
"supercluster": "7.1.5",
"transform-coordinates": "^1.0.0",
"typescript": "^5.4.5",
"unzipper": "^0.11.6",
"vt-pbf": "^3.1.3"
},
"engines": {
Expand Down
1 change: 1 addition & 0 deletions services/apps.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
export enum APP_TYPES {
infostatyba = 'infostatyba',
izuvinimas = 'izuvinimas',
miskoKirtimai = 'miskoKirtimai',
}

export interface App extends CommonFields {
Expand Down
1 change: 1 addition & 0 deletions services/datagov.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ export default class DatagovService extends moleculer.Service {
const existingEvent: Event = await ctx.call('events.findOne', {
query: {
externalId: event.externalId,
app: appIdByDokType[entry.dok_tipo_kodas],
},
});

Expand Down
2 changes: 1 addition & 1 deletion services/events.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export type EventBodyJSON = {
};

export function toEventBodyMarkdown(data: EventBodyJSON[]) {
return data.map((i) => `**${i.title}**: ${i.value || ''}`).join('\n\n');
return data.map((i) => `**${i.title}**: ${i.value || '-'}`).join('\n\n');
}

interface Populates extends CommonPopulates {
Expand Down
3 changes: 2 additions & 1 deletion services/integrations.fishStockings.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import moleculer, { Context } from 'moleculer';
import { Action, Service } from 'moleculer-decorators';
import { Event, toEventBodyMarkdown } from './events.service';
import { APP_TYPES, App } from './apps.service';
// @ts-ignore
import transformation from 'transform-coordinates';

// @ts-ignore
import Cron from '@r2d2bzh/moleculer-cron';
import { getFeatureCollection } from 'geojsonjs';
Expand Down Expand Up @@ -164,6 +164,7 @@ export default class IntegrationsFishStockingsService extends moleculer.Service

const existingEvent: Event = await ctx.call('events.findOne', {
query: {
app: app.id,
externalId: entry.id,
},
});
Expand Down
192 changes: 192 additions & 0 deletions services/integrations.lumbering.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
'use strict';

import moleculer, { Context } from 'moleculer';
import { Action, Method, Service } from 'moleculer-decorators';
import { APP_TYPES, App } from './apps.service';
// @ts-ignore
import Cron from '@r2d2bzh/moleculer-cron';
import unzipper from 'unzipper';
import stream from 'node:stream';

import pointOnFeature from '@turf/point-on-feature';
import transformation from 'transform-coordinates';
import { getFeatureCollection } from 'geojsonjs';
import { Event, toEventBodyMarkdown } from './events.service';

@Service({
name: 'integrations.lumbering',
settings: {
zipUrl: 'https://lkmp.alisas.lt/static/lkmp-data.geojson.zip',
},
mixins: [Cron],
crons: [
{
name: 'integrationsLumbering',
cronTime: '0 12 * * *',
timeZone: 'Europe/Vilnius',
async onTick() {
await this.call('integrations.lumbering.getData', {
limit: process.env.NODE_ENV === 'local' ? 100 : 0,
});
},
},
],
})
export default class IntegrationsLumberingService extends moleculer.Service {
@Action({
timeout: 0,
params: {
limit: {
type: 'number',
optional: true,
default: 0,
},
initial: {
type: 'boolean',
optional: true,
default: false,
},
},
})
async getData(ctx: Context<{ limit: number; initial: boolean }>) {
const stats = {
total: 0,
valid: {
total: 0,
inserted: 0,
updated: 0,
},
invalid: {
total: 0,
},
};

const app: App = await ctx.call('apps.findOne', {
query: {
key: APP_TYPES.miskoKirtimai,
},
});

if (!app?.id) {
return;
}

const response: any = await ctx.call(
'http.get',
{
url: this.settings.zipUrl,
opt: { isStream: true },
},
{
timeout: 0,
},
);

const geojson: any = await new Promise(function (resolve) {
response.pipe(unzipper.Parse()).pipe(
new stream.Transform({
objectMode: true,
transform: async function (entry, _e, cb) {
const fileName = entry.path;
const type = entry.type; // 'Directory' or 'File'

if (type === 'File' && fileName === 'lkmp-data.geojson') {
const chunks: Buffer[] = [];

entry.on('data', function (chunk: Buffer) {
chunks.push(chunk);
});

// Send the buffer or you can put it into a var
entry.on('end', function () {
const jsonString = Buffer.concat(chunks).toString('utf-8');
const geojson = JSON.parse(jsonString);
resolve(geojson);
});
}

cb();
},
}),
);
});

const features: any[] = ctx.params.limit
? geojson.features.splice(0, ctx.params.limit)
: geojson.features;

const transform = transformation('EPSG:4326', '3346');
for (const feature of features) {
const pointOnPolygon = pointOnFeature(feature);

const transformedCoordinates = transform.forward([
pointOnPolygon.geometry.coordinates[0],
pointOnPolygon.geometry.coordinates[1],
]);

const geom = getFeatureCollection({
type: 'Point',
coordinates: transformedCoordinates,
});

const bodyJSON = [
{ title: 'VĮ VMU padalinys', value: `${feature.properties.padalinys} RP` },
{ title: 'Girininkija', value: `${feature.properties.girininkija} girininkija` },
{
title: 'Galioja',
value: `${feature.properties.galioja_nuo} iki ${feature.properties.galioja_iki}`,
},
{ title: 'Kvartalas', value: feature.properties.kvartalas },
{ title: 'Sklypas', value: feature.properties.sklypas },
{ title: 'Kertamas plotas', value: feature.properties.kertamas_plotas },
{ title: 'Kirtimo rūšis', value: feature.properties.kirtimo_rusis },
{ title: 'Vyraujantys medžiai', value: feature.properties.vyraujantys_medziai },
{ title: 'Atkūrimo būdas', value: feature.properties.atkurimo_budas },
];

const event: Partial<Event> = {
name: `${feature.properties.kirtimo_rusis}, ${feature.properties.girininkija} girininkija, ${feature.properties.padalinys} r.p.`,
body: toEventBodyMarkdown(bodyJSON),
startAt: new Date(feature.properties.galioja_nuo),
endAt: new Date(feature.properties.galioja_iki),
geom,
app: app.id,
isFullDay: true,
externalId: feature.properties.id,
};

if (ctx.params.initial) {
event.createdAt = event.startAt;
}

stats.total++;

if (!event.externalId) {
stats.invalid.total++;
} else {
const existingEvent: Event = await ctx.call('events.findOne', {
query: {
externalId: event.externalId,
app: app.id,
},
});

if (existingEvent?.id) {
await ctx.call('events.update', {
id: Number(existingEvent.id),
...event,
});
stats.valid.total++;
stats.valid.updated++;
} else {
await ctx.call('events.create', event);
stats.valid.total++;
stats.valid.inserted++;
}
}
}

this.broker.emit('tiles.events.renew');
return stats;
}
}
27 changes: 26 additions & 1 deletion services/seed.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ const APPS = {
description: 'Įžuvinimų informacinė sistema',
icon: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M2 16C2 16 11 1 22 12C11 23 2 8 2 8" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>',
},
miskoKirtimai: {
type: APP_TYPES.miskoKirtimai,
name: 'Miško kirtimai',
description: 'Miško kirtimų informacinė sistema',
icon: '<svg width="24" height="24" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M10.75 9.5L13 11.975C13.1028 12.0798 13.1725 12.2125 13.2006 12.3566C13.2287 12.5007 13.2139 12.6499 13.158 12.7856C13.1021 12.9214 13.0076 13.0377 12.8861 13.1203C12.7647 13.2028 12.6218 13.2479 12.475 13.25H1.52499C1.37819 13.2479 1.23523 13.2028 1.11383 13.1203C0.992422 13.0377 0.897912 12.9214 0.842014 12.7856C0.786117 12.6499 0.77129 12.5007 0.799371 12.3566C0.827452 12.2125 0.897207 12.0798 0.999988 11.975L3.24999 9.5H3.02499C2.87819 9.49794 2.73523 9.45284 2.61383 9.37029C2.49242 9.28775 2.39791 9.17139 2.34201 9.03564C2.28612 8.89988 2.27129 8.75071 2.29937 8.60661C2.32745 8.46252 2.39721 8.32983 2.49999 8.225L4.74999 5.75H4.59999C4.4468 5.76382 4.29307 5.7302 4.15962 5.65371C4.02618 5.57722 3.91948 5.46155 3.85399 5.32238C3.7885 5.18321 3.76738 5.02727 3.7935 4.87569C3.81961 4.72411 3.8917 4.58423 3.99999 4.475L6.99999 1.25L9.99999 4.475C10.1083 4.58423 10.1804 4.72411 10.2065 4.87569C10.2326 5.02727 10.2115 5.18321 10.146 5.32238C10.0805 5.46155 9.97379 5.57722 9.84035 5.65371C9.70691 5.7302 9.55318 5.76382 9.39999 5.75H9.24999L11.5 8.225C11.6028 8.32983 11.6725 8.46252 11.7006 8.60661C11.7287 8.75071 11.7139 8.89988 11.658 9.03564C11.6021 9.17139 11.5076 9.28775 11.3861 9.37029C11.2647 9.45284 11.1218 9.49794 10.975 9.5H10.75Z" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>',
},
};

@Service({
Expand All @@ -60,6 +66,7 @@ export default class SeedService extends moleculer.Service {
const apps: Record<string, App['id'][]> = await this.seedApps(ctx);
await this.infostatyba(ctx, apps.infostatyba);
await this.fishStockings(ctx, apps.izuvinimas);
await this.lumbering(ctx, apps.miskoKirtimai);
return true;
}

Expand Down Expand Up @@ -111,7 +118,25 @@ export default class SeedService extends moleculer.Service {
});

if (!count) {
await ctx.call('integrations.fishStockings.getData', { limit: 100 });
await ctx.call('integrations.fishStockings.getData', {
limit: process.env.NODE_ENV === 'local' ? 100 : 0,
});
}
}

@Method
async lumbering(ctx: Context, appsIds: App['id'][]) {
await this.broker.waitForServices(['integrations.lumbering', 'events']);

const count: number = await ctx.call('events.count', {
query: { app: { $in: appsIds } },
});

if (!count) {
await ctx.call('integrations.lumbering.getData', {
limit: process.env.NODE_ENV === 'local' ? 100 : 0,
initial: true,
});
}
}

Expand Down
4 changes: 2 additions & 2 deletions types/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ export const COMMON_FIELDS = {
createdAt: {
type: 'date',
columnType: 'datetime',
readonly: true,
onCreate: () => new Date(),
immutable: true,
onCreate: ({ value }: FieldHookCallback) => value || new Date(),
},

updatedBy: {
Expand Down
Loading

0 comments on commit 16e6b79

Please sign in to comment.