@tillhub/schemas 6.464.0 → 6.465.1
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/lib/v0/customers/base.js +31 -0
- package/lib/v0/tags/create.js +10 -1
- package/lib/v0/tags/update.js +10 -1
- package/lib/v1/configurations/items/tenant.js +23 -0
- package/package.json +1 -1
- package/test/configurations/configurations.v1.spec.js +47 -0
- package/test/customers/customers.v0.spec.js +53 -0
- package/test/tags/tags.v0.spec.js +42 -0
- package/test/tags/tags.v0.specs.js +0 -20
package/lib/v0/customers/base.js
CHANGED
|
@@ -425,5 +425,36 @@ module.exports = {
|
|
|
425
425
|
example: 'true',
|
|
426
426
|
type: 'boolean',
|
|
427
427
|
default: true
|
|
428
|
+
},
|
|
429
|
+
e_invoicing_email: {
|
|
430
|
+
description: 'Email address the electronic invoice is delivered to',
|
|
431
|
+
example: 'invoices@kamino.empire',
|
|
432
|
+
...anyOf({
|
|
433
|
+
type: 'string',
|
|
434
|
+
maxLength: 128,
|
|
435
|
+
format: 'email'
|
|
436
|
+
}),
|
|
437
|
+
'default': null
|
|
438
|
+
},
|
|
439
|
+
e_invoicing_document_format: {
|
|
440
|
+
description: 'Document format of the electronic invoice',
|
|
441
|
+
example: 'ZUGFERD_V2',
|
|
442
|
+
type: 'string',
|
|
443
|
+
'enum': [
|
|
444
|
+
'ZUGFERD_V2',
|
|
445
|
+
'XRECHNUNG_V3'
|
|
446
|
+
],
|
|
447
|
+
'default': 'ZUGFERD_V2'
|
|
448
|
+
},
|
|
449
|
+
e_invoicing_delivery_channel: {
|
|
450
|
+
description: 'Delivery channel the electronic invoice is sent through',
|
|
451
|
+
example: 'EMAIL',
|
|
452
|
+
type: 'string',
|
|
453
|
+
'enum': [
|
|
454
|
+
'EMAIL',
|
|
455
|
+
'PEPPOL',
|
|
456
|
+
'SDI'
|
|
457
|
+
],
|
|
458
|
+
'default': 'EMAIL'
|
|
428
459
|
}
|
|
429
460
|
}
|
package/lib/v0/tags/create.js
CHANGED
package/lib/v0/tags/update.js
CHANGED
|
@@ -7,7 +7,16 @@ module.exports.request = {
|
|
|
7
7
|
additionalProperties: false,
|
|
8
8
|
type: 'object',
|
|
9
9
|
required: [],
|
|
10
|
-
properties:
|
|
10
|
+
properties: {
|
|
11
|
+
...base,
|
|
12
|
+
name: {
|
|
13
|
+
type: 'string',
|
|
14
|
+
minLength: 1,
|
|
15
|
+
not: {
|
|
16
|
+
pattern: '^\\s|\\s$'
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
11
20
|
}
|
|
12
21
|
|
|
13
22
|
module.exports.response = {
|
|
@@ -44,6 +44,29 @@ module.exports = {
|
|
|
44
44
|
phone: {
|
|
45
45
|
type: 'string',
|
|
46
46
|
description: 'Phone number of commercial contact'
|
|
47
|
+
},
|
|
48
|
+
trade_name: {
|
|
49
|
+
oneOf: [
|
|
50
|
+
{
|
|
51
|
+
type: 'string',
|
|
52
|
+
maxLength: 128
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
type: 'null'
|
|
56
|
+
}
|
|
57
|
+
],
|
|
58
|
+
description: 'Trade name of the company, printed on the e-invoice instead of company_name'
|
|
59
|
+
},
|
|
60
|
+
official_email: {
|
|
61
|
+
oneOf: [
|
|
62
|
+
{
|
|
63
|
+
type: 'string'
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
type: 'null'
|
|
67
|
+
}
|
|
68
|
+
],
|
|
69
|
+
description: 'Official contact email of the seller, printed on the e-invoice'
|
|
47
70
|
}
|
|
48
71
|
}
|
|
49
72
|
}
|
package/package.json
CHANGED
|
@@ -476,3 +476,50 @@ test('Configurations: press_item_barcode rejects unknown enum values', function
|
|
|
476
476
|
}), 'lookup_priority')
|
|
477
477
|
t.end()
|
|
478
478
|
})
|
|
479
|
+
|
|
480
|
+
;['create', 'update', 'patch'].forEach(function (operation) {
|
|
481
|
+
const request = require('../../lib/v1/configurations')[operation].request
|
|
482
|
+
const validatePayload = ajv.compile(request)
|
|
483
|
+
const payload = function (tenant) {
|
|
484
|
+
return {
|
|
485
|
+
...(operation === 'create' ? { name: 'E-Rechnung configuration', owner: 'self' } : {}),
|
|
486
|
+
tenant
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
test(`Configurations: ${operation} accepts the e-invoicing tenant properties`, function (t) {
|
|
491
|
+
const cases = [
|
|
492
|
+
['both properties next to company_name', {
|
|
493
|
+
company_name: 'Muster GmbH',
|
|
494
|
+
trade_name: 'Muster',
|
|
495
|
+
official_email: 'invoices@seller.example'
|
|
496
|
+
}],
|
|
497
|
+
['trade_name only', { trade_name: 'Muster' }],
|
|
498
|
+
['official_email only', { official_email: 'invoices@seller.example' }],
|
|
499
|
+
['neither property', { company_name: 'Muster GmbH' }],
|
|
500
|
+
['a free-form official_email', { official_email: 'invoices at seller example' }],
|
|
501
|
+
['a null trade_name', { trade_name: null }],
|
|
502
|
+
['a null official_email', { official_email: null }]
|
|
503
|
+
]
|
|
504
|
+
t.plan(cases.length)
|
|
505
|
+
cases.forEach(function ([description, tenant]) {
|
|
506
|
+
const valid = validatePayload(payload(tenant))
|
|
507
|
+
t.ok(valid, `${description}: ${ajv.errorsText(validatePayload.errors)}`)
|
|
508
|
+
})
|
|
509
|
+
t.end()
|
|
510
|
+
})
|
|
511
|
+
|
|
512
|
+
test(`Configurations: ${operation} rejects invalid e-invoicing tenant properties`, function (t) {
|
|
513
|
+
const cases = [
|
|
514
|
+
['a numeric trade_name', { trade_name: 42 }],
|
|
515
|
+
['a numeric official_email', { official_email: 42 }],
|
|
516
|
+
['a trade_name over 128 characters', { trade_name: 'a'.repeat(129) }],
|
|
517
|
+
['an undeclared property', { official_trade_name: 'Muster' }]
|
|
518
|
+
]
|
|
519
|
+
t.plan(cases.length)
|
|
520
|
+
cases.forEach(function ([description, tenant]) {
|
|
521
|
+
t.notOk(validatePayload(payload(tenant)), description)
|
|
522
|
+
})
|
|
523
|
+
t.end()
|
|
524
|
+
})
|
|
525
|
+
})
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
const test = require('tape')
|
|
2
|
+
const Ajv = require('ajv')
|
|
2
3
|
const validate = require('../helpers/validate-schema')
|
|
3
4
|
const customers = require('../../lib/v0/customers')
|
|
5
|
+
const customerBase = require('../../lib/v0/customers/base')
|
|
6
|
+
|
|
7
|
+
const ajv = new Ajv()
|
|
8
|
+
const validateCreatePayload = ajv.compile(customers.create.request)
|
|
9
|
+
const validateUpdatePayload = ajv.compile(customers.update.request)
|
|
4
10
|
|
|
5
11
|
test('Customers:v0: create schema validation', function (t) {
|
|
6
12
|
{
|
|
@@ -97,3 +103,50 @@ test('Customers:v0: read.one schema validation', function (t) {
|
|
|
97
103
|
|
|
98
104
|
t.end()
|
|
99
105
|
})
|
|
106
|
+
|
|
107
|
+
test('Customers:v0: create accepts every e-invoicing document format and delivery channel', function (t) {
|
|
108
|
+
const formats = customerBase.e_invoicing_document_format.enum
|
|
109
|
+
const channels = customerBase.e_invoicing_delivery_channel.enum
|
|
110
|
+
t.plan(formats.length + channels.length)
|
|
111
|
+
|
|
112
|
+
formats.forEach((format) => {
|
|
113
|
+
const valid = validateCreatePayload({ e_invoicing_document_format: format })
|
|
114
|
+
t.ok(valid, `should accept document format "${format}"`)
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
channels.forEach((channel) => {
|
|
118
|
+
const valid = validateCreatePayload({ e_invoicing_delivery_channel: channel })
|
|
119
|
+
t.ok(valid, `should accept delivery channel "${channel}"`)
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
t.end()
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
test('Customers:v0: create accepts an invoicing email and null', function (t) {
|
|
126
|
+
t.plan(2)
|
|
127
|
+
t.ok(validateCreatePayload({ e_invoicing_email: 'invoices@kamino.empire' }), 'should accept an email address')
|
|
128
|
+
t.ok(validateCreatePayload({ e_invoicing_email: null }), 'should accept null')
|
|
129
|
+
|
|
130
|
+
t.end()
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
test('Customers:v0: create rejects invalid e-invoicing values', function (t) {
|
|
134
|
+
t.plan(5)
|
|
135
|
+
t.notOk(validateCreatePayload({ e_invoicing_document_format: 'XRECHNUNG' }), 'should reject an unknown document format')
|
|
136
|
+
t.notOk(validateCreatePayload({ e_invoicing_document_format: null }), 'should reject a null document format')
|
|
137
|
+
t.notOk(validateCreatePayload({ e_invoicing_delivery_channel: 'FAX' }), 'should reject an unknown delivery channel')
|
|
138
|
+
t.notOk(validateCreatePayload({ e_invoicing_delivery_channel: null }), 'should reject a null delivery channel')
|
|
139
|
+
t.notOk(validateCreatePayload({ e_invoicing_email: 'not-an-email' }), 'should reject an invoicing email that is not an email address')
|
|
140
|
+
|
|
141
|
+
t.end()
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
test('Customers:v0: update accepts and rejects the same e-invoicing values', function (t) {
|
|
145
|
+
t.plan(4)
|
|
146
|
+
t.ok(validateUpdatePayload({ e_invoicing_document_format: 'XRECHNUNG_V3' }), 'should accept a known document format')
|
|
147
|
+
t.ok(validateUpdatePayload({ e_invoicing_delivery_channel: 'SDI' }), 'should accept a known delivery channel')
|
|
148
|
+
t.notOk(validateUpdatePayload({ e_invoicing_document_format: 'ZUGFERD' }), 'should reject an unknown document format')
|
|
149
|
+
t.notOk(validateUpdatePayload({ e_invoicing_email: 'not-an-email' }), 'should reject an invoicing email that is not an email address')
|
|
150
|
+
|
|
151
|
+
t.end()
|
|
152
|
+
})
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const test = require('tape')
|
|
2
|
+
const Ajv = require('ajv')
|
|
3
|
+
const validate = require('../helpers/validate-schema')
|
|
4
|
+
const tags = require('../../lib/v0/tags')
|
|
5
|
+
|
|
6
|
+
test('Tags: create schema validation', function (t) {
|
|
7
|
+
t.plan(2)
|
|
8
|
+
const createRequest = require('../../lib/v0/tags').create.request
|
|
9
|
+
const { valid, error } = validate(createRequest)
|
|
10
|
+
t.ok(valid, 'create schema is valid')
|
|
11
|
+
t.error(error, 'should not get any error')
|
|
12
|
+
t.end()
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
test('Tags: update schema validation', function (t) {
|
|
16
|
+
t.plan(2)
|
|
17
|
+
const updateRequest = require('../../lib/v0/tags').update.request
|
|
18
|
+
const { valid, error } = validate(updateRequest)
|
|
19
|
+
t.ok(valid, 'update schema is valid')
|
|
20
|
+
t.error(error, 'should not get any error')
|
|
21
|
+
t.end()
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
for (const operation of ['create', 'update']) {
|
|
25
|
+
test(`Tags: ${operation} rejects empty names and surrounding whitespace`, function (t) {
|
|
26
|
+
const validateRequest = new Ajv().compile(tags[operation].request)
|
|
27
|
+
|
|
28
|
+
for (const name of [
|
|
29
|
+
'', ' ', '\t\n', null, 42,
|
|
30
|
+
' green', 'green ', ' green ',
|
|
31
|
+
'\tgreen', 'green\t', 'green\n', 'green\r\n',
|
|
32
|
+
'\u00a0green', 'green\u00a0', '\ufeffgreen', 'green\ufeff'
|
|
33
|
+
]) {
|
|
34
|
+
t.notOk(validateRequest({ name }), `rejects name ${JSON.stringify(name)}`)
|
|
35
|
+
}
|
|
36
|
+
for (const name of ['g', 'green', 'Grüner Tee', 'Grüner Tee', '🟢']) {
|
|
37
|
+
t.ok(validateRequest({ name }), `accepts name ${JSON.stringify(name)}`)
|
|
38
|
+
}
|
|
39
|
+
t.equal(validateRequest({ deleted: true }), operation === 'update', 'only updates may omit the name')
|
|
40
|
+
t.end()
|
|
41
|
+
})
|
|
42
|
+
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
const test = require('tape')
|
|
2
|
-
const validate = require('../helpers/validate-schema')
|
|
3
|
-
|
|
4
|
-
test('Tags: create schema validation', function (t) {
|
|
5
|
-
t.plan(2)
|
|
6
|
-
const createRequest = require('../../lib/v0/tags').create.request
|
|
7
|
-
const { valid, error } = validate(createRequest)
|
|
8
|
-
t.ok(valid, 'create schema is valid')
|
|
9
|
-
t.error(error, 'should not get any error')
|
|
10
|
-
t.end()
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
test('Tags: update schema validation', function (t) {
|
|
14
|
-
t.plan(2)
|
|
15
|
-
const updateRequest = require('../../lib/v0/tags').update.request
|
|
16
|
-
const { valid, error } = validate(updateRequest)
|
|
17
|
-
t.ok(valid, 'update schema is valid')
|
|
18
|
-
t.error(error, 'should not get any error')
|
|
19
|
-
t.end()
|
|
20
|
-
})
|