js-klikvet-logic-worker 2.3.22 → 2.3.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/worker.mts CHANGED
@@ -1,13 +1,13 @@
1
1
 
2
- import assert from 'assert'
3
- import clonedeep from 'lodash.clonedeep'
4
- import makeDir from 'make-dir'
5
- import fs from 'fs'
6
- import path from 'path'
7
- import { Worker, Client } from 'cry-ebus2'
2
+ import assert from 'assert'
3
+ import clonedeep from 'lodash.clonedeep'
4
+ import makeDir from 'make-dir'
5
+ import fs from 'fs'
6
+ import path from 'path'
7
+ import { Worker, Client } from 'cry-ebus2'
8
8
  import { Mongo } from 'cry-db'
9
- import { arrayToObject, dedup, Log, serialize, sleep } from 'cry-helpers'
10
- import { ArtikelOsnova, Blagajna, Blagovnica, Cepljenje, Lokacija, Narocen, Nastavitve, Poslovalnica, PostavkaRacuna, Racun, Skladisce, VrstaPoslovnegaDogodka, VrstaRazknjizbeZdravila, VsotaDobavZaObdobje, anonimizirajPodatke, certs, createMongoForAnonimizacija, dobavaZdravil, ensureIndexes, karticaArtikla, koledarVeterinarja, mojPromet, pobrisiNeuporabljeno, podatkiRejca, poisciBlagovnice, poisciNeuporabljeno, porabaInProdajaZdravil, porabaZaDobavnico, prodajaZdravil, prodano, prodanoInPorabljeno, promet, racuni, racunovodji, razknjiziBlagovnico, razknjiziDobavnico, smsCepljen, smsCepljenjaNaDan, smsNarocen, smsNaroceniNaDan, spremembaZalogeZaObdobje, spremeniZalogoNaPodlagiRacuna, stranke, updateOpombeRejca, updatePotrditevBrejosti, updatePresusitve, updateStatusOsemenitve, vrniPopravekDobavniceCeNiZaPorabo, zakljucekBlagajne, zakljucekPolneInventureSestaviInZapisi, zalogaNaDan, zalogaPoDnevih, zaracunajDobavnice, zdruziStranke, zdruziPaciente } from 'cry-klikvet-logic'
9
+ import { Log, serialize, sleep } from 'cry-helpers'
10
+ import { Blagajna, Blagovnica, Cepljenje, Narocen, Nastavitve, Poslovalnica, PostavkaRacuna, Racun, Skladisce, VrstaPoslovnegaDogodka, VrstaRazknjizbeZdravila, VsotaDobavZaObdobje, anonimizirajPodatke, certs, createMongoForAnonimizacija, dobavaZdravil, ensureIndexes, karticaArtikla, koledarVeterinarja, mojPromet, pobrisiNeuporabljeno, podatkiRejca, poisciBlagovnice, poisciNeuporabljeno, porabaInProdajaZdravil, prodajaZdravil, prodano, prodanoInPorabljeno, promet, racuni, racunovodji, razknjiziBlagovnico, razknjiziDobavnico, smsCepljen, smsCepljenjaNaDan, smsNarocen, smsNaroceniNaDan, spremembaZalogeZaObdobje, spremeniZalogoNaPodlagiRacuna, stranke, updateOpombeRejca, updatePotrditevBrejosti, updatePresusitve, updateStatusOsemenitve, zakljucekBlagajne, zakljucekPolneInventureSestaviInZapisi, zalogaNaDan, zalogaPoDnevih, zaracunajDobavnice, zdruziStranke, zdruziPaciente, Obravnava, ArtikelKarkoli, zapisiPoraboZaObravnavo, zapisiPorabeZaObravnave, zapisiPorabeZaDobavnice, } from 'cry-klikvet-logic'
11
11
  import { OsemenitevGoveda, StatusOsemenitve } from 'cry-klikvet-logic/dist/types/teren.mjs'
12
12
  import { RacunZaKnjizbo } from 'cry-klikvet-logic/dist/spremeniZalogo.mjs'
13
13
  import { Dobavnica } from 'cry-klikvet-logic/dist/types/Dobavnica.mjs'
@@ -16,7 +16,7 @@ import { Dobavnica } from 'cry-klikvet-logic/dist/types/Dobavnica.mjs'
16
16
  const DEFAULT_SERVICE_NAME = 'klikvet'
17
17
  let log = new Log(['KLIKVET'])
18
18
 
19
- type Obj = Record<string,any>
19
+ type Obj = Record<string, any>
20
20
 
21
21
  export type KlikvetClientRequest = "ping"
22
22
  | { operation: "ping" }
@@ -25,7 +25,7 @@ export type KlikvetClientRequest = "ping"
25
25
  | { operation: "racuni-isci-create-pipeline", spec: Obj }
26
26
  | { operation: "promet-exec-pipeline", tenant: string, pipeline?: Obj, spec?: Obj }
27
27
  | { operation: "racuni-isci-exec-pipeline", tenant: string, pipeline: Obj, spec?: Obj }
28
- | { operation: "porocilo-racunovodji", tenant: string, odDne: Date, doDne: Date, racuniPravnim?: boolean, racuniOdlozeno?: boolean }
28
+ | { operation: "porocilo-racunovodji", tenant: string, odDne: Date, doDne: Date, racuniPravnim?: boolean, racuniOdlozeno?: boolean, lokacija?: string, skladisca?: string[] }
29
29
  | { operation: "zakljucek-blagajne", tenant: string, odDne: Date; doDne: Date; rounding: number; stevilka?: string; }
30
30
  | { operation: "moj-promet", tenant: string, username: string, odDne: Date, doDne: Date }
31
31
  | { operation: "prodano", tenant: string, username: string, odDne: Date, doDne: Date }
@@ -46,6 +46,8 @@ export type KlikvetClientRequest = "ping"
46
46
  | { operation: "razknjizi-blagovnice", tenant: string, }
47
47
  | { operation: "razknjizi-blagovnico", tenant: string, _id: string }
48
48
  | { operation: "porabe-za-dobavnice", tenant: string, username: string }
49
+ | { operation: "poraba-za-obravnavo", tenant: string, username: string, id: string, }
50
+ | { operation: "porabe-za-obravnave", tenant: string, username: string, }
49
51
  | { operation: "kartica", tenant: string, _id: string, razknjizba: VrstaRazknjizbeZdravila, skladisca_ids: string[] }
50
52
  | { operation: "blagovnice", tenant: string, odDne: Date, doDne: Date }
51
53
  | { operation: "dobava-zdravil", tenant: string, odDne: Date, doDne: Date }
@@ -66,22 +68,21 @@ export type KlikvetClientRequest = "ping"
66
68
  | { operation: "poslji-smse-cepljenim", tenant: string, dan: Date, dniPrej?: number, nacin: string }
67
69
  | { operation: "seznam-narocenih-za-sms", tenant: string, dan: Date, dniPrej?: number, nacin: string }
68
70
  | { operation: "seznam-cepljenj-za-sms", tenant: string, dan: Date, dniPrej?: number }
69
- | { operation: "potrditev-brejosti", tenant: string, _id: string, kdo: string, db?: string , breja: boolean}
70
- | { operation: "v-presusitev", tenant: string, presusitev?: boolean, db?: string, _id:string, kdo: string}
71
- | { operation: "status-osemenitve", tenant: string, db?: string, _id:string, kdo: string, status: StatusOsemenitve }
71
+ | { operation: "potrditev-brejosti", tenant: string, _id: string, kdo: string, db?: string, breja: boolean }
72
+ | { operation: "v-presusitev", tenant: string, presusitev?: boolean, db?: string, _id: string, kdo: string }
73
+ | { operation: "status-osemenitve", tenant: string, db?: string, _id: string, kdo: string, status: StatusOsemenitve }
72
74
  | { operation: "opomba-rejca-osemenitve", tenant: string, db?: string, _id: string, kdo: string, opomba: string }
73
75
  | { operation: "podatki-rejca", tenant: string, rejciGeslo: string, rejciKoda: string }
74
- | { operation: "zaracunaj-dobavnice", tenant: string, dobavnice_ids: string[], lokacija_id: string, naprava_id: string, izdal: string,}
76
+ | { operation: "zaracunaj-dobavnice", tenant: string, dobavnice_ids: string[], lokacija_id: string, naprava_id: string, izdal: string, }
75
77
  | { operation: "anonimiziraj-podatke", tenant: string, letNazaj?: number }
76
78
  | { operation: "razknjizi-dobavnico", tenant: string, _id: string }
77
79
  | { operation: "zdruzi-stranke", tenant: string, v: string, iz: string[] }
78
80
  | { operation: "zdruzi-paciente", tenant: string, v: string, iz: string[] }
79
81
  ;
80
82
 
81
-
82
83
 
