summaryrefslogtreecommitdiff
path: root/src/services/uploads.service.ts
blob: 1d39a66daf03b515089b2f11b659887845a10ca0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import { Application } from '@feathersjs/express';
import { HookContext } from '@feathersjs/feathers';
import blobService from 'feathers-blob';
import fs from 'fs-blob-store';
import moment from 'moment';
import Bluebird from 'bluebird';
import { PdfReader } from 'pdfreader'
import _ from 'lodash';

const dir = './documents';
const blobStorage = fs(dir);
const uploads = blobService({ Model: blobStorage });


const parseTransfersBill = async (context: HookContext): Promise<HookContext> => {
  const { id } = context.result;
  const fileName = `${dir}/${id}`;

  const reader = new PdfReader();
  const items: any[] = [];

  reader.parseFileItems(fileName, (err: Error, item: any) => {
    if (item) items.push(item);
    else { // Finished parsing. TODO: wrap into async
      const hash = _.groupBy(items, 'y')
      const rows = _.map(hash, (elements: any[]) => _.map(elements, 'text'));

      const transfers = rows.reduce((acc: any, cols: string[]) => {
        if (cols[0]?.startsWith('УНП')) {
          acc[acc.length - 1].vatId = cols[2];
          acc[acc.length - 1].name = cols[3];
        } else if (cols.length === 7) {
          const [dateString, doc, op, code, account, debet, credit] = cols;
          try {
            const date = moment(dateString, 'DD.MM.YYYY').toISOString();
            acc.push({ date, doc, op, code, account, debet, credit });
          } catch (e) {
            console.log(`Skipping row because not a date: ${dateString}`);
          }
        }

        return acc;
      }, []);

      return Bluebird.mapSeries(transfers, async (transfer: any) => {
        const { date, vatId, name } = transfer;
        const debet = parseFloat(transfer.debet.replace(/ /g, ''));
        const credit = parseFloat(transfer.credit.replace(/ /g, ''));

        const operation = debet ? 'out' : 'in';
        const amount = debet || credit;

        const contractorId = await context.app
          .service('contractors')
          .find({ query: { vatId } })
          .then((results: any[]) => {
            if (results.length) return results[0];
            return context.app
              .service('contractors')
              .create({ vatId, name });
          })
          .then((contractor: any) => contractor._id);

        return context.app.service('transfers').create({
          date,
          operation,
          amount,
          contractorId,
        });
      }).then(() => context.service.remove(id));
    }
  });

  return context;
};


export default (app: Application): void => {
  app.use('/uploads', uploads);

  app.service('uploads').hooks({
    after: {
      create: parseTransfersBill,
    },
  });
};