@things-factory/sales 10.1.223 → 10.1.227
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/dist-client/index.d.ts +1 -0
- package/dist-client/index.js +1 -0
- package/dist-client/index.js.map +1 -1
- package/dist-client/pages/quotation-editor.d.ts +50 -6
- package/dist-client/pages/quotation-editor.js +303 -33
- package/dist-client/pages/quotation-editor.js.map +1 -1
- package/dist-client/pages/sales-product-list.d.ts +54 -0
- package/dist-client/pages/sales-product-list.js +202 -0
- package/dist-client/pages/sales-product-list.js.map +1 -0
- package/dist-client/route.d.ts +1 -1
- package/dist-client/route.js +3 -0
- package/dist-client/route.js.map +1 -1
- package/dist-client/sales-product-pick.d.ts +51 -0
- package/dist-client/sales-product-pick.js +210 -0
- package/dist-client/sales-product-pick.js.map +1 -0
- package/dist-client/sales-product-words.d.ts +2 -0
- package/dist-client/sales-product-words.js +8 -0
- package/dist-client/sales-product-words.js.map +1 -0
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/service/index.d.ts +6 -2
- package/dist-server/service/index.js +8 -3
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/service/quotation/quotation-query.d.ts +3 -0
- package/dist-server/service/quotation/quotation-query.js +36 -0
- package/dist-server/service/quotation/quotation-query.js.map +1 -1
- package/dist-server/service/quotation/quotation-service.d.ts +1 -0
- package/dist-server/service/quotation/quotation-service.js +5 -4
- package/dist-server/service/quotation/quotation-service.js.map +1 -1
- package/dist-server/service/sales-product/index.d.ts +6 -0
- package/dist-server/service/sales-product/index.js +10 -0
- package/dist-server/service/sales-product/index.js.map +1 -0
- package/dist-server/service/sales-product/sales-product-mutation.d.ts +6 -0
- package/dist-server/service/sales-product/sales-product-mutation.js +46 -0
- package/dist-server/service/sales-product/sales-product-mutation.js.map +1 -0
- package/dist-server/service/sales-product/sales-product-query.d.ts +11 -0
- package/dist-server/service/sales-product/sales-product-query.js +78 -0
- package/dist-server/service/sales-product/sales-product-query.js.map +1 -0
- package/dist-server/service/sales-product/sales-product-rules.d.ts +8 -0
- package/dist-server/service/sales-product/sales-product-rules.js +26 -0
- package/dist-server/service/sales-product/sales-product-rules.js.map +1 -0
- package/dist-server/service/sales-product/sales-product-service.d.ts +10 -0
- package/dist-server/service/sales-product/sales-product-service.js +86 -0
- package/dist-server/service/sales-product/sales-product-service.js.map +1 -0
- package/dist-server/service/sales-product/sales-product-type.d.ts +22 -0
- package/dist-server/service/sales-product/sales-product-type.js +81 -0
- package/dist-server/service/sales-product/sales-product-type.js.map +1 -0
- package/dist-server/service/sales-product/sales-product.d.ts +32 -0
- package/dist-server/service/sales-product/sales-product.js +126 -0
- package/dist-server/service/sales-product/sales-product.js.map +1 -0
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -7
- package/things-factory.config.js +2 -1
- package/translations/en.json +33 -3
- package/translations/es.json +33 -3
- package/translations/ja.json +33 -3
- package/translations/ko.json +34 -4
- package/translations/ms.json +33 -3
- package/translations/zh.json +33 -3
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.saveSalesProducts = saveSalesProducts;
|
|
4
|
+
const invoice_1 = require("@things-factory/invoice");
|
|
5
|
+
const shell_1 = require("@things-factory/shell");
|
|
6
|
+
const typeorm_1 = require("typeorm");
|
|
7
|
+
const sales_product_1 = require("./sales-product");
|
|
8
|
+
const sales_product_rules_1 = require("./sales-product-rules");
|
|
9
|
+
const TEXT = ['grade', 'spec', 'description'];
|
|
10
|
+
/** A patch as the row it writes: words trimmed, the unit the kind's when blank, the price and currency checked. */
|
|
11
|
+
function rowOf(patch, old) {
|
|
12
|
+
const row = {};
|
|
13
|
+
if (patch.code !== undefined || !old) {
|
|
14
|
+
const code = String(patch.code ?? '').trim();
|
|
15
|
+
if (!code)
|
|
16
|
+
throw new shell_1.Refusal('sales-product-code-required', {}, 'Give the product a code');
|
|
17
|
+
row.code = code;
|
|
18
|
+
}
|
|
19
|
+
if (patch.name !== undefined || !old) {
|
|
20
|
+
const name = String(patch.name ?? '').trim();
|
|
21
|
+
if (!name)
|
|
22
|
+
throw new shell_1.Refusal('sales-product-name-required', {}, 'Name the product');
|
|
23
|
+
row.name = name;
|
|
24
|
+
}
|
|
25
|
+
const kind = patch.kind ?? old?.kind ?? sales_product_rules_1.SalesProductKind.GOODS;
|
|
26
|
+
row.kind = kind;
|
|
27
|
+
for (const field of TEXT)
|
|
28
|
+
if (patch[field] !== undefined)
|
|
29
|
+
row[field] = String(patch[field] ?? '').trim() || null;
|
|
30
|
+
/* A blank unit is the kind's - also when the kind changes and the unit was the old kind's own. */
|
|
31
|
+
if (patch.unit !== undefined || !old)
|
|
32
|
+
row.unit = (0, sales_product_rules_1.unitOf)(kind, patch.unit);
|
|
33
|
+
else if (patch.kind !== undefined)
|
|
34
|
+
row.unit = old.unit === (0, sales_product_rules_1.unitOf)(old.kind) ? (0, sales_product_rules_1.unitOf)(kind) : old.unit;
|
|
35
|
+
if (patch.currency !== undefined || !old) {
|
|
36
|
+
row.currency = (String(patch.currency ?? '').trim() || 'KRW').toUpperCase();
|
|
37
|
+
(0, invoice_1.currencyDigits)(row.currency);
|
|
38
|
+
}
|
|
39
|
+
if (patch.unitPrice !== undefined || !old) {
|
|
40
|
+
const price = patch.unitPrice ?? 0;
|
|
41
|
+
if (!Number.isFinite(price) || price < 0)
|
|
42
|
+
throw new shell_1.Refusal('sales-product-price-invalid', {}, 'The price is zero or more');
|
|
43
|
+
row.unitPrice = price;
|
|
44
|
+
}
|
|
45
|
+
if (patch.taxKind !== undefined || !old)
|
|
46
|
+
row.taxKind = patch.taxKind ?? 'TAXABLE';
|
|
47
|
+
if (patch.active !== undefined || !old)
|
|
48
|
+
row.active = patch.active !== false;
|
|
49
|
+
return row;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Apply grid rows to a domain's products: `+` (or no id) registers, `M` changes, `-` deletes (softly). A code is the
|
|
53
|
+
* domain's once among the products not deleted. Nothing names a product - a quotation line copies what it says - so a
|
|
54
|
+
* product is deleted freely.
|
|
55
|
+
*/
|
|
56
|
+
async function saveSalesProducts(tx, domain, user, patches) {
|
|
57
|
+
const repository = tx.getRepository(sales_product_1.SalesProduct);
|
|
58
|
+
const deletes = patches.filter(one => one.cuFlag === '-' && one.id).map(one => one.id);
|
|
59
|
+
const changes = patches.filter(one => one.cuFlag !== '-');
|
|
60
|
+
if (deletes.length) {
|
|
61
|
+
const owned = await repository.find({ where: { domain: { id: domain.id }, id: (0, typeorm_1.In)(deletes) }, select: ['id'] });
|
|
62
|
+
if (owned.length !== deletes.length)
|
|
63
|
+
throw new shell_1.Refusal('sales-product-not-found', {}, 'A product was not found - reload and try again');
|
|
64
|
+
await repository.softDelete({ id: (0, typeorm_1.In)(deletes) });
|
|
65
|
+
}
|
|
66
|
+
const rows = [];
|
|
67
|
+
for (const patch of changes) {
|
|
68
|
+
const old = patch.id && patch.cuFlag !== '+' ? await repository.findOne({ where: { domain: { id: domain.id }, id: patch.id } }) : undefined;
|
|
69
|
+
if (patch.id && patch.cuFlag !== '+' && !old)
|
|
70
|
+
throw new shell_1.Refusal('sales-product-not-found', {}, 'A product was not found - reload and try again');
|
|
71
|
+
rows.push({ ...(old ?? {}), ...rowOf(patch, old ?? undefined) });
|
|
72
|
+
}
|
|
73
|
+
/* One code, one product: against the rows kept and against one another in the batch. */
|
|
74
|
+
const codes = rows.map(row => row.code);
|
|
75
|
+
const taken = codes.length ? await repository.find({ where: { domain: { id: domain.id }, code: (0, typeorm_1.In)(codes) }, select: ['id', 'code'] }) : [];
|
|
76
|
+
for (const [index, row] of rows.entries()) {
|
|
77
|
+
const clash = taken.find(one => one.code === row.code && one.id !== row.id) || rows.find((other, at) => at < index && other.code === row.code);
|
|
78
|
+
if (clash)
|
|
79
|
+
throw new shell_1.Refusal('sales-product-code-duplicate', { code: row.code }, `Product code ${row.code} is already in use`);
|
|
80
|
+
}
|
|
81
|
+
const saved = [];
|
|
82
|
+
for (const row of rows)
|
|
83
|
+
saved.push(await repository.save({ ...row, domain, ...(row.id ? {} : { creator: user }), updater: user }));
|
|
84
|
+
return saved;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=sales-product-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sales-product-service.js","sourceRoot":"","sources":["../../../server/service/sales-product/sales-product-service.ts"],"names":[],"mappings":"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","sourcesContent":["import { currencyDigits } from '@things-factory/invoice'\nimport { Domain, Refusal } from '@things-factory/shell'\nimport { EntityManager, In } from 'typeorm'\n\nimport { SalesProduct } from './sales-product'\nimport { SalesProductKind, unitOf } from './sales-product-rules'\nimport { SalesProductPatch } from './sales-product-type'\n\nconst TEXT = ['grade', 'spec', 'description'] as const\n\n/** A patch as the row it writes: words trimmed, the unit the kind's when blank, the price and currency checked. */\nfunction rowOf(patch: SalesProductPatch, old?: SalesProduct): Partial<SalesProduct> {\n const row: Record<string, any> = {}\n if (patch.code !== undefined || !old) {\n const code = String(patch.code ?? '').trim()\n if (!code) throw new Refusal('sales-product-code-required', {}, 'Give the product a code')\n row.code = code\n }\n if (patch.name !== undefined || !old) {\n const name = String(patch.name ?? '').trim()\n if (!name) throw new Refusal('sales-product-name-required', {}, 'Name the product')\n row.name = name\n }\n const kind = patch.kind ?? old?.kind ?? SalesProductKind.GOODS\n row.kind = kind\n for (const field of TEXT) if (patch[field] !== undefined) row[field] = String(patch[field] ?? '').trim() || null\n /* A blank unit is the kind's - also when the kind changes and the unit was the old kind's own. */\n if (patch.unit !== undefined || !old) row.unit = unitOf(kind, patch.unit)\n else if (patch.kind !== undefined) row.unit = old.unit === unitOf(old.kind) ? unitOf(kind) : old.unit\n if (patch.currency !== undefined || !old) {\n row.currency = (String(patch.currency ?? '').trim() || 'KRW').toUpperCase()\n currencyDigits(row.currency)\n }\n if (patch.unitPrice !== undefined || !old) {\n const price = patch.unitPrice ?? 0\n if (!Number.isFinite(price) || price < 0) throw new Refusal('sales-product-price-invalid', {}, 'The price is zero or more')\n row.unitPrice = price\n }\n if (patch.taxKind !== undefined || !old) row.taxKind = patch.taxKind ?? 'TAXABLE'\n if (patch.active !== undefined || !old) row.active = patch.active !== false\n return row\n}\n\n/**\n * Apply grid rows to a domain's products: `+` (or no id) registers, `M` changes, `-` deletes (softly). A code is the\n * domain's once among the products not deleted. Nothing names a product - a quotation line copies what it says - so a\n * product is deleted freely.\n */\nexport async function saveSalesProducts(tx: EntityManager, domain: Domain, user: any, patches: SalesProductPatch[]) {\n const repository = tx.getRepository(SalesProduct)\n const deletes = patches.filter(one => one.cuFlag === '-' && one.id).map(one => one.id!)\n const changes = patches.filter(one => one.cuFlag !== '-')\n\n if (deletes.length) {\n const owned = await repository.find({ where: { domain: { id: domain.id }, id: In(deletes) }, select: ['id'] })\n if (owned.length !== deletes.length) throw new Refusal('sales-product-not-found', {}, 'A product was not found - reload and try again')\n await repository.softDelete({ id: In(deletes) })\n }\n\n const rows: Partial<SalesProduct>[] = []\n for (const patch of changes) {\n const old = patch.id && patch.cuFlag !== '+' ? await repository.findOne({ where: { domain: { id: domain.id }, id: patch.id } }) : undefined\n if (patch.id && patch.cuFlag !== '+' && !old) throw new Refusal('sales-product-not-found', {}, 'A product was not found - reload and try again')\n rows.push({ ...(old ?? {}), ...rowOf(patch, old ?? undefined) })\n }\n\n /* One code, one product: against the rows kept and against one another in the batch. */\n const codes = rows.map(row => row.code!)\n const taken = codes.length ? await repository.find({ where: { domain: { id: domain.id }, code: In(codes) }, select: ['id', 'code'] }) : []\n for (const [index, row] of rows.entries()) {\n const clash = taken.find(one => one.code === row.code && one.id !== row.id) || rows.find((other, at) => at < index && other.code === row.code)\n if (clash) throw new Refusal('sales-product-code-duplicate', { code: row.code }, `Product code ${row.code} is already in use`)\n }\n\n const saved: SalesProduct[] = []\n for (const row of rows) saved.push(await repository.save({ ...row, domain, ...(row.id ? {} : { creator: user }), updater: user } as SalesProduct))\n return saved\n}\n"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { TaxKind } from '@things-factory/invoice';
|
|
2
|
+
import { SalesProduct } from './sales-product';
|
|
3
|
+
import { SalesProductKind } from './sales-product-rules';
|
|
4
|
+
export declare class SalesProductPatch {
|
|
5
|
+
id?: string;
|
|
6
|
+
cuFlag?: string;
|
|
7
|
+
code?: string;
|
|
8
|
+
name?: string;
|
|
9
|
+
kind?: SalesProductKind;
|
|
10
|
+
grade?: string;
|
|
11
|
+
spec?: string;
|
|
12
|
+
unit?: string;
|
|
13
|
+
unitPrice?: number;
|
|
14
|
+
currency?: string;
|
|
15
|
+
taxKind?: TaxKind;
|
|
16
|
+
active?: boolean;
|
|
17
|
+
description?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare class SalesProductList {
|
|
20
|
+
items: SalesProduct[];
|
|
21
|
+
total: number;
|
|
22
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SalesProductList = exports.SalesProductPatch = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const invoice_1 = require("@things-factory/invoice");
|
|
6
|
+
const type_graphql_1 = require("type-graphql");
|
|
7
|
+
const sales_product_1 = require("./sales-product");
|
|
8
|
+
const sales_product_rules_1 = require("./sales-product-rules");
|
|
9
|
+
let SalesProductPatch = class SalesProductPatch {
|
|
10
|
+
};
|
|
11
|
+
exports.SalesProductPatch = SalesProductPatch;
|
|
12
|
+
tslib_1.__decorate([
|
|
13
|
+
(0, type_graphql_1.Field)(type => type_graphql_1.ID, { nullable: true, description: 'The product; empty for a new one' }),
|
|
14
|
+
tslib_1.__metadata("design:type", String)
|
|
15
|
+
], SalesProductPatch.prototype, "id", void 0);
|
|
16
|
+
tslib_1.__decorate([
|
|
17
|
+
(0, type_graphql_1.Field)({ nullable: true, description: 'Grid flag: + new, M changed, - deleted' }),
|
|
18
|
+
tslib_1.__metadata("design:type", String)
|
|
19
|
+
], SalesProductPatch.prototype, "cuFlag", void 0);
|
|
20
|
+
tslib_1.__decorate([
|
|
21
|
+
(0, type_graphql_1.Field)({ nullable: true, description: 'Code of the product, unique in the domain' }),
|
|
22
|
+
tslib_1.__metadata("design:type", String)
|
|
23
|
+
], SalesProductPatch.prototype, "code", void 0);
|
|
24
|
+
tslib_1.__decorate([
|
|
25
|
+
(0, type_graphql_1.Field)({ nullable: true, description: 'What the product is called' }),
|
|
26
|
+
tslib_1.__metadata("design:type", String)
|
|
27
|
+
], SalesProductPatch.prototype, "name", void 0);
|
|
28
|
+
tslib_1.__decorate([
|
|
29
|
+
(0, type_graphql_1.Field)(type => sales_product_rules_1.SalesProductKind, { nullable: true, description: 'Goods, a service or labor; goods when empty' }),
|
|
30
|
+
tslib_1.__metadata("design:type", String)
|
|
31
|
+
], SalesProductPatch.prototype, "kind", void 0);
|
|
32
|
+
tslib_1.__decorate([
|
|
33
|
+
(0, type_graphql_1.Field)({ nullable: true, description: 'Grade of the people, for labor' }),
|
|
34
|
+
tslib_1.__metadata("design:type", String)
|
|
35
|
+
], SalesProductPatch.prototype, "grade", void 0);
|
|
36
|
+
tslib_1.__decorate([
|
|
37
|
+
(0, type_graphql_1.Field)({ nullable: true, description: 'Specification' }),
|
|
38
|
+
tslib_1.__metadata("design:type", String)
|
|
39
|
+
], SalesProductPatch.prototype, "spec", void 0);
|
|
40
|
+
tslib_1.__decorate([
|
|
41
|
+
(0, type_graphql_1.Field)({ nullable: true, description: 'Unit it is sold in; the kind gives it when empty' }),
|
|
42
|
+
tslib_1.__metadata("design:type", String)
|
|
43
|
+
], SalesProductPatch.prototype, "unit", void 0);
|
|
44
|
+
tslib_1.__decorate([
|
|
45
|
+
(0, type_graphql_1.Field)(type => type_graphql_1.Float, { nullable: true, description: 'Price of one unit, before tax' }),
|
|
46
|
+
tslib_1.__metadata("design:type", Number)
|
|
47
|
+
], SalesProductPatch.prototype, "unitPrice", void 0);
|
|
48
|
+
tslib_1.__decorate([
|
|
49
|
+
(0, type_graphql_1.Field)({ nullable: true, description: 'ISO 4217 currency code, KRW when empty' }),
|
|
50
|
+
tslib_1.__metadata("design:type", String)
|
|
51
|
+
], SalesProductPatch.prototype, "currency", void 0);
|
|
52
|
+
tslib_1.__decorate([
|
|
53
|
+
(0, type_graphql_1.Field)(type => invoice_1.TaxKind, { nullable: true, description: 'Taxable, zero-rated or exempt; taxable when empty' }),
|
|
54
|
+
tslib_1.__metadata("design:type", String)
|
|
55
|
+
], SalesProductPatch.prototype, "taxKind", void 0);
|
|
56
|
+
tslib_1.__decorate([
|
|
57
|
+
(0, type_graphql_1.Field)({ nullable: true, description: 'Whether it is still offered for new quotation lines' }),
|
|
58
|
+
tslib_1.__metadata("design:type", Boolean)
|
|
59
|
+
], SalesProductPatch.prototype, "active", void 0);
|
|
60
|
+
tslib_1.__decorate([
|
|
61
|
+
(0, type_graphql_1.Field)({ nullable: true, description: 'Notes' }),
|
|
62
|
+
tslib_1.__metadata("design:type", String)
|
|
63
|
+
], SalesProductPatch.prototype, "description", void 0);
|
|
64
|
+
exports.SalesProductPatch = SalesProductPatch = tslib_1.__decorate([
|
|
65
|
+
(0, type_graphql_1.InputType)({ description: 'A row of the product grid (cuFlag + for new, M for changed, - for deleted)' })
|
|
66
|
+
], SalesProductPatch);
|
|
67
|
+
let SalesProductList = class SalesProductList {
|
|
68
|
+
};
|
|
69
|
+
exports.SalesProductList = SalesProductList;
|
|
70
|
+
tslib_1.__decorate([
|
|
71
|
+
(0, type_graphql_1.Field)(type => [sales_product_1.SalesProduct], { description: 'Products on the page' }),
|
|
72
|
+
tslib_1.__metadata("design:type", Array)
|
|
73
|
+
], SalesProductList.prototype, "items", void 0);
|
|
74
|
+
tslib_1.__decorate([
|
|
75
|
+
(0, type_graphql_1.Field)(type => type_graphql_1.Int, { description: 'Number of products matching the list parameters' }),
|
|
76
|
+
tslib_1.__metadata("design:type", Number)
|
|
77
|
+
], SalesProductList.prototype, "total", void 0);
|
|
78
|
+
exports.SalesProductList = SalesProductList = tslib_1.__decorate([
|
|
79
|
+
(0, type_graphql_1.ObjectType)({ description: 'A page of sales products' })
|
|
80
|
+
], SalesProductList);
|
|
81
|
+
//# sourceMappingURL=sales-product-type.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sales-product-type.js","sourceRoot":"","sources":["../../../server/service/sales-product/sales-product-type.ts"],"names":[],"mappings":";;;;AAAA,qDAAiD;AACjD,+CAA2E;AAE3E,mDAA8C;AAC9C,+DAAwD;AAGjD,IAAM,iBAAiB,GAAvB,MAAM,iBAAiB;CAc7B,CAAA;AAdY,8CAAiB;AAC4D;IAAvF,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,kCAAkC,EAAE,CAAC;;6CAAY;AACjB;IAAjF,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,wCAAwC,EAAE,CAAC;;iDAAgB;AACZ;IAApF,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,2CAA2C,EAAE,CAAC;;+CAAc;AAC5B;IAArE,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,4BAA4B,EAAE,CAAC;;+CAAc;AAC8B;IAAhH,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,sCAAgB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,6CAA6C,EAAE,CAAC;;+CAAwB;AAC9D;IAAzE,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,gCAAgC,EAAE,CAAC;;gDAAe;AAC/B;IAAxD,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,eAAe,EAAE,CAAC;;+CAAc;AACsB;IAA3F,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,kDAAkD,EAAE,CAAC;;+CAAc;AACjB;IAAvF,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,oBAAK,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,+BAA+B,EAAE,CAAC;;oDAAmB;AACxB;IAAjF,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,wCAAwC,EAAE,CAAC;;mDAAkB;AACW;IAA7G,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,mDAAmD,EAAE,CAAC;;kDAAkB;AAChC;IAA9F,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,qDAAqD,EAAE,CAAC;;iDAAiB;AAC9D;IAAhD,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC;;sDAAqB;4BAb1D,iBAAiB;IAD7B,IAAA,wBAAS,EAAC,EAAE,WAAW,EAAE,4EAA4E,EAAE,CAAC;GAC5F,iBAAiB,CAc7B;AAGM,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;CAG5B,CAAA;AAHY,4CAAgB;AAC6C;IAAvE,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,4BAAY,CAAC,EAAE,EAAE,WAAW,EAAE,sBAAsB,EAAE,CAAC;;+CAAsB;AACL;IAAvF,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,kBAAG,EAAE,EAAE,WAAW,EAAE,iDAAiD,EAAE,CAAC;;+CAAc;2BAF1F,gBAAgB;IAD5B,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,0BAA0B,EAAE,CAAC;GAC3C,gBAAgB,CAG5B","sourcesContent":["import { TaxKind } from '@things-factory/invoice'\nimport { Field, Float, ID, InputType, Int, ObjectType } from 'type-graphql'\n\nimport { SalesProduct } from './sales-product'\nimport { SalesProductKind } from './sales-product-rules'\n\n@InputType({ description: 'A row of the product grid (cuFlag + for new, M for changed, - for deleted)' })\nexport class SalesProductPatch {\n @Field(type => ID, { nullable: true, description: 'The product; empty for a new one' }) id?: string\n @Field({ nullable: true, description: 'Grid flag: + new, M changed, - deleted' }) cuFlag?: string\n @Field({ nullable: true, description: 'Code of the product, unique in the domain' }) code?: string\n @Field({ nullable: true, description: 'What the product is called' }) name?: string\n @Field(type => SalesProductKind, { nullable: true, description: 'Goods, a service or labor; goods when empty' }) kind?: SalesProductKind\n @Field({ nullable: true, description: 'Grade of the people, for labor' }) grade?: string\n @Field({ nullable: true, description: 'Specification' }) spec?: string\n @Field({ nullable: true, description: 'Unit it is sold in; the kind gives it when empty' }) unit?: string\n @Field(type => Float, { nullable: true, description: 'Price of one unit, before tax' }) unitPrice?: number\n @Field({ nullable: true, description: 'ISO 4217 currency code, KRW when empty' }) currency?: string\n @Field(type => TaxKind, { nullable: true, description: 'Taxable, zero-rated or exempt; taxable when empty' }) taxKind?: TaxKind\n @Field({ nullable: true, description: 'Whether it is still offered for new quotation lines' }) active?: boolean\n @Field({ nullable: true, description: 'Notes' }) description?: string\n}\n\n@ObjectType({ description: 'A page of sales products' })\nexport class SalesProductList {\n @Field(type => [SalesProduct], { description: 'Products on the page' }) items: SalesProduct[]\n @Field(type => Int, { description: 'Number of products matching the list parameters' }) total: number\n}\n"]}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { User } from '@things-factory/auth-base';
|
|
2
|
+
import { TaxKind } from '@things-factory/invoice';
|
|
3
|
+
import { Domain } from '@things-factory/shell';
|
|
4
|
+
import { SalesProductKind } from './sales-product-rules';
|
|
5
|
+
/**
|
|
6
|
+
* A product the domain sells - goods, a service, or the labor of people of a grade - with the price it is offered at
|
|
7
|
+
* (ADR-0171). A quotation line chosen from it copies its name, unit, price and taxation at that moment; the line is the
|
|
8
|
+
* quotation's from then on, and a later price here never changes a written quotation.
|
|
9
|
+
*/
|
|
10
|
+
export declare class SalesProduct {
|
|
11
|
+
readonly id: string;
|
|
12
|
+
domain?: Domain;
|
|
13
|
+
domainId?: string;
|
|
14
|
+
code: string;
|
|
15
|
+
name: string;
|
|
16
|
+
kind: SalesProductKind;
|
|
17
|
+
grade?: string;
|
|
18
|
+
spec?: string;
|
|
19
|
+
unit: string;
|
|
20
|
+
unitPrice: number;
|
|
21
|
+
currency: string;
|
|
22
|
+
taxKind: TaxKind;
|
|
23
|
+
active: boolean;
|
|
24
|
+
description?: string;
|
|
25
|
+
createdAt?: Date;
|
|
26
|
+
updatedAt?: Date;
|
|
27
|
+
deletedAt?: Date;
|
|
28
|
+
creator?: User;
|
|
29
|
+
creatorId?: string;
|
|
30
|
+
updater?: User;
|
|
31
|
+
updaterId?: string;
|
|
32
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SalesProduct = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const auth_base_1 = require("@things-factory/auth-base");
|
|
6
|
+
const invoice_1 = require("@things-factory/invoice");
|
|
7
|
+
const shell_1 = require("@things-factory/shell");
|
|
8
|
+
const type_graphql_1 = require("type-graphql");
|
|
9
|
+
const typeorm_1 = require("typeorm");
|
|
10
|
+
const sales_product_rules_1 = require("./sales-product-rules");
|
|
11
|
+
/**
|
|
12
|
+
* A product the domain sells - goods, a service, or the labor of people of a grade - with the price it is offered at
|
|
13
|
+
* (ADR-0171). A quotation line chosen from it copies its name, unit, price and taxation at that moment; the line is the
|
|
14
|
+
* quotation's from then on, and a later price here never changes a written quotation.
|
|
15
|
+
*/
|
|
16
|
+
let SalesProduct = class SalesProduct {
|
|
17
|
+
};
|
|
18
|
+
exports.SalesProduct = SalesProduct;
|
|
19
|
+
tslib_1.__decorate([
|
|
20
|
+
(0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
|
|
21
|
+
(0, type_graphql_1.Field)(type => type_graphql_1.ID),
|
|
22
|
+
tslib_1.__metadata("design:type", String)
|
|
23
|
+
], SalesProduct.prototype, "id", void 0);
|
|
24
|
+
tslib_1.__decorate([
|
|
25
|
+
(0, typeorm_1.ManyToOne)(type => shell_1.Domain),
|
|
26
|
+
(0, type_graphql_1.Field)(type => shell_1.Domain, { nullable: true }),
|
|
27
|
+
tslib_1.__metadata("design:type", shell_1.Domain)
|
|
28
|
+
], SalesProduct.prototype, "domain", void 0);
|
|
29
|
+
tslib_1.__decorate([
|
|
30
|
+
(0, typeorm_1.RelationId)((product) => product.domain),
|
|
31
|
+
tslib_1.__metadata("design:type", String)
|
|
32
|
+
], SalesProduct.prototype, "domainId", void 0);
|
|
33
|
+
tslib_1.__decorate([
|
|
34
|
+
(0, typeorm_1.Column)(),
|
|
35
|
+
(0, type_graphql_1.Field)({ description: 'Code of the product, unique in the domain' }),
|
|
36
|
+
tslib_1.__metadata("design:type", String)
|
|
37
|
+
], SalesProduct.prototype, "code", void 0);
|
|
38
|
+
tslib_1.__decorate([
|
|
39
|
+
(0, typeorm_1.Column)(),
|
|
40
|
+
(0, type_graphql_1.Field)({ description: 'What the product is called, as a quotation line prints it' }),
|
|
41
|
+
tslib_1.__metadata("design:type", String)
|
|
42
|
+
], SalesProduct.prototype, "name", void 0);
|
|
43
|
+
tslib_1.__decorate([
|
|
44
|
+
(0, typeorm_1.Column)({ default: sales_product_rules_1.SalesProductKind.GOODS }),
|
|
45
|
+
(0, type_graphql_1.Field)(type => sales_product_rules_1.SalesProductKind, { description: 'Goods, a service or labor' }),
|
|
46
|
+
tslib_1.__metadata("design:type", String)
|
|
47
|
+
], SalesProduct.prototype, "kind", void 0);
|
|
48
|
+
tslib_1.__decorate([
|
|
49
|
+
(0, typeorm_1.Column)({ nullable: true }),
|
|
50
|
+
(0, type_graphql_1.Field)({ nullable: true, description: 'Grade of the people, for labor - a senior or a junior engineer' }),
|
|
51
|
+
tslib_1.__metadata("design:type", String)
|
|
52
|
+
], SalesProduct.prototype, "grade", void 0);
|
|
53
|
+
tslib_1.__decorate([
|
|
54
|
+
(0, typeorm_1.Column)({ nullable: true }),
|
|
55
|
+
(0, type_graphql_1.Field)({ nullable: true, description: 'Specification, printed after the name' }),
|
|
56
|
+
tslib_1.__metadata("design:type", String)
|
|
57
|
+
], SalesProduct.prototype, "spec", void 0);
|
|
58
|
+
tslib_1.__decorate([
|
|
59
|
+
(0, typeorm_1.Column)(),
|
|
60
|
+
(0, type_graphql_1.Field)({ description: 'Unit it is sold in - pieces for goods, a lot for a service, man-months for labor unless written' }),
|
|
61
|
+
tslib_1.__metadata("design:type", String)
|
|
62
|
+
], SalesProduct.prototype, "unit", void 0);
|
|
63
|
+
tslib_1.__decorate([
|
|
64
|
+
(0, typeorm_1.Column)({ ...(0, shell_1.moneyColumn)({ scale: 4 }), default: 0 }),
|
|
65
|
+
(0, type_graphql_1.Field)(type => type_graphql_1.Float, { description: 'Price of one unit, before tax' }),
|
|
66
|
+
tslib_1.__metadata("design:type", Number)
|
|
67
|
+
], SalesProduct.prototype, "unitPrice", void 0);
|
|
68
|
+
tslib_1.__decorate([
|
|
69
|
+
(0, typeorm_1.Column)({ default: 'KRW' }),
|
|
70
|
+
(0, type_graphql_1.Field)({ description: 'ISO 4217 currency code of the price' }),
|
|
71
|
+
tslib_1.__metadata("design:type", String)
|
|
72
|
+
], SalesProduct.prototype, "currency", void 0);
|
|
73
|
+
tslib_1.__decorate([
|
|
74
|
+
(0, typeorm_1.Column)({ default: invoice_1.TaxKind.TAXABLE }),
|
|
75
|
+
(0, type_graphql_1.Field)(type => invoice_1.TaxKind, { description: 'Taxable, zero-rated or exempt' }),
|
|
76
|
+
tslib_1.__metadata("design:type", String)
|
|
77
|
+
], SalesProduct.prototype, "taxKind", void 0);
|
|
78
|
+
tslib_1.__decorate([
|
|
79
|
+
(0, typeorm_1.Column)({ default: true }),
|
|
80
|
+
(0, type_graphql_1.Field)({ description: 'Whether it is still offered for new quotation lines' }),
|
|
81
|
+
tslib_1.__metadata("design:type", Boolean)
|
|
82
|
+
], SalesProduct.prototype, "active", void 0);
|
|
83
|
+
tslib_1.__decorate([
|
|
84
|
+
(0, typeorm_1.Column)({ type: 'text', nullable: true }),
|
|
85
|
+
(0, type_graphql_1.Field)({ nullable: true, description: 'Notes' }),
|
|
86
|
+
tslib_1.__metadata("design:type", String)
|
|
87
|
+
], SalesProduct.prototype, "description", void 0);
|
|
88
|
+
tslib_1.__decorate([
|
|
89
|
+
(0, typeorm_1.CreateDateColumn)(),
|
|
90
|
+
(0, type_graphql_1.Field)({ nullable: true, description: 'When the product was registered' }),
|
|
91
|
+
tslib_1.__metadata("design:type", Date)
|
|
92
|
+
], SalesProduct.prototype, "createdAt", void 0);
|
|
93
|
+
tslib_1.__decorate([
|
|
94
|
+
(0, typeorm_1.UpdateDateColumn)(),
|
|
95
|
+
(0, type_graphql_1.Field)({ nullable: true, description: 'When the product last changed' }),
|
|
96
|
+
tslib_1.__metadata("design:type", Date)
|
|
97
|
+
], SalesProduct.prototype, "updatedAt", void 0);
|
|
98
|
+
tslib_1.__decorate([
|
|
99
|
+
(0, typeorm_1.DeleteDateColumn)(),
|
|
100
|
+
(0, type_graphql_1.Field)({ nullable: true, description: 'When the product was deleted' }),
|
|
101
|
+
tslib_1.__metadata("design:type", Date)
|
|
102
|
+
], SalesProduct.prototype, "deletedAt", void 0);
|
|
103
|
+
tslib_1.__decorate([
|
|
104
|
+
(0, typeorm_1.ManyToOne)(type => auth_base_1.User, { nullable: true }),
|
|
105
|
+
(0, type_graphql_1.Field)(type => auth_base_1.User, { nullable: true }),
|
|
106
|
+
tslib_1.__metadata("design:type", auth_base_1.User)
|
|
107
|
+
], SalesProduct.prototype, "creator", void 0);
|
|
108
|
+
tslib_1.__decorate([
|
|
109
|
+
(0, typeorm_1.RelationId)((product) => product.creator),
|
|
110
|
+
tslib_1.__metadata("design:type", String)
|
|
111
|
+
], SalesProduct.prototype, "creatorId", void 0);
|
|
112
|
+
tslib_1.__decorate([
|
|
113
|
+
(0, typeorm_1.ManyToOne)(type => auth_base_1.User, { nullable: true }),
|
|
114
|
+
(0, type_graphql_1.Field)(type => auth_base_1.User, { nullable: true }),
|
|
115
|
+
tslib_1.__metadata("design:type", auth_base_1.User)
|
|
116
|
+
], SalesProduct.prototype, "updater", void 0);
|
|
117
|
+
tslib_1.__decorate([
|
|
118
|
+
(0, typeorm_1.RelationId)((product) => product.updater),
|
|
119
|
+
tslib_1.__metadata("design:type", String)
|
|
120
|
+
], SalesProduct.prototype, "updaterId", void 0);
|
|
121
|
+
exports.SalesProduct = SalesProduct = tslib_1.__decorate([
|
|
122
|
+
(0, typeorm_1.Entity)(),
|
|
123
|
+
(0, typeorm_1.Index)('ix_sales_product_0', (product) => [product.domain, product.code], { unique: true, where: '"deleted_at" IS NULL' }),
|
|
124
|
+
(0, type_graphql_1.ObjectType)({ description: 'Entity for SalesProduct — a product the domain sells, and its price' })
|
|
125
|
+
], SalesProduct);
|
|
126
|
+
//# sourceMappingURL=sales-product.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sales-product.js","sourceRoot":"","sources":["../../../server/service/sales-product/sales-product.ts"],"names":[],"mappings":"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","sourcesContent":["import { User } from '@things-factory/auth-base'\nimport { TaxKind } from '@things-factory/invoice'\nimport { Domain, moneyColumn } from '@things-factory/shell'\nimport { Field, Float, ID, ObjectType } from 'type-graphql'\nimport { Column, CreateDateColumn, DeleteDateColumn, Entity, Index, ManyToOne, PrimaryGeneratedColumn, RelationId, UpdateDateColumn } from 'typeorm'\n\nimport { SalesProductKind } from './sales-product-rules'\n\n/**\n * A product the domain sells - goods, a service, or the labor of people of a grade - with the price it is offered at\n * (ADR-0171). A quotation line chosen from it copies its name, unit, price and taxation at that moment; the line is the\n * quotation's from then on, and a later price here never changes a written quotation.\n */\n@Entity()\n@Index('ix_sales_product_0', (product: SalesProduct) => [product.domain, product.code], { unique: true, where: '\"deleted_at\" IS NULL' })\n@ObjectType({ description: 'Entity for SalesProduct — a product the domain sells, and its price' })\nexport class SalesProduct {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID)\n readonly id: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { nullable: true })\n domain?: Domain\n\n @RelationId((product: SalesProduct) => product.domain)\n domainId?: string\n\n @Column()\n @Field({ description: 'Code of the product, unique in the domain' })\n code: string\n\n @Column()\n @Field({ description: 'What the product is called, as a quotation line prints it' })\n name: string\n\n @Column({ default: SalesProductKind.GOODS })\n @Field(type => SalesProductKind, { description: 'Goods, a service or labor' })\n kind: SalesProductKind\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Grade of the people, for labor - a senior or a junior engineer' })\n grade?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Specification, printed after the name' })\n spec?: string\n\n @Column()\n @Field({ description: 'Unit it is sold in - pieces for goods, a lot for a service, man-months for labor unless written' })\n unit: string\n\n @Column({ ...moneyColumn({ scale: 4 }), default: 0 })\n @Field(type => Float, { description: 'Price of one unit, before tax' })\n unitPrice: number\n\n @Column({ default: 'KRW' })\n @Field({ description: 'ISO 4217 currency code of the price' })\n currency: string\n\n @Column({ default: TaxKind.TAXABLE })\n @Field(type => TaxKind, { description: 'Taxable, zero-rated or exempt' })\n taxKind: TaxKind\n\n @Column({ default: true })\n @Field({ description: 'Whether it is still offered for new quotation lines' })\n active: boolean\n\n @Column({ type: 'text', nullable: true })\n @Field({ nullable: true, description: 'Notes' })\n description?: string\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'When the product was registered' })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true, description: 'When the product last changed' })\n updatedAt?: Date\n\n @DeleteDateColumn()\n @Field({ nullable: true, description: 'When the product was deleted' })\n deletedAt?: Date\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true })\n creator?: User\n\n @RelationId((product: SalesProduct) => product.creator)\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true })\n updater?: User\n\n @RelationId((product: SalesProduct) => product.updater)\n updaterId?: string\n}\n"]}
|