83
- function round(num: number, dec = 2)
84
- {
84
+
85
+ function round(num: number, dec = 2) {
85
86
  return Number(num.toFixed(dec))
86
87
  };
87
88
 
@@ -98,25 +99,46 @@ export class KlikvetLogicWorker extends Worker {
98
99
  gsm?: string,
99
100
  }, opts: any) {
100
101
 
101
- if (tenant==="klikvet") tenant=""
102
+ if (tenant === "klikvet") tenant = ""
102
103
  const asService = (tenant
103
104
  ? `${DEFAULT_SERVICE_NAME}-${tenant}`
104
105
  : DEFAULT_SERVICE_NAME);
105
-
106
+
106
107
  super(asService, opts)
107
108
 
108
109
  this.client = new Client({ clientChecksBrokerWithHeartbeat: false });
109
110
  this.gsm = gsm || "";
110
-
111
+
111
112
  console.log("starting klikvet as", asService)
112
113
  }
113
114
 
115
+ async porabaZaObravnavo(mongo: Mongo, data: { tenant: string, id: string, username: string }) {
116
+ console.log('porabaZaObravnavo',data);
117
+
118
+ let nastavitve = await this.dbNastavitve(data.tenant);
119
+ let obravnava = await this.dbFindById<Obravnava>(data.tenant, "obravnave", data.id);
120
+ if (!obravnava) throw new Error("porabaZaObravnavo: ni obravnave " + data?.id);
121
+ let artikel_ids = obravnava.koraki.map(k => (k.postavke || []).map(p => p.artikel_id)).flat(2).filter(a => !!a);
122
+ let artikli = await this.dbFind<ArtikelKarkoli>(data.tenant, "artikli", { _id: { $in: artikel_ids } });
123
+ let poraba = await zapisiPoraboZaObravnavo({ tenant: data.tenant, mongo, obravnava, nastavitve, username: data.username, artikli });
124
+
125
+ console.log('poraba',poraba);
126
+
127
+ return poraba;
128
+ }
129
+
130
+ async porabeZaObravnave(mongo: Mongo, data: { tenant: string, username: string, od?: Date }) {
131
+ let porabe = await zapisiPorabeZaObravnave({ tenant: data.tenant, mongo, username: data.username, od: data.od });
132
+ console.log('porabeZaObravnave',porabe);
133
+ return porabe;
134
+ }
135
+
114
136
  async publishMsg(what: { channel: string, payload: any }) {
115
137
  try {
116
138
  await super.publish(what.channel, what.payload)
117
139
  } catch (err) {
118
140
  console.log('publish failed, continue working', err.message);
119
-
141
+
120
142
  }
121
143
  }
122
144
 
@@ -142,7 +164,7 @@ export class KlikvetLogicWorker extends Worker {
142
164
  console.dir(opts, { depth: 10 });
143
165
  }
144
166
 
