• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

GrottoCenter / grottocenter-api / 10996310862

23 Sep 2024 02:22PM UTC coverage: 46.158% (-2.8%) from 48.952%
10996310862

push

github

vmarseguerra
feat(entities): adds delete / restore for document

740 of 2203 branches covered (33.59%)

Branch coverage included in aggregate %.

24 of 153 new or added lines in 17 files covered. (15.69%)

484 existing lines in 49 files now uncovered.

2462 of 4734 relevant lines covered (52.01%)

4.5 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

2.65
/api/services/DocumentCSVImportService.js
1
const {
2
  valIfTruthyOrNull,
3
  getDateFromKarstlink,
4
  extractUrlFragment,
5
  getCreator,
6
} = require('../utils/csvHelper');
1✔
7
const GrottoService = require('./GrottoService');
1✔
8

9
module.exports = {
1✔
10
  getConvertedDescriptionFromCsv: async (data, authorId) => {
11
    let descLang =
12
      valIfTruthyOrNull(data['karstlink:hasDescriptionDocument/dc:language']) ??
×
13
      valIfTruthyOrNull(data['dc:language']);
14

15
    if (descLang) descLang = descLang.toLowerCase();
×
16
    if (descLang && descLang.length === 2) {
×
17
      const nameLang = await TLanguage.findOne({ part1: descLang });
×
18
      if (nameLang) descLang = nameLang.id;
×
19
    }
20

21
    return {
×
22
      author: authorId,
23
      title: valIfTruthyOrNull(data['rdfs:label']),
24
      description: valIfTruthyOrNull(
25
        data['karstlink:hasDescriptionDocument/dct:description']
26
      ),
27
      dateInscription: getDateFromKarstlink(
28
        valIfTruthyOrNull(data['dct:rights/dct:created']) ?? new Date()
×
29
      ),
30
      dateReviewed: getDateFromKarstlink(
31
        valIfTruthyOrNull(data['dct:rights/dct:modified']) ?? new Date()
×
32
      ),
33
      language: descLang,
34
    };
35
  },
36

37
  getConvertedDocumentFromCsv: async (req, data, authorId) => {
38
    // License
39
    const licence = extractUrlFragment(
×
40
      valIfTruthyOrNull(data['dct:rights/karstlink:licenseType'])
41
    );
42
    const licenceDb = await TLicense.findOne({ name: licence });
×
43
    if (!licenceDb) {
×
44
      throw Error(`This kind of license (${licence}) cannot be imported.`);
×
45
    }
46

47
    const language = valIfTruthyOrNull(data['dc:language'])?.toLowerCase();
×
48
    let nameLang;
49
    if (language && language.length === 2) {
×
50
      nameLang = await TLanguage.findOne({ part1: language });
×
51
    }
52
    const languages = nameLang ? [nameLang.id] : [];
×
53

54
    const country = valIfTruthyOrNull(data['gn:countryCode'])?.toUpperCase();
×
55
    let aCountry;
56
    if (country && country.length === 2) {
×
57
      aCountry = await TCountry.findOne({ id: country });
×
58
    }
59
    const countries = aCountry ? [aCountry.id] : [];
×
60

61
    // Creator(s)
62
    const rawCreators = data['dct:creator'].split('|').filter((e) => e);
×
63
    // For each creator, first check if there is a grotto of this name.
64
    // If not, check for a caver. If not, create a caver.
65
    const creatorsPromises = rawCreators.map(async (creatorRaw) => {
×
66
      const authorGrotto = await TName.findOne({
×
67
        name: extractUrlFragment(creatorRaw),
68
        grotto: { '!=': null },
69
        isDeleted: false,
70
      });
71

72
      // If a grotto is found, a name object is returned.
73
      if (authorGrotto) return { type: 'grotto', value: authorGrotto };
×
74

75
      // If it as a caver which is found, it returns a caver object
76
      return {
×
77
        type: 'caver',
78
        value: await getCreator(creatorRaw),
79
      };
80
    });
81
    const creators = await Promise.all(creatorsPromises);
×
82
    const creatorsCaverId = [];
×
83
    const creatorsGrottoId = [];
×
84

85
    for (const creator of creators) {
×
86
      if (creator.type === 'caver') creatorsCaverId.push(creator.value.id);
×
87
      if (creator.type === 'grotto')
×
88
        creatorsGrottoId.push(creator.value.grotto);
×
89
    }
90

91
    // Editor
92
    let editorId;
93
    const editorsRaw = valIfTruthyOrNull(data['dct:publisher']);
×
94

95
    if (editorsRaw) {
×
96
      const editorName = editorsRaw
×
97
        .split('|')
98
        .map((e) => extractUrlFragment(e).replace(/_/g, ' '))
×
99
        .filter((e) => e)
×
100
        .join(', ');
101

102
      const name = await TName.findOne({
×
103
        name: editorName,
104
        grotto: { '!=': null },
105
        isDeleted: false,
106
      });
107
      if (!name) {
×
108
        const paramsGrotto = {
×
109
          author: authorId,
110
          dateInscription: new Date(),
111
        };
112
        const nameGrotto = {
×
113
          text: editorName,
114
          language: language ?? 'eng',
×
115
          author: authorId,
116
        };
117
        const editorGrotto = await GrottoService.createGrotto(
×
118
          req,
119
          paramsGrotto,
120
          nameGrotto
121
        );
122
        editorId = editorGrotto.id;
×
123
      } else {
124
        editorId = name.grotto;
×
125
      }
126
    }
127

128
    // Doc type
129
    let typeId;
130
    const typeData = valIfTruthyOrNull(data['karstlink:documentType']);
×
131
    if (typeData) {
×
132
      const typeCriteria = typeData.startsWith('http')
×
133
        ? { url: typeData }
134
        : { name: typeData };
135
      const type = await TType.findOne(typeCriteria);
×
136
      if (!type) {
×
137
        throw Error(`The document type '${typeData}' is incorrect.`);
×
138
      }
139
      typeId = type.id;
×
140
    }
141

142
    // Parent / partOf
143
    const parentId = valIfTruthyOrNull(data['dct:isPartOf']);
×
144
    const doesParentExist = parentId
×
145
      ? await TDocument.findOne({ id: parentId })
146
      : false;
UNCOV
147
    if (parentId && !doesParentExist) {
×
UNCOV
148
      throw Error(`Document parent with id ${parentId} not found.`);
×
149
    }
150

151
    return {
×
152
      idDbImport: valIfTruthyOrNull(data.id),
153
      nameDbImport: valIfTruthyOrNull(data['dct:rights/cc:attributionName']),
154
      identifier: valIfTruthyOrNull(data['dct:source']),
155
      identifierType: valIfTruthyOrNull(data['dct:identifier'])
156
        ?.trim()
157
        ?.toLowerCase(),
158

159
      dateInscription: getDateFromKarstlink(
160
        valIfTruthyOrNull(data['dct:rights/dct:created']) ?? new Date()
×
161
      ),
162
      dateReviewed: getDateFromKarstlink(
163
        valIfTruthyOrNull(data['dct:rights/dct:modified']) ?? new Date()
×
164
      ),
165
      datePublication: valIfTruthyOrNull(data['dct:date']),
166
      // isValidated, // TODO auto validate an imported document ?
167
      // validationComment: 'From CSV import',
168

169
      author: authorId,
170
      // authorComment: '', // TODO Add ?
171
      authors: creatorsCaverId,
172
      authorsGrotto: creatorsGrottoId,
173
      editor: editorId,
174
      // library: '', // TODO Add ?
175

176
      type: typeId,
177
      // descriptions is changed independently (getConvertedDescriptionFromCsv)
178
      subjects: valIfTruthyOrNull(data['dct:subject'])?.split('|'),
179
      // issue: '', // TODO Add ?
180
      // pages: '', // TODO Add ?
181
      // option: '', // TODO Add ?
182
      license: licenceDb.id,
183
      languages,
184

185
      // TODO Add massifs, cave, entrance, files, authorizationDocument ?
186
      // TODO Add isoRegions ?
187
      countries,
188
      parent: parentId,
189
    };
190
  },
191
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc