@things-factory/saas 10.1.236 → 10.1.239
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/components/saas-candidates.d.ts +33 -0
- package/dist-client/components/saas-candidates.js +157 -0
- package/dist-client/components/saas-candidates.js.map +1 -0
- 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/saas-account-list.js +3 -0
- package/dist-client/pages/saas-account-list.js.map +1 -1
- package/dist-client/pages/saas-account-page.js +7 -2
- package/dist-client/pages/saas-account-page.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/role-tasks.js +3 -1
- package/dist-server/role-tasks.js.map +1 -1
- package/dist-server/service/checks.d.ts +4 -1
- package/dist-server/service/checks.js +5 -2
- package/dist-server/service/checks.js.map +1 -1
- package/dist-server/service/index.d.ts +4 -1
- package/dist-server/service/index.js +5 -1
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/service/saas-bill.d.ts +1 -0
- package/dist-server/service/saas-bill.js +5 -0
- package/dist-server/service/saas-bill.js.map +1 -1
- package/dist-server/service/saas-hidden-vendor.d.ts +19 -0
- package/dist-server/service/saas-hidden-vendor.js +53 -0
- package/dist-server/service/saas-hidden-vendor.js.map +1 -0
- package/dist-server/service/saas-mutation.d.ts +8 -1
- package/dist-server/service/saas-mutation.js +69 -0
- package/dist-server/service/saas-mutation.js.map +1 -1
- package/dist-server/service/saas-query.d.ts +2 -1
- package/dist-server/service/saas-query.js +16 -0
- package/dist-server/service/saas-query.js.map +1 -1
- package/dist-server/service/saas-rules.d.ts +41 -0
- package/dist-server/service/saas-rules.js +49 -1
- package/dist-server/service/saas-rules.js.map +1 -1
- package/dist-server/service/saas-seat.d.ts +1 -0
- package/dist-server/service/saas-seat.js +5 -0
- package/dist-server/service/saas-seat.js.map +1 -1
- package/dist-server/service/saas-service.d.ts +30 -7
- package/dist-server/service/saas-service.js +136 -17
- package/dist-server/service/saas-service.js.map +1 -1
- package/dist-server/service/saas-subscription.d.ts +2 -0
- package/dist-server/service/saas-subscription.js +10 -0
- package/dist-server/service/saas-subscription.js.map +1 -1
- package/dist-server/service/saas-sync.d.ts +69 -0
- package/dist-server/service/saas-sync.js +166 -0
- package/dist-server/service/saas-sync.js.map +1 -0
- package/dist-server/service/saas-type.d.ts +69 -0
- package/dist-server/service/saas-type.js +257 -1
- package/dist-server/service/saas-type.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/translations/en.json +24 -0
- package/translations/es.json +24 -0
- package/translations/ja.json +24 -0
- package/translations/ko.json +24 -0
- package/translations/ms.json +24 -0
- package/translations/zh.json +24 -0
|
@@ -12,10 +12,13 @@ exports.billsOf = billsOf;
|
|
|
12
12
|
exports.saasBillsOf = saasBillsOf;
|
|
13
13
|
exports.saasExpected = saasExpected;
|
|
14
14
|
exports.saasCostTrend = saasCostTrend;
|
|
15
|
-
exports.
|
|
15
|
+
exports.vendorLinesOf = vendorLinesOf;
|
|
16
16
|
exports.saasPaymentsOf = saasPaymentsOf;
|
|
17
17
|
exports.saasTrendsOf = saasTrendsOf;
|
|
18
18
|
exports.saasChangesOf = saasChangesOf;
|
|
19
|
+
exports.saasCandidatesOf = saasCandidatesOf;
|
|
20
|
+
exports.createSaasAccountsFromCandidates = createSaasAccountsFromCandidates;
|
|
21
|
+
exports.hideSaasCandidates = hideSaasCandidates;
|
|
19
22
|
const accounting_1 = require("@things-factory/accounting");
|
|
20
23
|
const asset_1 = require("@things-factory/asset");
|
|
21
24
|
/* The register grids' save, the asset module's - this module saves its grids the same way (one implementation). */
|
|
@@ -28,6 +31,7 @@ const typeorm_1 = require("typeorm");
|
|
|
28
31
|
const saas_access_1 = require("./saas-access");
|
|
29
32
|
const saas_account_1 = require("./saas-account");
|
|
30
33
|
const saas_bill_1 = require("./saas-bill");
|
|
34
|
+
const saas_hidden_vendor_1 = require("./saas-hidden-vendor");
|
|
31
35
|
const saas_rules_1 = require("./saas-rules");
|
|
32
36
|
const saas_seat_1 = require("./saas-seat");
|
|
33
37
|
const saas_subscription_1 = require("./saas-subscription");
|
|
@@ -63,7 +67,7 @@ const field = (patch, name, old) => (patch[name] !== undefined ? patch[name] : o
|
|
|
63
67
|
exports.SAAS_ACCOUNT_FACT = 'saas-account';
|
|
64
68
|
exports.SAAS_SUBSCRIPTION_FACT = 'saas-subscription';
|
|
65
69
|
const ACCOUNT_TRACKED = ['name', 'counterpartyId', 'identifier', 'parentId', 'paymentAccountId', 'currency', 'billingDay', 'increaseAlertRate', 'status', 'closedOn'];
|
|
66
|
-
const SUBSCRIPTION_TRACKED = ['name', 'billing', 'quantity', 'unitPrice', 'amount', 'budget', 'everyMonths', 'startOn', 'renewalOn', 'autoRenew', 'noticeDays', 'departmentId', 'assetId', 'status', 'endedOn'];
|
|
70
|
+
const SUBSCRIPTION_TRACKED = ['name', 'billing', 'vendorKey', 'trial', 'quantity', 'unitPrice', 'amount', 'budget', 'everyMonths', 'startOn', 'renewalOn', 'autoRenew', 'noticeDays', 'departmentId', 'assetId', 'status', 'endedOn'];
|
|
67
71
|
const idsOf = (row) => Object.fromEntries(Object.entries(row).map(([key, value]) => (value && typeof value === 'object' && 'id' in value ? [`${key}Id`, value.id] : value === null && ['counterparty', 'parent', 'paymentAccount', 'department', 'asset'].includes(key) ? [`${key}Id`, null] : [key, value])));
|
|
68
72
|
async function recordChanges(tx, domain, user, factKind, old, row, fields) {
|
|
69
73
|
if (!old)
|
|
@@ -73,8 +77,8 @@ async function recordChanges(tx, domain, user, factKind, old, row, fields) {
|
|
|
73
77
|
}
|
|
74
78
|
/* ----------------------------------------------------------------------------------------------------------------- */
|
|
75
79
|
/* Accounts (decision 2) - kept by `saas` keepers only */
|
|
76
|
-
function saveSaasAccounts(tx, domain, user, patches) {
|
|
77
|
-
|
|
80
|
+
async function saveSaasAccounts(tx, domain, user, patches) {
|
|
81
|
+
const saved = await (0, patches_js_1.applyPatches)(tx, saas_account_1.SaasAccount, domain, user, patches, async (patch, old) => {
|
|
78
82
|
const row = {};
|
|
79
83
|
const name = (0, patches_js_1.touched)(patch, 'name', old) ? (0, patches_js_1.textOf)(patch.name) : old.name;
|
|
80
84
|
if (!name)
|
|
@@ -121,6 +125,11 @@ function saveSaasAccounts(tx, domain, user, patches) {
|
|
|
121
125
|
await recordChanges(tx, domain, user, exports.SAAS_ACCOUNT_FACT, old, row, ACCOUNT_TRACKED);
|
|
122
126
|
return row;
|
|
123
127
|
}, 'saas-account-not-found');
|
|
128
|
+
/* The vendor's lines written with its name and not linked yet are the account's months (개정 1). */
|
|
129
|
+
const vendors = patches.filter(one => one.cuFlag !== '-' && one.counterpartyId).map(one => one.counterpartyId);
|
|
130
|
+
if (vendors.length)
|
|
131
|
+
await (0, accounting_1.linkLinesByName)(tx, domain, user, vendors);
|
|
132
|
+
return saved;
|
|
124
133
|
}
|
|
125
134
|
/* ----------------------------------------------------------------------------------------------------------------- */
|
|
126
135
|
/* Subscriptions (decision 3) - by keepers, and by the account's admins */
|
|
@@ -141,8 +150,15 @@ async function saveSaasSubscriptions(tx, domain, user, scope, accountId, patches
|
|
|
141
150
|
for (const one of ['quantity', 'unitPrice', 'amount', 'budget'])
|
|
142
151
|
if ((0, patches_js_1.touched)(patch, one, old))
|
|
143
152
|
row[one] = (0, patches_js_1.amountOf)(patch[one], 'saas-amount-invalid');
|
|
153
|
+
/* `vendorKey` and `trial` are a sync's (개정 2) - the GraphQL patch does not carry them. */
|
|
154
|
+
if ((0, patches_js_1.touched)(patch, 'vendorKey', old))
|
|
155
|
+
row.vendorKey = (0, patches_js_1.textOf)(patch.vendorKey);
|
|
156
|
+
if ((0, patches_js_1.touched)(patch, 'trial', old))
|
|
157
|
+
row.trial = patch.trial === true;
|
|
144
158
|
const value = (name) => (row[name] !== undefined ? row[name] : old?.[name]);
|
|
145
|
-
|
|
159
|
+
/* A plan read from the vendor's tenant may wait for its price (개정 2) - it is expected at nothing until then. */
|
|
160
|
+
const priced = value('unitPrice') !== null && value('unitPrice') !== undefined;
|
|
161
|
+
if (billing === saas_rules_1.SaasBilling.SEAT && !(Number(value('quantity')) > 0 && (priced || value('vendorKey'))))
|
|
146
162
|
throw new shell_1.Refusal('saas-seat-price-required', {}, 'A seat plan takes its seats and the price of one');
|
|
147
163
|
if ((billing === saas_rules_1.SaasBilling.FIXED || billing === saas_rules_1.SaasBilling.COMMITMENT) && (value('amount') === null || value('amount') === undefined))
|
|
148
164
|
throw new shell_1.Refusal('saas-amount-required', {}, 'Give what one billing costs');
|
|
@@ -203,7 +219,8 @@ async function saveSaasSeats(tx, domain, user, scope, subscriptionId, patches) {
|
|
|
203
219
|
const row = old ? {} : { subscription };
|
|
204
220
|
if ((0, patches_js_1.touched)(patch, 'employeeId', old))
|
|
205
221
|
row.employee = await oneOf(tx, organization_1.Employee, domain, patch.employeeId, 'saas-seat-employee-not-found');
|
|
206
|
-
|
|
222
|
+
/* `login` is a sync's (개정 2) - the GraphQL patch does not carry it. */
|
|
223
|
+
for (const one of ['holder', 'login', 'description'])
|
|
207
224
|
if ((0, patches_js_1.touched)(patch, one, old))
|
|
208
225
|
row[one] = (0, patches_js_1.textOf)(patch[one]);
|
|
209
226
|
if (!(row.employee !== undefined ? row.employee : old?.employeeId) && !(row.holder !== undefined ? row.holder : old?.holder))
|
|
@@ -254,6 +271,8 @@ async function saveSaasBill(tx, domain, user, scope, accountId, input) {
|
|
|
254
271
|
month,
|
|
255
272
|
billedOn: (0, patches_js_1.dayOf)(input.billedOn, 'saas-day-invalid'),
|
|
256
273
|
description: (0, patches_js_1.textOf)(input.description),
|
|
274
|
+
/* Whoever writes it owns it: a person's save keeps a later sync off it (a sync marks its own, 개정 3). */
|
|
275
|
+
synced: false,
|
|
257
276
|
updater: user
|
|
258
277
|
});
|
|
259
278
|
await tx.getRepository(saas_bill_1.SaasBillLine).delete({ bill: { id: bill.id } });
|
|
@@ -419,18 +438,20 @@ async function saasCostTrend(tx, domain, from, to) {
|
|
|
419
438
|
/* ----------------------------------------------------------------------------------------------------------------- */
|
|
420
439
|
/* A row's months for the list and the 360 (decision 10) and what moved on it (decision 11) */
|
|
421
440
|
/**
|
|
422
|
-
* What
|
|
423
|
-
* - the bank
|
|
424
|
-
*
|
|
441
|
+
* What went out to an account's vendor (ADR-0177 decision 10, the user 2026-10-30: 「이테크 입금 이력이 있을텐데」;
|
|
442
|
+
* 개정 1) - the bank withdrawals and the card charges (accounting, CONFIRMED and CARD) to the account's counterparty,
|
|
443
|
+
* newest first. A line takes its counterparty when it lands (accounting `saveTransactions`), so a vendor's lines are
|
|
444
|
+
* its linked ones. Only lines in the account's currency count toward its months.
|
|
425
445
|
*/
|
|
426
|
-
async function
|
|
446
|
+
async function vendorLinesOf(tx, domain, counterpartyIds, from, to) {
|
|
427
447
|
if (!counterpartyIds.length)
|
|
428
448
|
return [];
|
|
429
449
|
const query = tx
|
|
430
450
|
.getRepository(accounting_1.Transaction)
|
|
431
451
|
.createQueryBuilder('line')
|
|
452
|
+
.leftJoinAndSelect('line.bankAccount', 'bankAccount')
|
|
432
453
|
.where('line.domain = :domain', { domain: domain.id })
|
|
433
|
-
.andWhere('line.category
|
|
454
|
+
.andWhere('line.category IN (:...categories)', { categories: [accounting_1.TransactionCategory.CONFIRMED, accounting_1.TransactionCategory.CARD] })
|
|
434
455
|
.andWhere('line.type = :type', { type: accounting_1.CashFlowType.EXPENSE })
|
|
435
456
|
.andWhere('line.counterparty IN (:...parties)', { parties: counterpartyIds });
|
|
436
457
|
if (from)
|
|
@@ -439,15 +460,15 @@ async function bankPaymentsOf(tx, domain, counterpartyIds, from, to) {
|
|
|
439
460
|
query.andWhere('line.transactionDate <= :to', { to });
|
|
440
461
|
return query.orderBy('line.transactionDate', 'DESC').addOrderBy('line.amount', 'DESC').getMany();
|
|
441
462
|
}
|
|
442
|
-
/** The bank lines that paid an account's vendor, every one - for its 360. */
|
|
463
|
+
/** The bank and card lines that paid an account's vendor, every one - for its 360. */
|
|
443
464
|
async function saasPaymentsOf(tx, domain, scope, accountId) {
|
|
444
465
|
const account = await (0, saas_access_1.accountIn)(tx, domain, scope, accountId);
|
|
445
|
-
return account.counterpartyId ?
|
|
466
|
+
return account.counterpartyId ? vendorLinesOf(tx, domain, [account.counterpartyId]) : [];
|
|
446
467
|
}
|
|
447
468
|
/**
|
|
448
469
|
* Each account's last twelve months before this one and the next three expected (`saasExpected`). A month is its bill
|
|
449
|
-
* when one is written; else, for a reader of the bank lines (`withBank`), what
|
|
450
|
-
* (decision 10); else empty. One read for all the accounts of a list.
|
|
470
|
+
* when one is written; else, for a reader of the bank lines (`withBank`), what went out to its vendor that month from
|
|
471
|
+
* the bank or a card (decision 10, 개정 1); else empty. One read for all the accounts of a list.
|
|
451
472
|
*/
|
|
452
473
|
async function saasTrendsOf(tx, domain, accounts, today, withBank = false) {
|
|
453
474
|
const trends = new Map();
|
|
@@ -459,7 +480,7 @@ async function saasTrendsOf(tx, domain, accounts, today, withBank = false) {
|
|
|
459
480
|
const bills = await billsOf(tx, domain, accounts.map(one => one.id), months[0], months[months.length - 1]);
|
|
460
481
|
const expected = await saasExpected(tx, domain, nextMonths[0], nextMonths[nextMonths.length - 1]);
|
|
461
482
|
const parties = [...new Set(accounts.map(one => one.counterpartyId).filter(Boolean))];
|
|
462
|
-
const paid = withBank ? await
|
|
483
|
+
const paid = withBank ? await vendorLinesOf(tx, domain, parties, `${months[0]}-01`, `${months[months.length - 1]}-31`) : [];
|
|
463
484
|
for (const account of accounts) {
|
|
464
485
|
const own = bills.filter(one => one.accountId === account.id);
|
|
465
486
|
const lines = paid.filter(line => line.counterpartyId === account.counterpartyId && (line.currency || 'KRW') === account.currency);
|
|
@@ -471,7 +492,13 @@ async function saasTrendsOf(tx, domain, accounts, today, withBank = false) {
|
|
|
471
492
|
trends.set(account.id, {
|
|
472
493
|
months,
|
|
473
494
|
values,
|
|
474
|
-
sources: months.map((month, i) =>
|
|
495
|
+
sources: months.map((month, i) => own.some(one => one.month === month)
|
|
496
|
+
? 'bill'
|
|
497
|
+
: values[i] === null
|
|
498
|
+
? null
|
|
499
|
+
: lines.some(line => line.transactionDate?.slice(0, 7) === month && line.category === accounting_1.TransactionCategory.CONFIRMED)
|
|
500
|
+
? 'bank'
|
|
501
|
+
: 'card'),
|
|
475
502
|
nextMonths,
|
|
476
503
|
expected: nextMonths.map(month => expected.find(one => one.accountId === account.id && one.month === month)?.amount ?? null),
|
|
477
504
|
currency: account.currency
|
|
@@ -489,4 +516,96 @@ async function saasChangesOf(tx, domain, scope, accountId) {
|
|
|
489
516
|
];
|
|
490
517
|
return rows.sort((a, b) => new Date(b.at).getTime() - new Date(a.at).getTime());
|
|
491
518
|
}
|
|
519
|
+
/**
|
|
520
|
+
* Whom the bank and card lines of the last twelve months show paid month after month that is no account yet and no
|
|
521
|
+
* recurring item - what a keeper may make an account of with one press. A line on a subject outside profit and loss
|
|
522
|
+
* (a card bill, a tax, a transfer, a loan) pays no vendor, and a person (salary, expenses) is no vendor. With `hidden`,
|
|
523
|
+
* the ones a keeper hid instead.
|
|
524
|
+
*/
|
|
525
|
+
async function saasCandidatesOf(tx, domain, today, hidden = false) {
|
|
526
|
+
const now = today.slice(0, 7);
|
|
527
|
+
const from = `${(0, saas_rules_1.shiftMonth)(now, -12)}-01`;
|
|
528
|
+
const lines = await tx
|
|
529
|
+
.getRepository(accounting_1.Transaction)
|
|
530
|
+
.createQueryBuilder('line')
|
|
531
|
+
.leftJoinAndSelect('line.account', 'subject')
|
|
532
|
+
.where('line.domain = :domain', { domain: domain.id })
|
|
533
|
+
.andWhere('line.category IN (:...categories)', { categories: [accounting_1.TransactionCategory.CONFIRMED, accounting_1.TransactionCategory.CARD] })
|
|
534
|
+
.andWhere('line.type = :type', { type: accounting_1.CashFlowType.EXPENSE })
|
|
535
|
+
.andWhere('line.transactionDate >= :from', { from })
|
|
536
|
+
.getMany();
|
|
537
|
+
const accounts = await tx.getRepository(saas_account_1.SaasAccount).find({ where: { domain: { id: domain.id } } });
|
|
538
|
+
const recurring = await tx.getRepository(accounting_1.RecurringCashItem).find({ where: { domain: { id: domain.id } } });
|
|
539
|
+
const hiddenKeys = new Set((await tx.getRepository(saas_hidden_vendor_1.SaasHiddenVendor).find({ where: { domain: { id: domain.id } } })).map(one => one.counterpartyId ?? `name:${one.nameKey}`));
|
|
540
|
+
const skip = new Set([...accounts.map(one => one.counterpartyId), ...recurring.map(one => one.counterpartyId), ...(hidden ? [] : hiddenKeys)].filter(Boolean));
|
|
541
|
+
const parties = await tx.getRepository(biz_base_1.Counterparty).find({ where: { domain: { id: domain.id } }, select: ['id', 'name', 'aliases', 'kind'] });
|
|
542
|
+
const named = (0, biz_base_1.partyNamed)(parties);
|
|
543
|
+
const people = new Set(parties.filter(one => one.kind === biz_base_1.CounterpartyKind.PERSON).map(one => one.id));
|
|
544
|
+
/* Whom a line paid: its counterparty, else the one its written name is (the rule a line is linked by), else the name. */
|
|
545
|
+
const vendorOf = (line) => {
|
|
546
|
+
const id = line.counterpartyId ?? named(line.counterpartyName)?.id;
|
|
547
|
+
if (id)
|
|
548
|
+
return people.has(id) ? null : { key: id, counterpartyId: id };
|
|
549
|
+
const key = (0, biz_base_1.nameKey)(line.counterpartyName);
|
|
550
|
+
return key && !(0, biz_base_1.looksLikePersonName)(line.counterpartyName) ? { key: `name:${key}`, counterpartyId: null } : null;
|
|
551
|
+
};
|
|
552
|
+
const found = (0, saas_rules_1.candidatesOf)(lines
|
|
553
|
+
.filter(line => line.account?.profitAndLoss !== false)
|
|
554
|
+
.flatMap(line => {
|
|
555
|
+
const vendor = vendorOf(line);
|
|
556
|
+
return vendor ? [{ ...vendor, name: line.counterpartyName, transactionDate: line.transactionDate, amount: Number(line.amount), currency: line.currency, bankAccountId: line.bankAccountId }] : [];
|
|
557
|
+
}), skip).filter(one => hiddenKeys.has(one.key) === hidden);
|
|
558
|
+
return found.map(one => ({ ...one, counterpartyName: parties.find(party => party.id === one.counterpartyId)?.name ?? one.name ?? '', hidden }));
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* Make an account of each candidate - named after the vendor, paid from where it was paid most, on the day it was paid
|
|
562
|
+
* most - with one usage subscription budgeted at the monthly average, so the months to come are expected at it until
|
|
563
|
+
* bills say otherwise. A vendor the lines only name is registered as a counterparty first; the lines written with its
|
|
564
|
+
* name are linked to it (accounting `linkLinesByName`). One that is no candidate any more is refused.
|
|
565
|
+
*/
|
|
566
|
+
async function createSaasAccountsFromCandidates(tx, domain, user, keys, today) {
|
|
567
|
+
const candidates = await saasCandidatesOf(tx, domain, today);
|
|
568
|
+
const made = [];
|
|
569
|
+
for (const key of [...new Set(keys)]) {
|
|
570
|
+
const one = candidates.find(candidate => candidate.key === key);
|
|
571
|
+
if (!one)
|
|
572
|
+
throw new shell_1.Refusal('saas-candidate-not-found', {}, 'It is no candidate any more - reload and try again');
|
|
573
|
+
const counterpartyId = one.counterpartyId ?? (await (0, biz_base_1.saveCounterparties)(tx, domain, user, [{ cuFlag: '+', name: one.counterpartyName, kind: biz_base_1.CounterpartyKind.COMPANY }]))[0].id;
|
|
574
|
+
/* Its lines written with its name and not linked yet are its months. */
|
|
575
|
+
await (0, accounting_1.linkLinesByName)(tx, domain, user, [counterpartyId]);
|
|
576
|
+
const [account] = await saveSaasAccounts(tx, domain, user, [
|
|
577
|
+
{ cuFlag: '+', name: one.counterpartyName, counterpartyId, paymentAccountId: one.paymentAccountId, currency: one.currency, billingDay: one.billingDay, status: saas_rules_1.SaasAccountStatus.ACTIVE }
|
|
578
|
+
]);
|
|
579
|
+
await saveSaasSubscriptions(tx, domain, user, 'all', account.id, [
|
|
580
|
+
{ cuFlag: '+', name: one.counterpartyName, billing: saas_rules_1.SaasBilling.USAGE, budget: one.average, startOn: one.firstDate, status: saas_rules_1.SaasSubscriptionStatus.ACTIVE }
|
|
581
|
+
]);
|
|
582
|
+
made.push(account);
|
|
583
|
+
}
|
|
584
|
+
return made;
|
|
585
|
+
}
|
|
586
|
+
/** Hide candidates - by their keys - or show them again. */
|
|
587
|
+
async function hideSaasCandidates(tx, domain, user, keys, hide) {
|
|
588
|
+
const repo = tx.getRepository(saas_hidden_vendor_1.SaasHiddenVendor);
|
|
589
|
+
const wanted = [...new Set(keys)].filter(Boolean);
|
|
590
|
+
const names = wanted.filter(key => key.startsWith('name:')).map(key => key.slice(5));
|
|
591
|
+
const ids = wanted.filter(key => !key.startsWith('name:'));
|
|
592
|
+
const parties = ids.length ? await tx.getRepository(biz_base_1.Counterparty).find({ where: { domain: { id: domain.id }, id: (0, typeorm_1.In)(ids) } }) : [];
|
|
593
|
+
if (parties.length !== ids.length)
|
|
594
|
+
throw new shell_1.Refusal('saas-counterparty-not-found', {}, 'The vendor was not found - reload and try again');
|
|
595
|
+
const rows = await repo.find({ where: { domain: { id: domain.id } } });
|
|
596
|
+
const held = (row) => (row.counterpartyId ? ids.includes(row.counterpartyId) : names.includes(row.nameKey));
|
|
597
|
+
if (!hide) {
|
|
598
|
+
const gone = rows.filter(held);
|
|
599
|
+
if (gone.length)
|
|
600
|
+
await repo.remove(gone);
|
|
601
|
+
return true;
|
|
602
|
+
}
|
|
603
|
+
for (const party of parties)
|
|
604
|
+
if (!rows.some(row => row.counterpartyId === party.id))
|
|
605
|
+
await repo.save({ domain, counterparty: party, creator: user });
|
|
606
|
+
for (const key of names)
|
|
607
|
+
if (!rows.some(row => !row.counterpartyId && row.nameKey === key))
|
|
608
|
+
await repo.save({ domain, nameKey: key, creator: user });
|
|
609
|
+
return true;
|
|
610
|
+
}
|
|
492
611
|
//# sourceMappingURL=saas-service.js.map
|