145
- async process(data: KlikvetClientRequest) : Promise<any> {
167
+ async process(data: KlikvetClientRequest): Promise<any> {
146
168
  let ret
147
169
  try {
148
170
  await this.resetMongo()
@@ -153,16 +175,16 @@ export class KlikvetLogicWorker extends Worker {
153
175
  }
154
176
 
155
177
  await this.closeMongo()
156
-
178
+
157
179
  return ret;
158
180
  }
159
181
 
160
- async processLogic(data: KlikvetClientRequest) : Promise<any> {
182
+ async processLogic(data: KlikvetClientRequest): Promise<any> {
161
183
 
162
184
  log.debug(`klikvet worker request of type ${typeof data}`, data)
163
-
185
+
164
186
  // console.log('data', data);
165
-
187
+
166
188
  if (data === 'ping') {
167
189
  return 'pong from ' + this.service;
168
190
  }
@@ -170,7 +192,7 @@ export class KlikvetLogicWorker extends Worker {
170
192
  if (typeof data === "string" && (data as string)?.match?.(/^ping/i)) {
171
193
  let ms = (data as string).match(/\d+/)?.[0]
172
194
  console.log('ms', ms);
173
-
195
+
174
196
  if (ms) await sleep(parseInt(ms))
175
197
  return 'pong from ' + this.service + (ms ? ` after ${ms}ms` : '')
176
198
  }
@@ -178,10 +200,10 @@ export class KlikvetLogicWorker extends Worker {
178
200
  if (data.operation === 'ping') {
179
201
  return { ping: 'pong' }
180
202
  }
181
-
203
+
182
204
  assert(data.operation, 'must specify operation')
183
205
  assert(this.client, 'missing EbusClient')
184
-
206
+
185
207
  if (data.operation === 'promet-get-config') {
186
208
  return promet;
187
209
  }
@@ -190,12 +212,12 @@ export class KlikvetLogicWorker extends Worker {
190
212
  assert(data.spec, 'must specify data.spec')
191
213
  return promet.createAggregationPipeline(data.spec)
192
214
  }
193
-
215
+
194
216
  if (data.operation === 'racuni-isci-create-pipeline') {
195
217
  assert(data.spec, 'must specify data.spec')
196
218
  return racuni.isci.createAggregationPipeline(data.spec)
197
219
  }
198
-
220
+
199
221
  if (data.operation === 'promet-exec-pipeline') {
200
222
  assert(data.tenant, 'must specify tenant')
201
223
  assert(data.pipeline || data.spec, 'must specify data.spec or data.pipeline')
@@ -219,6 +241,10 @@ export class KlikvetLogicWorker extends Worker {
219
241
  assert(data.odDne, 'must odDne')
220
242
  assert(data.doDne, 'must doDne')
221
243
 
244
+ if (data.lokacija) {
245
+ data.skladisca = await this.vsaSkladiscaLokacije(data.lokacija, data.tenant);
246
+ }
247
+
222
248
  let pipeline = racunovodji.createAggregationPipeline(data)
223
249
  let podatki = await racunovodji.execPipeline(pipeline.pipeline, data.tenant)
224
250
  let prviZadnji = await racunovodji.getFirstLastBills(data.tenant, pipeline.match)
@@ -234,7 +260,7 @@ export class KlikvetLogicWorker extends Worker {
234
260
  let spremembaZaloge = await spremembaZalogeZaObdobje({ ...data, poVrstah: true })
235
261
  let spremembaKonsignacije = await spremembaZalogeZaObdobje({ ...data, poVrstah: true, samoKonsignacija: true })
236
262
  let vsotaDobav = await VsotaDobavZaObdobje({ ...data })
237
-
263
+
238
264
  return { podatki, racuniOdlozeno, racuniPravnim, kategorije, stornirani, placila, zaloga: { pred, po }, konsignacija: { pred: predKonsignacija, po: poKonsignacija }, spremembaZaloge, spremembaKonsignacije, vsotaDobav, prviZadnji };
239
265
  }
240
266
 
@@ -303,7 +329,7 @@ export class KlikvetLogicWorker extends Worker {
303
329
  assert(data.certPass, "must specify certPass")
304
330
  assert(this.client)
305
331
  let timeoutError = ""
306
-
332
+
307
333
  try {
308
334
  timeoutError = "furs/cert: FURS podsistem se ni odzval."
309
335
  let res: { certSerial: string, certTaxNo: number, certName: string, certValidUntil: Date, certIssuer: string } | undefined = (await this.client.request('durs', { operation: 'add cert', data: { cert: data.certBase64, password: data.certPass } }, { receiveTimeout: 2000 }));
@@ -312,7 +338,7 @@ export class KlikvetLogicWorker extends Worker {
312
338
  if (!res) {
313
339
  return { certMessage: "furs/cert ni nič vrnil", certOk: false }
314
340
  }
315
-
341
+
316
342
  timeoutError = "furs/cert: spodletelo je pisanje v bazo."
317
343
 
318
344
  await this.client.request('db', {
@@ -321,7 +347,7 @@ export class KlikvetLogicWorker extends Worker {
321
347
  db: data.tenant,
322
348
  query: { serijskaStevilka: res.certSerial }
323
349
  });
324
-
350
+
325
351
  let req = {
326
352
  operation: 'upsert',
327
353
  collection: 'certifikati',
@@ -352,15 +378,15 @@ export class KlikvetLogicWorker extends Worker {
352
378
  cert,
353
379
  tenant: data.tenant,
354
380
  };
355
-
381
+
356
382
  log.info("furs-reg-cert returns", ret)
357
-
383
+
358
384
  return ret;
359
385
 
360
386
  } catch (err) {
361
387
 
362
388
  // console.log('err',err);
363
-
389
+
364
390
  if (err.reason === "reject" && err.data.message && /Invalid password/gi.test(err.data.message)) {
365
391
  return {
366
392
  certMessage: "Napačno geslo.",
@@ -386,19 +412,19 @@ export class KlikvetLogicWorker extends Worker {
386
412
 
387
413
  assert(data.certId, "must specify certId")
388
414
  assert(data.taxNo, "must specify taxNo")
389
-
415
+
390
416
  log.debug('removing cert', data);
391
417
 
392
418
  let result = await this.client.request('durs',
393
419
  { operation: 'remove cert', data: { taxNo: data.taxNo, } }, { receiveTimeout: 2000 });
394
420
 
395
421
  log.trace('cert removed', result);
396
-
422
+
397
423
  return {
398
424
  ok: true,
399
425
  result: result
400
426
  };
401
-
427
+
402
428
  }
403
429
 
404
430
  if (data.operation === "furs-register-premise") {
@@ -511,7 +537,7 @@ export class KlikvetLogicWorker extends Worker {
511
537
  }, 2000);
512
538
  return res
513
539
  };
514
-
540
+
515
541
  if (data.operation === "furs-register-all-invoices") {
516
542
  let all = await this.registerAllInvoices(data);
517
543
  setTimeout(async () => {
@@ -544,7 +570,7 @@ export class KlikvetLogicWorker extends Worker {
544
570
  assert(data.tenant, "must specify tenant")
545
571
  return await this.razknjiziBlagovnice(data);
546
572
  };
547
-
573
+
548
574
  if (data.operation === "porabe-za-dobavnice") {
549
575
  assert(data.tenant, "must specify tenant")
550
576
  let ret = await this.porabeZaDobavnice(data);
@@ -552,6 +578,21 @@ export class KlikvetLogicWorker extends Worker {
552
578
  return ret;
553
579
  };
554
580
 
581
+ if (data.operation === "poraba-za-obravnavo") {
582
+ assert(data.tenant, "must specify tenant");
583
+ assert(data.username, "must specify username");
584
+ assert(data.id, "must specify id");
585
+ let ret = await this.porabaZaObravnavo(this.mongo!, data);
586
+ return ret;
587
+ };
588
+
589
+ if (data.operation === "porabe-za-obravnave") {
590
+ assert(data.tenant, "must specify tenant");
591
+ assert(data.username, "must specify username");
592
+ let ret = await this.porabeZaObravnave(this.mongo!, data);
593
+ return ret;
594
+ };
595
+
555
596
  if (data.operation === "razknjizi-dobavnico") {
556
597
  assert(data._id, "must specify _id of Dobavnica")
557
598
  assert(data.tenant, "must specify tenant")
@@ -800,7 +841,7 @@ export class KlikvetLogicWorker extends Worker {
800
841
  assert(data.tenant, "must specify tenant")
801
842
  assert(["demo", "demo2", "dev", "test"].includes(data.tenant), "cnly valid for demo, dev, test");
802
843
  assert(data.letNazaj, "must specify letNazaj");
803
-
844
+
804
845
  return await anonimizirajPodatke(createMongoForAnonimizacija(data.tenant), parseInt(data.letNazaj.toString() || "1"));
805
846
  };
806
847
 
@@ -808,7 +849,7 @@ export class KlikvetLogicWorker extends Worker {
808
849
  assert(data.tenant, "must specify tenant")
809
850
  assert(data.v, "must specify v");
810
851
  assert(data.iz, "must specify iz");
811
-
852
+
812
853
  return await this.zdruziStranke(data);
813
854
  };
814
855
 
@@ -816,7 +857,7 @@ export class KlikvetLogicWorker extends Worker {
816
857
  assert(data.tenant, "must specify tenant")
817
858
  assert(data.v, "must specify v");
818
859
  assert(data.iz, "must specify iz");
819
-
860
+
820
861
  return await this.zdruziPaciente(data);
821
862
  };
822
863
 
@@ -1032,530 +1073,479 @@ export class KlikvetLogicWorker extends Worker {
1032
1073
  return moje?.[0]
1033
1074
  }
1034
1075
 
1076
+ async vsaSkladiscaLokacije(lokacija_id: string, tenant: string) {
1077
+ let vsa: Skladisce[] = (await this.dbFind(tenant, "skladisca", { _deleted: { $exists: false } })) as Skladisce[];
1078
+ return vsa.filter(s => s.lokacija_id.toString() === lokacija_id)?.map(s => s._id);
1079
+ }
1080
+
1035
1081
  async porabeZaDobavnice(data: { tenant: string, username: string }) {
1036
1082
 
1037
- let nastavitve = await this.dbNastavitve(data.tenant);
1038
- let lokacije = await this.dbFind<Lokacija>(data.tenant, "lokacije", {});
1039
- let od = new Date(new Date().valueOf() - 365 * 24 * 60 * 60 * 1000);
1083
+ let ret = await zapisiPorabeZaDobavnice({
1084
+ mongo: this.mongo!,
1085
+ tenant: data.tenant,
1086
+ username: data.username,
1087
+ });
1088
+ console.log('porabeZaDobavnice', ret);
1089
+ return ret;
1040
1090
 
1041
- let nerazknijzene = await this.dbFind<Dobavnica>(data.tenant, "dobavnice", {
1042
- datumDokumenta: { $gte: od },
1043
- status: { $in: ["izdana", "zaračunana"] },
1044
- poraba_id: { $exists: false },
1045
- razknjizbaPreskocena: { $exists: false },
1046
- _deleted: { $exists: false }
1047
- }, { sort: { datumDokumenta: 1 } });
1091
+ }
1048
1092
 
1049
- let artikel_ids = dedup(nerazknijzene.map(d => d.postavke.map(p => p.artikel_id?.toString())).flat());
1093
+ async razknjiziBlagovnice(data: { tenant: string }) {
1094
+ this.mongo!.emitPublishEvents(false);
1095
+ this.mongo!.useAuditing(false)
1096
+ this.mongo!.setDb(data.tenant);
1097
+ this.mongo!.setAudit({ tenant: data.tenant, app: "klikvet/razknjiziBlagovnice" });
1050
1098
 
1051
- let artikli = await this.dbFind<ArtikelOsnova>(data.tenant, "artikli", {
1052
- _id: { $in: artikel_ids }
1053
- })
1099
+ let od = new Date(new Date().valueOf() - 60 * 24 * 60 * 60 * 1000);
1054
1100
 
1101
+ // poišči tiste, ki bi morale že biti razknjižene, pa niso
1102
+ {
1103
+ let od = new Date(new Date().valueOf() - 3 * 60 * 24 * 60 * 60 * 1000);
1104
+ let vpisane = await this.dbFind<Blagovnica>(data.tenant, "blagovnice", { datum: { $gte: od } }, { project: { _id: 1, status: 1 } });
1105
+ let idjiVpisanih = vpisane.map(b => b._id.toString());
1106
+
1107
+ let zaPovrnit = await this.dbFind<Blagovnica>(data.tenant, "odprteBlagovnice", { _deleted: { $ne: "hack" }, status: "zaključena", datum: { $gte: od }, _id: { $nin: idjiVpisanih } }, { project: { status: 1, dokumentDobavitelja: 1, vrsta: 1 } });
1108
+
1109
+ for await (let b of zaPovrnit) {
1110
+ console.log("vračam blagovnico v razkljižno", data.tenant, b)
1111
+ await this.dbUpsert(data.tenant, "odprteBlagovnice", b._id, { razknjizena: undefined, _deleted: undefined, _vrnjenoVRazknjizbo: new Date() });
1112
+ }
1113
+ }
1114
+
1115
+ let nerazknijzene = await this.dbFind<Dobavnica>(data.tenant, "odprteBlagovnice",
1116
+ { datum: { $gte: od }, status: "zaključena", razknjizena: { $exists: false } },
1117
+ { sort: { datum: 1 } }
1118
+ );
1055
1119
  let vse = 0, razknjizene = 0
1056
1120
  let napake = []
1057
1121
  for await (let dobavnica of nerazknijzene) {
1058
- let lokacija = lokacije.find(l => l._id.toString() === dobavnica.lokacija_id.toString());
1059
- if (!lokacija) continue;
1060
- let zaPorabo = vrniPopravekDobavniceCeNiZaPorabo({
1061
- dobavnica,
1062
- nastavitve,
1063
- lokacija
1064
- })
1065
- if (zaPorabo === false) continue;
1066
- if (zaPorabo && typeof zaPorabo === "object" && zaPorabo.razknjizbaPreskocena) {
1067
- await this.dbUpsert(data.tenant, "dobavnice", dobavnica._id, zaPorabo );
1068
- continue
1069
- }
1070
- if (!dobavnica.lokacija_id) console.error("dobavnica nima lokacije", dobavnica._id, dobavnica.stevilka)
1071
1122
  try {
1072
- let skladisce_id = dobavnica.skladisce_id || ((await this.skladisceLokacije(dobavnica.lokacija_id, data.tenant))._id);
1073
1123
  vse++
1074
- let poraba = await porabaZaDobavnico({
1075
- dobavnica,
1076
- nastavitve,
1077
- skladisce_id,
1078
- lokacija_id: dobavnica.lokacija_id,
1079
- username: data.username,
1080
- artikli: arrayToObject(artikli, "_id"),
1081
- });
1124
+ await this.razknjiziBlagovnico(dobavnica._id.toString(), data.tenant)
1125
+ razknjizene++
1126
+ } catch (err) {
1127
+ napake.push(err)
1128
+ }
1129
+ }
1130
+ return { ok: vse === razknjizene, vse, razknjizene, napake }
1131
+ }
1082
1132
 
1083
- console.log('poraba', poraba);
1133
+ async razknjiziDobavnice(data: { tenant: string }) {
1084
1134
 
1135
+ this.mongo!.emitPublishEvents(false)
1136
+ this.mongo!.useAuditing(false)
1137
+ this.mongo!.setDb(data.tenant)
1138
+ this.mongo!.setAudit({ tenant: data.tenant, app: "klikvet/razknjiziDobavnice" })
1085
1139
 
1086
- if (poraba) {
1087
- poraba.status = "zaključena"
1088
- let p = await this.dbUpsert(data.tenant, "odprteBlagovnice", poraba._id, poraba);
1089
- await this.dbUpsert(data.tenant, "dobavnice", dobavnica._id, { poraba_id: p._id, poraba_sestavljena: new Date() });
1090
- }
1091
- if (poraba === null) {
1092
- await this.dbUpsert(data.tenant, "dobavnice", dobavnica._id, { poraba_id: null, poraba_preskocena: new Date() });
1093
- }
1140
+ let od = new Date(new Date().valueOf() - 60 * 24 * 60 * 60 * 1000)
1141
+ let nerazknijzene = await this.dbFind<Dobavnica>(data.tenant, "dobavnice",
1142
+ {
1143
+ datum: { $gte: od }, status: "izdana",
1144
+ razknjizena: { $not: { $type: "date" } },
1145
+ razknjizbaPreskocena: { $exists: false },
1146
+ },
1147
+ { sort: { datum: 1 } }
1148
+ );
1149
+ let vse = 0, razknjizene = 0
1150
+ let napake = []
1151
+ for await (let blagovnica of nerazknijzene) {
1152
+ try {
1153
+ vse++
1154
+ await this.razknjiziDobavnico(blagovnica._id.toString(), data.tenant)
1094
1155
  razknjizene++
1095
1156
  } catch (err) {
1096
1157
  napake.push(err)
1097
1158
  }
1098
1159
  }
1099
1160
  return { ok: vse === razknjizene, vse, razknjizene, napake }
1161
+
1100
1162
  }
1101
1163
 
1102
- async razknjiziBlagovnice(data: { tenant: string })
1103
- {
1104
- this.mongo!.emitPublishEvents(false);
1105
- this.mongo!.useAuditing(false)
1106
- this.mongo!.setDb(data.tenant);
1107
- this.mongo!.setAudit({ tenant: data.tenant, app: "klikvet/razknjiziBlagovnice" });
1164
+ // async razknjiziBlagovnico(_id, tenant)
1165
+ // {
1166
+ // let nastavitve = await dbNastavitve(tenant);
1167
+ // this.mongo!.setDb(tenant)
1168
+ // this.mongo!.setAudit({ tenant, app: "klikvet/razknjiziBlagovnico/1" })
1108
1169
 
1109
- let od = new Date(new Date().valueOf() - 60 * 24 * 60 * 60 * 1000);
1170
+ // await logic.zakljuciBlagovnico(_id, this.mongo);
1110
1171
 
1111
- // poišči tiste, ki bi morale že biti razknjižene, pa niso
1112
- {
1113
- let od = new Date(new Date().valueOf() - 3 * 60 * 24 * 60 * 60 * 1000);
1114
- let vpisane = await this.dbFind<Blagovnica>(data.tenant, "blagovnice", { datum: { $gte: od } }, { project: { _id: 1, status: 1 } });
1115
- let idjiVpisanih = vpisane.map(b => b._id.toString());
1172
+ // /** @type {Blagovnica}} */
1173
+ // let blagovnica = (/** @type {Blagovnica} */ await this.dbFindById(tenant, "blagovnice", _id))
1174
+ // if (!blagovnica) throw new Error(`ne morem razknjižiti blagovnice, ki je ni: ${_id}, tenant ${tenant}`)
1116
1175
 
1117
- let zaPovrnit = await this.dbFind<Blagovnica>(data.tenant, "odprteBlagovnice", { _deleted: { $ne: "hack" }, status: "zaključena", datum: { $gte: od }, _id: { $nin: idjiVpisanih } }, { project: { status: 1, dokumentDobavitelja: 1, vrsta: 1 } });
1176
+ // this.mongo!.setDb(tenant)
1177
+ // this.mongo!.setAudit({ tenant, app: "klikvet/razknjiziBlagovnico/2" })
1118
1178
 
1119
- for await (let b of zaPovrnit) {
1120
- console.log("vračam blagovnico v razkljižno", data.tenant, b)
1121
- await this.dbUpsert(data.tenant, "odprteBlagovnice", b._id, { razknjizena: undefined, _deleted: undefined, _vrnjenoVRazknjizbo: new Date() });
1122
- }
1123
- }
1179
+ // await logic.spremeniZalogoNaPodlagiBlagovnice(blagovnica, nastavitve, this.mongo);
1180
+ // await pobrisiZalogoNaDan(tenant, [ blagovnica.datum ]);
1181
+ // }
1182
+
1183
+ async razknjiziBlagovnico(_id: string, tenant: string) {
1124
1184
 
1125
- let nerazknijzene = await this.dbFind<Dobavnica>(data.tenant, "odprteBlagovnice",
1126
- { datum: { $gte: od }, status: "zaključena", razknjizena: { $exists: false } },
1127
- { sort: { datum: 1 } }
1128
- );
1129
- let vse = 0, razknjizene = 0
1130
- let napake = []
1131
- for await (let dobavnica of nerazknijzene) {
1185
+ if (this.razknjizujem) return;
1186
+ this.razknjizujem = true;
1132
1187
  try {
1133
- vse++
1134
- await this.razknjiziBlagovnico(dobavnica._id.toString(), data.tenant)
1135
- razknjizene++
1188
+ this.mongo!.emitPublishEvents(false)
1189
+ this.mongo!.useAuditing(false)
1190
+ this.mongo!.setDb(tenant)
1191
+ this.mongo!.setAudit({ tenant, app: "klikvet/razknjiziBlagovnico" })
1192
+
1193
+ let blagovnica = await razknjiziBlagovnico(_id, this.mongo as any);
1194
+ this.razknjizujem = false;
1195
+ return blagovnica
1136
1196
  } catch (err) {
1137
- napake.push(err)
1197
+ console.error("razknjiziBlagovnico", tenant)
1138
1198
  }
1199
+ this.razknjizujem = false;
1200
+ return undefined
1139
1201
  }
1140
- return { ok: vse === razknjizene, vse, razknjizene, napake }
1141
- }
1142
1202
 
1143
- async razknjiziDobavnice(data: { tenant: string }) {
1144
-
1145
- this.mongo!.emitPublishEvents(false)
1146
- this.mongo!.useAuditing(false)
1147
- this.mongo!.setDb(data.tenant)
1148
- this.mongo!.setAudit({ tenant: data.tenant, app: "klikvet/razknjiziDobavnice" })
1149
-
1150
- let od = new Date(new Date().valueOf() - 60 * 24 * 60 * 60 * 1000)
1151
- let nerazknijzene = await this.dbFind<Dobavnica>(data.tenant, "dobavnice",
1152
- {
1153
- datum: { $gte: od }, status: "izdana",
1154
- razknjizena: { $not: { $type: "date" } },
1155
- razknjizbaPreskocena: { $exists: false },
1156
- },
1157
- { sort: { datum: 1 } }
1158
- );
1159
- let vse = 0, razknjizene = 0
1160
- let napake = []
1161
- for await (let blagovnica of nerazknijzene) {
1203
+ async razknjiziDobavnico(_id: string, tenant: string) {
1204
+ if (this.razknjizujem) return;
1205
+ this.razknjizujem = true;
1162
1206
  try {
1163
- vse++
1164
- await this.razknjiziDobavnico(blagovnica._id.toString(), data.tenant)
1165
- razknjizene++
1207
+ this.mongo!.setDb(tenant)
1208
+ this.mongo!.setAudit({ tenant, app: "klikvet/razknjiziDobavnico" })
1209
+ let dobavnica = await razknjiziDobavnico(_id, this.mongo as any);
1210
+ this.razknjizujem = false;
1211
+ return dobavnica
1166
1212
  } catch (err) {
1167
- napake.push(err)
1213
+ console.error("razknjiziDobavnico", tenant, err?.message || err)
1168
1214
  }
1169
- }
1170
- return { ok: vse === razknjizene, vse, razknjizene, napake }
1171
-
1172
- }
1173
-
1174
- // async razknjiziBlagovnico(_id, tenant)
1175
- // {
1176
- // let nastavitve = await dbNastavitve(tenant);
1177
- // this.mongo!.setDb(tenant)
1178
- // this.mongo!.setAudit({ tenant, app: "klikvet/razknjiziBlagovnico/1" })
1179
-
1180
- // await logic.zakljuciBlagovnico(_id, this.mongo);
1181
-
1182
- // /** @type {Blagovnica}} */
1183
- // let blagovnica = (/** @type {Blagovnica} */ await this.dbFindById(tenant, "blagovnice", _id))
1184
- // if (!blagovnica) throw new Error(`ne morem razknjižiti blagovnice, ki je ni: ${_id}, tenant ${tenant}`)
1185
-
1186
- // this.mongo!.setDb(tenant)
1187
- // this.mongo!.setAudit({ tenant, app: "klikvet/razknjiziBlagovnico/2" })
1188
-
1189
- // await logic.spremeniZalogoNaPodlagiBlagovnice(blagovnica, nastavitve, this.mongo);
1190
- // await pobrisiZalogoNaDan(tenant, [ blagovnica.datum ]);
1191
- // }
1192
-
1193
- async razknjiziBlagovnico(_id: string, tenant: string) {
1194
-
1195
- if (this.razknjizujem) return;
1196
- this.razknjizujem = true;
1197
- try {
1198
- this.mongo!.emitPublishEvents(false)
1199
- this.mongo!.useAuditing(false)
1200
- this.mongo!.setDb(tenant)
1201
- this.mongo!.setAudit({ tenant, app: "klikvet/razknjiziBlagovnico" })
1202
-
1203
- let blagovnica = await razknjiziBlagovnico(_id, this.mongo as any);
1204
1215
  this.razknjizujem = false;
1205
- return blagovnica
1206
- } catch (err) {
1207
- console.error("razknjiziBlagovnico", tenant)
1208
- }
1209
- this.razknjizujem = false;
1210
- return undefined
1211
- }
1212
-
1213
- async razknjiziDobavnico(_id: string, tenant: string) {
1214
- if (this.razknjizujem) return;
1215
- this.razknjizujem = true;
1216
- try {
1217
- this.mongo!.setDb(tenant)
1218
- this.mongo!.setAudit({ tenant, app: "klikvet/razknjiziDobavnico" })
1219
- let dobavnica = await razknjiziDobavnico(_id, this.mongo as any);
1220
- this.razknjizujem = false;
1221
- return dobavnica
1222
- } catch (err) {
1223
- console.error("razknjiziDobavnico", tenant, err?.message || err)
1216
+ return undefined
1224
1217
  }
1225
- this.razknjizujem = false;
1226
- return undefined
1227
- }
1228
1218
 
1229
- async registerAllInvoices(data: { tenant: string, env: string, }) {
1230
- if (this.razknjizujem) return { nall: 0, nok: 0, napake: ["worker že razknjižuje"] };
1231
- this.razknjizujem = true;
1232
- try {
1233
- assert(data.tenant, "must specify tenant")
1234
-
1235
- let err = null;
1236
- let napake = new Set()
1219
+ async registerAllInvoices(data: { tenant: string, env: string, }) {
1220
+ if (this.razknjizujem) return { nall: 0, nok: 0, napake: ["worker že razknjižuje"] };
1221
+ this.razknjizujem = true;
1237
1222
  try {
1223
+ assert(data.tenant, "must specify tenant")
1238
1224
 
1239
- err = "Podsistem db ni dosegljiv."
1225
+ let err = null;
1226
+ let napake = new Set()
1227
+ try {
1240
1228
 
1241
- this.mongo!.setDb(data.tenant)
1242
- this.mongo!.setAudit({ tenant: data.tenant, app: "klikvet/registerAllInvoices" })
1229
+ err = "Podsistem db ni dosegljiv."
1243
1230
 
1244
- let myquery = { eor: null, negotovinski: { $ne: true }, leto: { $gte: 2022 } };
1245
- let env = data.env || (await this.mongo!.findOne<Nastavitve>("nastavitve", {}))?.okolje || "error"
1231
+ this.mongo!.setDb(data.tenant)
1232
+ this.mongo!.setAudit({ tenant: data.tenant, app: "klikvet/registerAllInvoices" })
1246
1233
 
1247
- let all = await this.mongo!.find<Racun>("racuni", myquery, { project: { _id: 1 }, limit: 1000, })
1248
- err = "Napaka pri potrjevanju računov."
1234
+ let myquery = { eor: null, negotovinski: { $ne: true }, leto: { $gte: 2022 } };
1235
+ let env = data.env || (await this.mongo!.findOne<Nastavitve>("nastavitve", {}))?.okolje || "error"
1249
1236
 
1250
- let n = 0;
1251
- try {
1252
- for await (let r of all) {
1253
- let res = await this.registerInvoice({ tenant: data.tenant, env, _id: r._id.toString() }, true);
1254
- if (res instanceof Error || typeof res === "string") {
1255
- console.error("cannot register invoice (1)",data.tenant,r._id,res)
1256
- } else {
1257
- if (res.eor) n++;
1258
- if (res.fursError) napake.add(res.fursError)
1237
+ let all = await this.mongo!.find<Racun>("racuni", myquery, { project: { _id: 1 }, limit: 1000, })
1238
+ err = "Napaka pri potrjevanju računov."
1239
+
1240
+ let n = 0;
1241
+ try {
1242
+ for await (let r of all) {
1243
+ let res = await this.registerInvoice({ tenant: data.tenant, env, _id: r._id.toString() }, true);
1244
+ if (res instanceof Error || typeof res === "string") {
1245
+ console.error("cannot register invoice (1)", data.tenant, r._id, res)
1246
+ } else {
1247
+ if (res.eor) n++;
1248
+ if (res.fursError) napake.add(res.fursError)
1249
+ }
1259
1250
  }
1251
+ } catch (e) {
1252
+ err = e.message;
1253
+ console.log('err', err);
1254
+ throw new Error()
1260
1255
  }
1261
- } catch (e) {
1262
- err = e.message;
1263
- console.log('err', err);
1264
- throw new Error()
1265
- }
1266
1256
 
1267
- this.razknjizujem = false;
1268
- return { nall: all.length, nok: n, napake: [...napake] };
1257
+ this.razknjizujem = false;
1258
+ return { nall: all.length, nok: n, napake: [...napake] };
1269
1259
 
1260
+ } catch (err) {
1261
+ console.error('registerAllInvoices', err);
1262
+ this.razknjizujem = false;
1263
+ throw new Error(err);
1264
+ }
1270
1265
  } catch (err) {
1271
- console.error('registerAllInvoices', err);
1266
+ console.error("registerAllInvoices", data.tenant, err?.message || err)
1272
1267
  this.razknjizujem = false;
1273
- throw new Error(err);
1268
+ return { nall: 0, nok: 0, napake: [err.message || err] };
1274
1269
  }
1275
- } catch (err) {
1276
- console.error("registerAllInvoices", data.tenant, err?.message || err)
1277
- this.razknjizujem = false;
1278
- return { nall: 0, nok: 0, napake: [err.message || err] };
1279
1270
  }
1280
- }
1281
1271
 
1282
- async registerCert(db: string, davcnaStevilka: string) {
1283
- let cert = (await this.client?.request('db', {
1284
- operation: 'findOne',
1285
- db,
1286
- collection: "certifikati",
1287
- query: { davcnaStevilka }
1288
- }, { receiveTimeout: 3000 })) as { certBase64: string, certPass: string };
1272
+ async registerCert(db: string, davcnaStevilka: string) {
1273
+ let cert = (await this.client?.request('db', {
1274
+ operation: 'findOne',
1275
+ db,
1276
+ collection: "certifikati",
1277
+ query: { davcnaStevilka }
1278
+ }, { receiveTimeout: 3000 })) as { certBase64: string, certPass: string };
1289
1279
 
1290
- let res = (await this.client?.request('durs', { operation: 'add cert', data: { cert: cert.certBase64, password: cert.certPass } }, { receiveTimeout: 4000 }));
1291
- return res
1292
- }
1293
-
1294
- async registerInvoice(data: { env:string, tenant: string, _id: string}, kasneje = false) {
1295
- this.mongo!.setAudit({ tenant: data.tenant, app: "klikvet/registerInvoice" })
1296
-
1297
- assert(data._id, "must specify _id of racun")
1298
- assert(["error", "production", "test"].includes(data.env), "must specify env")
1299
- assert(data.tenant, "must specify tenant")
1300
-
1301
- let timeoutError = "";
1302
- try {
1303
- // poišči račun
1304
- timeoutError = "Db podsistem se ni odzval."
1305
- let racun = await this.dbFindById<Racun>(data.tenant, "racuni", data._id)
1306
- if (!racun) return `registerInvoice for ${data.tenant}: ni računa ${data._id}`
1307
- if (racun.negotovinski) return "negotovinski račun ne bo fiskaliziran";
1308
-
1309
- let blagajna = await this.dbFindById<Blagajna>(data.tenant, "blagajne", racun.blagajna_id)
1310
- if (!blagajna) throw new Error("cannot locate blagajna: " + racun.blagajna_id)
1311
- let poslovalnica = await this.dbFindById<Poslovalnica>(data.tenant, "poslovalnice", blagajna.poslovalnica_id)
1312
- if (!blagajna) throw new Error("cannot locate poslovalnica: " + racun.blagajna_id)
1313
- let veterina = await this.dbFindById<Nastavitve>(data.tenant, "nastavitve", poslovalnica.veterina_id)
1314
- if (!veterina) throw new Error("cannot locate poslovalnica: " + poslovalnica.veterina_id)
1315
- if (!racun.izdalDs) throw new Error("Uporabnik verjetno nima vpisane davčne številke.")
1316
-
1317
- // če gre za popravek računa, poveži izvorni račun na ta popravek
1318
- if (racun.predhodniRacun && racun.predhodniRacun._id ) {
1319
- this.dbUpdateById(data.tenant, "racuni", racun.predhodniRacun._id.toString(), {
1320
- naslednjiRacun: {
1321
- _id: data._id.toString(),
1322
- datum: racun.datum,
1323
- stevilka: racun.stevilka,
1324
- }
1325
- })
1326
- }
1280
+ let res = (await this.client?.request('durs', { operation: 'add cert', data: { cert: cert.certBase64, password: cert.certPass } }, { receiveTimeout: 4000 }));
1281
+ return res
1282
+ }
1327
1283
 
1328
- let TaxNumber = (veterina.dsCertifikata || veterina.davcnaStevilka)
1329
- TaxNumber = parseInt(TaxNumber.toString().match(/\d+/)?.toString()||"0");
1330
- if (!TaxNumber) return new Error("no TaxNumber for "+data.tenant)
1331
-
1332
- let Invoice = {
1333
- TaxNumber,
1334
- IssueDateTime: new Date(racun.datum),
1335
- NumberingStructure: "B",
1336
- InvoiceIdentifier: {
1337
- BusinessPremiseID: poslovalnica.koda,
1338
- ElectronicDeviceID: blagajna.nazivZaIzpis,
1339
- InvoiceNumber: racun.stRacuna.toString(),
1340
- },
1341
- InvoiceAmount: round(racun.mpc),
1342
- PaymentAmount: round(racun.mpc),
1343
- TaxesPerSeller: [{
1344
- VAT: racun.davki.map(d => {
1345
- return {
1346
- TaxRate: round(d.dst * 100),
1347
- TaxableAmount: round(d.osnova),
1348
- TaxAmount: round(d.davek),
1349
- }
1350
- })
1351
- }],
1352
- OperatorTaxNumber: Number(racun.izdalDs),
1353
- //ProtectedID: null,
1354
- SubsequentSubmit: kasneje,
1355
- // ReferenceInvoice: [{
1356
- // ReferenceInvoiceIdentifier: {
1357
- // BusinessPremiseID: "36CF",
1358
- // ElectronicDeviceID: "BLAG2",
1359
- // InvoiceNumber: "144"
1360
- // },
1361
- // ReferenceInvoiceIssueDateTime: new Date()
1362
- // }],
1363
- };
1364
- if (racun.predhodniRacun) {
1365
- let s = racun.predhodniRacun.stevilka.split("-");
1366
- (Invoice as any).ReferenceInvoice = [{
1367
- ReferenceInvoiceIdentifier: {
1368
- BusinessPremiseID: s[2],
1369
- ElectronicDeviceID: s[1],
1370
- InvoiceNumber: s[0],
1371
- },
1372
- ReferenceInvoiceIssueDateTime: racun.predhodniRacun.datum,
1373
- }];
1374
- }
1375
- let DursEnv = veterina.okolje;
1376
- if (DursEnv !== data.env) throw new Error(`data.env (${data.env}) !== veterina.okolje (${veterina.okolje})`);
1284
+ async registerInvoice(data: { env: string, tenant: string, _id: string }, kasneje = false) {
1285
+ this.mongo!.setAudit({ tenant: data.tenant, app: "klikvet/registerInvoice" })
1377
1286
 
1378
- // console.dir(Invoice, {depth:10});
1287
+ assert(data._id, "must specify _id of racun")
1288
+ assert(["error", "production", "test"].includes(data.env), "must specify env")
1289
+ assert(data.tenant, "must specify tenant")
1379
1290
 
1380
- // davčno potrdi račun
1381
- let furs: { error?: string, EOR?: string, ZOI?: string, QR?: string } = {};
1382
- let napaka : string|undefined = ""
1291
+ let timeoutError = "";
1383
1292
  try {
1293
+ // poišči račun
1294
+ timeoutError = "Db podsistem se ni odzval."
1295
+ let racun = await this.dbFindById<Racun>(data.tenant, "racuni", data._id)
1296
+ if (!racun) return `registerInvoice for ${data.tenant}: ni računa ${data._id}`
1297
+ if (racun.negotovinski) return "negotovinski račun ne bo fiskaliziran";
1298
+
1299
+ let blagajna = await this.dbFindById<Blagajna>(data.tenant, "blagajne", racun.blagajna_id)
1300
+ if (!blagajna) throw new Error("cannot locate blagajna: " + racun.blagajna_id)
1301
+ let poslovalnica = await this.dbFindById<Poslovalnica>(data.tenant, "poslovalnice", blagajna.poslovalnica_id)
1302
+ if (!blagajna) throw new Error("cannot locate poslovalnica: " + racun.blagajna_id)
1303
+ let veterina = await this.dbFindById<Nastavitve>(data.tenant, "nastavitve", poslovalnica.veterina_id)
1304
+ if (!veterina) throw new Error("cannot locate poslovalnica: " + poslovalnica.veterina_id)
1305
+ if (!racun.izdalDs) throw new Error("Uporabnik verjetno nima vpisane davčne številke.")
1306
+
1307
+ // če gre za popravek računa, poveži izvorni račun na ta popravek
1308
+ if (racun.predhodniRacun && racun.predhodniRacun._id) {
1309
+ this.dbUpdateById(data.tenant, "racuni", racun.predhodniRacun._id.toString(), {
1310
+ naslednjiRacun: {
1311
+ _id: data._id.toString(),
1312
+ datum: racun.datum,
1313
+ stevilka: racun.stevilka,
1314
+ }
1315
+ })
1316
+ }
1384
1317
 
1385
- timeoutError = "FURS podsistem se ni odzval."
1318
+ let TaxNumber = (veterina.dsCertifikata || veterina.davcnaStevilka)
1319
+ TaxNumber = parseInt(TaxNumber.toString().match(/\d+/)?.toString() || "0");
1320
+ if (!TaxNumber) return new Error("no TaxNumber for " + data.tenant)
1321
+
1322
+ let Invoice = {
1323
+ TaxNumber,
1324
+ IssueDateTime: new Date(racun.datum),
1325
+ NumberingStructure: "B",
1326
+ InvoiceIdentifier: {
1327
+ BusinessPremiseID: poslovalnica.koda,
1328
+ ElectronicDeviceID: blagajna.nazivZaIzpis,
1329
+ InvoiceNumber: racun.stRacuna.toString(),
1330
+ },
1331
+ InvoiceAmount: round(racun.mpc),
1332
+ PaymentAmount: round(racun.mpc),
1333
+ TaxesPerSeller: [{
1334
+ VAT: racun.davki.map(d => {
1335
+ return {
1336
+ TaxRate: round(d.dst * 100),
1337
+ TaxableAmount: round(d.osnova),
1338
+ TaxAmount: round(d.davek),
1339
+ }
1340
+ })
1341
+ }],
1342
+ OperatorTaxNumber: Number(racun.izdalDs),
1343
+ //ProtectedID: null,
1344
+ SubsequentSubmit: kasneje,
1345
+ // ReferenceInvoice: [{
1346
+ // ReferenceInvoiceIdentifier: {
1347
+ // BusinessPremiseID: "36CF",
1348
+ // ElectronicDeviceID: "BLAG2",
1349
+ // InvoiceNumber: "144"
1350
+ // },
1351
+ // ReferenceInvoiceIssueDateTime: new Date()
1352
+ // }],
1353
+ };
1354
+ if (racun.predhodniRacun) {
1355
+ let s = racun.predhodniRacun.stevilka.split("-");
1356
+ (Invoice as any).ReferenceInvoice = [{
1357
+ ReferenceInvoiceIdentifier: {
1358
+ BusinessPremiseID: s[2],
1359
+ ElectronicDeviceID: s[1],
1360
+ InvoiceNumber: s[0],
1361
+ },
1362
+ ReferenceInvoiceIssueDateTime: racun.predhodniRacun.datum,
1363
+ }];
1364
+ }
1365
+ let DursEnv = veterina.okolje;
1366
+ if (DursEnv !== data.env) throw new Error(`data.env (${data.env}) !== veterina.okolje (${veterina.okolje})`);
1386
1367
 
1387
- furs = ((await this.client!.request('durs', {
1388
- operation: 'register invoice',
1389
- data: { Invoice, DursEnv, tenant: data.tenant }
1390
- }, { receiveTimeout: 4000 })) as { Durs: { error?:string } })?.Durs;
1368
+ // console.dir(Invoice, {depth:10});
1391
1369
 
1370
+ // davčno potrdi račun
1371
+ let furs: { error?: string, EOR?: string, ZOI?: string, QR?: string } = {};
1372
+ let napaka: string | undefined = ""
1392
1373
  try {
1393
- console.log("register invoice", data.tenant, Invoice.TaxNumber, `${Invoice?.InvoiceIdentifier?.BusinessPremiseID}-${Invoice?.InvoiceIdentifier?.ElectronicDeviceID}-${Invoice?.InvoiceIdentifier?.InvoiceNumber}`, Invoice.InvoiceAmount, furs.EOR);
1394
- } catch (err) {
1395
- console.error(`err logging furs response`);
1396
- }
1397
1374
 
1398
- if (furs?.error && furs.error.match(/no such file/g)) {
1399
- console.warn("no certificate, register it");
1400
- // register cert
1401
- timeoutError = "Samodejna registracija digitalnega potrdila furs spodletela."
1375
+ timeoutError = "FURS podsistem se ni odzval."
1402
1376
 
1403
- await this.registerCert(data.tenant, Invoice.TaxNumber?.toString());
1404
- // re-submit invoice
1405
- furs = (
1406
- (await this.client!.request('durs', {
1377
+ furs = ((await this.client!.request('durs', {
1407
1378
  operation: 'register invoice',
1408
1379
  data: { Invoice, DursEnv, tenant: data.tenant }
1409
1380
  }, { receiveTimeout: 4000 })) as { Durs: { error?: string } })?.Durs;
1381
+
1382
+ try {
1383
+ console.log("register invoice", data.tenant, Invoice.TaxNumber, `${Invoice?.InvoiceIdentifier?.BusinessPremiseID}-${Invoice?.InvoiceIdentifier?.ElectronicDeviceID}-${Invoice?.InvoiceIdentifier?.InvoiceNumber}`, Invoice.InvoiceAmount, furs.EOR);
1384
+ } catch (err) {
1385
+ console.error(`err logging furs response`);
1386
+ }
1387
+
1388
+ if (furs?.error && furs.error.match(/no such file/g)) {
1389
+ console.warn("no certificate, register it");
1390
+ // register cert
1391
+ timeoutError = "Samodejna registracija digitalnega potrdila furs spodletela."
1392
+
1393
+ await this.registerCert(data.tenant, Invoice.TaxNumber?.toString());
1394
+ // re-submit invoice
1395
+ furs = (
1396
+ (await this.client!.request('durs', {
1397
+ operation: 'register invoice',
1398
+ data: { Invoice, DursEnv, tenant: data.tenant }
1399
+ }, { receiveTimeout: 4000 })) as { Durs: { error?: string } })?.Durs;
1400
+ }
1401
+ if (furs?.error && furs.error.match(/SSL alert number 40/gi)) {
1402
+ console.warn("certifikat potekel");
1403
+ timeoutError = "Je digitalno potrdilo FURS pretečeno?"
1404
+ throw new Error(furs.error)
1405
+ }
1406
+ if (furs?.error && furs.error.match(/no such file/g)) {
1407
+ console.warn("no certificate, register it");
1408
+ // register cert
1409
+ timeoutError = "Samodejna registracija digitalnega potrdila furs spodletela."
1410
+
1411
+ await this.registerCert(data.tenant, Invoice.TaxNumber?.toString());
1412
+ // re-submit invoice
1413
+ furs = ((await this.client!.request('durs', {
1414
+ operation: 'register invoice',
1415
+ data: { Invoice, DursEnv, tenant: data.tenant }
1416
+ }, { receiveTimeout: 4000 })) as { Durs: any }).Durs;
1417
+ }
1418
+
1419
+ } catch (err) {
1420
+ console.error("Err calling durs register.invoice", err)
1421
+ napaka = `${timeoutError} (${err && err.data && err.data.message})`
1410
1422
  }
1411
- if (furs?.error && furs.error.match(/SSL alert number 40/gi)) {
1412
- console.warn("certifikat potekel");
1413
- timeoutError = "Je digitalno potrdilo FURS pretečeno?"
1414
- throw new Error(furs.error)
1423
+
1424
+ napaka = napaka || furs?.error;
1425
+ if (!napaka && (!furs?.EOR || !furs?.ZOI)) napaka = "furs sistem ni vrnil EOR ali ZOI"
1426
+ let fursObj = napaka ? {
1427
+ zoi: furs?.ZOI,
1428
+ eor: furs?.EOR,
1429
+ qr: furs?.QR,
1430
+ fursError: `furs/račun: ${napaka}`,
1431
+ davcnoSpodletloPrvic: racun.davcnoSpodletloPrvic || new Date(),
1432
+ davcnoSpodletloZadnjic: new Date(),
1433
+ davcnoSpodletloPoskusov: (racun.davcnoSpodletloPoskusov || 0) + 1
1434
+ } : {
1435
+ zoi: furs.ZOI,
1436
+ eor: furs.EOR,
1437
+ qr: furs.QR,
1438
+ davcnoPotrjeno: new Date(),
1415
1439
  }
1416
- if (furs?.error && furs.error.match(/no such file/g)) {
1417
- console.warn("no certificate, register it");
1418
- // register cert
1419
- timeoutError = "Samodejna registracija digitalnega potrdila furs spodletela."
1420
1440
 
1421
- await this.registerCert(data.tenant, Invoice.TaxNumber?.toString());
1422
- // re-submit invoice
1423
- furs = ((await this.client!.request('durs', {
1424
- operation: 'register invoice',
1425
- data: { Invoice, DursEnv, tenant: data.tenant }
1426
- }, { receiveTimeout: 4000 })) as { Durs: any }).Durs;
1441
+ // posodobi račun
1442
+ timeoutError = "Napaka pri vpisu davčno potrjenega računa: Db podsistem se ne odziva več."
1443
+ let updated = await this.dbUpdateById(data.tenant, "racuni", data._id, fursObj);
1444
+
1445
+ try {
1446
+ let dir = path.join('./racuni', new Date().getFullYear().toString(), data.tenant)
1447
+ !fs.existsSync(dir) && makeDir.sync(dir);
1448
+ fs.writeFileSync(path.join(dir, racun.stevilka), serialize.pack(clonedeep({ ...racun, ...updated }), false));
1449
+ } catch (err) {
1450
+ console.log("napaka pri zapisu izdanega računa na disk", err)
1427
1451
  }
1428
1452
 
1453
+ return updated;
1454
+
1429
1455
  } catch (err) {
1430
- console.error("Err calling durs register.invoice", err)
1431
- napaka = `${timeoutError} (${err && err.data && err.data.message})`
1432
- }
1433
1456
 
1434
- napaka = napaka || furs?.error;
1435
- if (!napaka && (!furs?.EOR || !furs?.ZOI)) napaka = "furs sistem ni vrnil EOR ali ZOI"
1436
- let fursObj = napaka ? {
1437
- zoi: furs?.ZOI,
1438
- eor: furs?.EOR,
1439
- qr: furs?.QR,
1440
- fursError: `furs/račun: ${napaka}`,
1441
- davcnoSpodletloPrvic: racun.davcnoSpodletloPrvic || new Date(),
1442
- davcnoSpodletloZadnjic: new Date(),
1443
- davcnoSpodletloPoskusov: (racun.davcnoSpodletloPoskusov || 0) + 1
1444
- } : {
1445
- zoi: furs.ZOI,
1446
- eor: furs.EOR,
1447
- qr: furs.QR,
1448
- davcnoPotrjeno: new Date(),
1457
+ return {
1458
+ fursError: `furs/račun: ${err.message || err}`,
1459
+ }
1449
1460
  }
1461
+ };
1450
1462
 
1451
- // posodobi račun
1452
- timeoutError = "Napaka pri vpisu davčno potrjenega računa: Db podsistem se ne odziva več."
1453
- let updated = await this.dbUpdateById(data.tenant, "racuni", data._id, fursObj);
1463
+ /**
1464
+ * Stornira račun" tako, da kreira nov odprtRacun z negativnimi postavkami.
1465
+ * @param {string} db
1466
+ * @param {string} id
1467
+ */
1468
+ async storno(db: string, id: string) {
1469
+ // poglej, če morda storno že poteka
1454
1470
 
1455
- try {
1456
- let dir = path.join('./racuni', new Date().getFullYear().toString(), data.tenant)
1457
- !fs.existsSync(dir) && makeDir.sync(dir);
1458
- fs.writeFileSync(path.join(dir, racun.stevilka), serialize.pack(clonedeep({ ...racun, ...updated }), false));
1459
- } catch (err) {
1460
- console.log("napaka pri zapisu izdanega računa na disk", err)
1461
- }
1471
+ this.mongo!.setDb(db)
1472
+ this.mongo!.setAudit({ tenant: db, app: "klikvet/storno/1" })
1462
1473
 
1463
- return updated;
1474
+ let obstojeci = await this.mongo!.findOne("odprtiRacuni", { "predhodniRacun._id": id })
1464
1475
 
1465
- } catch (err) {
1476
+ // (await client.requestPromise('db', {
1477
+ // operation: 'findOne',
1478
+ // db: string,
1479
+ //: string collection: 'odprtiRacuni',
1480
+ // query: { "predhodniRacun._id": id }
1481
+ // }, null, 2000)).data;
1466
1482
 
1467
- return {
1468
- fursError: `furs/račun: ${err.message || err}`,
1469
- }
1470
- }
1471
- };
1483
+ if (obstojeci) return obstojeci;
1472
1484
 
1473
- /**
1474
- * Stornira račun" tako, da kreira nov odprtRacun z negativnimi postavkami.
1475
- * @param {string} db
1476
- * @param {string} id
1477
- */
1478
- async storno(db: string, id: string) {
1479
- // poglej, če morda storno že poteka
1485
+ let racun = clonedeep(await this.dbFindById<Racun>(db, "racuni", id));
1480
1486
 
1481
- this.mongo!.setDb(db)
1482
- this.mongo!.setAudit({ tenant: db, app: "klikvet/storno/1" })
1487
+ if (!racun) throw new Error(`storno: ni računa ${id}`)
1483
1488
 
1484
- let obstojeci = await this.mongo!.findOne("odprtiRacuni", { "predhodniRacun._id": id })
1485
1489
 
1486
- // (await client.requestPromise('db', {
1487
- // operation: 'findOne',
1488
- // db: string,
1489
- //: string collection: 'odprtiRacuni',
1490
- // query: { "predhodniRacun._id": id }
1491
- // }, null, 2000)).data;
1490
+ // povezi racuna
1491
+ racun.predhodniRacun = {
1492
+ _id: racun._id,
1493
+ stevilka: racun.stevilka,
1494
+ datum: racun.datum
1495
+ };
1492
1496
 
1493
- if (obstojeci) return obstojeci;
1497
+ // ustvari negativne postavke
1498
+ let flds: (keyof PostavkaRacuna)[] = ['kolicina', 'tpop', 'tnbc', 'tdav', 'tprc', 'tmpc'];
1499
+ racun.postavke.forEach(postavka => {
1500
+ flds.forEach((f: keyof PostavkaRacuna) => {
1501
+ (postavka[f] as any) = -(postavka[f] || 0)
1502
+ })
1503
+ });
1504
+
1505
+ // ustvari negativne vsote
1506
+ let rflds: (keyof Racun)[] = ['mpc', 'prc', 'dav', 'pop', 'nbc'];
1507
+ rflds.forEach(f => {
1508
+ (racun[f] as any) = -(racun[f] || 0)
1509
+ });
1510
+ // zbrisi polja, ki jih ne sme biti na novem računu
1511
+
1512
+ // odstrani polja, ki so odvec
1513
+
1514
+ let dflds: (keyof Racun)[] =
1515
+ ["zapSt", "stRacuna", "pripis", "izdal", "opomba", "zoi", "eor", "stKopij", "stevilka",
1516
+ "idIzdanegaRacuna", "valuta", "izdalDs", "razknjizen", "statusIzdaje",
1517
+ "odprt", "odprtIz", "naprava_id", "izPredracuna_id", "izPredracuna_st",
1518
+ "izDobavnice_id", "izDobavnice_st", "datum", "zbirnik",
1519
+ "opomba", "fursError", "davcnoPotrjeno", "davcnoSpodletloPrvic",
1520
+ "davcnoSpodletloZadnjic", "davcnoSpodletloPoskusov", "stKopij", "datumiKopij",
1521
+ "navodiloStranki", "kontrola", "vCrpDatum", "vCrpKdo", "vCrp",
1522
+
1523
+ ];
1524
+ dflds.forEach(f => {
1525
+ delete racun[f]
1526
+ });
1527
+
1528
+ racun.datum = new Date();
1529
+ // tole nastavi GUI
1530
+ racun.placila = [];
1531
+ racun.davki = [];
1532
+ (racun._id as any) = undefined;
1494
1533
 
1495
- let racun = clonedeep(await this.dbFindById<Racun>(db, "racuni", id));
1534
+ this.mongo!.setDb(db)
1535
+ this.mongo!.setAudit({ tenant: db, app: "klikvet/storno/2" })
1496
1536
 
1497
- if (!racun) throw new Error(`storno: ni računa ${id}`)
1537
+ let odprtiRacun = await this.mongo!.insert("odprtiRacuni", racun)
1498
1538
 
1539
+ // (await client.requestPromise('db', {
1540
+ // operation: 'insert',
1541
+ // db: string,
1542
+ //: string collection: "odprtiRacuni",
1543
+ // insert: racun,
1544
+ // }, null, 2000)).data;
1499
1545
 
1500
- // povezi racuna
1501
- racun.predhodniRacun = {
1502
- _id: racun._id,
1503
- stevilka: racun.stevilka,
1504
- datum: racun.datum
1546
+ return odprtiRacun;
1505
1547
  };
1506
1548
 
1507
- // ustvari negativne postavke
1508
- let flds: (keyof PostavkaRacuna)[] = ['kolicina', 'tpop', 'tnbc', 'tdav', 'tprc', 'tmpc'];
1509
- racun.postavke.forEach(postavka => {
1510
- flds.forEach( (f: keyof PostavkaRacuna) => {
1511
- (postavka[f] as any) = -(postavka[f]||0)
1512
- })
1513
- });
1514
-
1515
- // ustvari negativne vsote
1516
- let rflds: (keyof Racun)[] = ['mpc', 'prc', 'dav', 'pop', 'nbc'];
1517
- rflds.forEach(f => {
1518
- (racun[f] as any) = -(racun[f]||0)
1519
- });
1520
- // zbrisi polja, ki jih ne sme biti na novem računu
1521
-
1522
- // odstrani polja, ki so odvec
1523
-
1524
- let dflds: (keyof Racun)[] =
1525
- ["zapSt", "stRacuna", "pripis", "izdal", "opomba", "zoi", "eor", "stKopij", "stevilka",
1526
- "idIzdanegaRacuna", "valuta", "izdalDs", "razknjizen", "statusIzdaje",
1527
- "odprt", "odprtIz", "naprava_id", "izPredracuna_id", "izPredracuna_st",
1528
- "izDobavnice_id", "izDobavnice_st", "datum", "zbirnik",
1529
- "opomba", "fursError", "davcnoPotrjeno", "davcnoSpodletloPrvic",
1530
- "davcnoSpodletloZadnjic", "davcnoSpodletloPoskusov", "stKopij", "datumiKopij",
1531
- "navodiloStranki", "kontrola", "vCrpDatum", "vCrpKdo", "vCrp",
1532
-
1533
- ];
1534
- dflds.forEach(f => {
1535
- delete racun[f]
1536
- });
1537
-
1538
- racun.datum = new Date();
1539
- // tole nastavi GUI
1540
- racun.placila = [];
1541
- racun.davki = [];
1542
- (racun._id as any) = undefined;
1543
-
1544
- this.mongo!.setDb(db)
1545
- this.mongo!.setAudit({ tenant: db, app: "klikvet/storno/2" })
1546
-
1547
- let odprtiRacun = await this.mongo!.insert("odprtiRacuni", racun)
1548
-
1549
- // (await client.requestPromise('db', {
1550
- // operation: 'insert',
1551
- // db: string,
1552
- //: string collection: "odprtiRacuni",
1553
- // insert: racun,
1554
- // }, null, 2000)).data;
1555
-
1556
- return odprtiRacun;
1557
- };
1558
-
1559
1549
 
1560
1550
 
1561
1551
  }