@things-factory/saas 10.1.236 → 10.1.238
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-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 +4 -1
- package/dist-server/service/saas-mutation.js +54 -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 +134 -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 +34 -0
- package/dist-server/service/saas-sync.js +106 -0
- package/dist-server/service/saas-sync.js.map +1 -0
- package/dist-server/service/saas-type.d.ts +45 -0
- package/dist-server/service/saas-type.js +171 -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 +23 -0
- package/translations/es.json +23 -0
- package/translations/ja.json +23 -0
- package/translations/ko.json +23 -0
- package/translations/ms.json +23 -0
- package/translations/zh.json +23 -0
|
@@ -11,6 +11,8 @@ exports.ROLE_TASKS = void 0;
|
|
|
11
11
|
exports.ROLE_TASKS = [
|
|
12
12
|
{ id: 'saas.reading', grants: [{ category: 'saas', axes: ['query'] }, { category: 'saas-self', axes: ['query'] }] },
|
|
13
13
|
{ id: 'saas.keeping', grants: [{ category: 'saas', axes: ['query', 'mutation'] }, { category: 'saas-self', axes: ['query', 'mutation'] }] },
|
|
14
|
-
{ id: 'saas.administering', grants: [{ category: 'saas-self', axes: ['query', 'mutation'] }] }
|
|
14
|
+
{ id: 'saas.administering', grants: [{ category: 'saas-self', axes: ['query', 'mutation'] }] },
|
|
15
|
+
/* Seats and quantities as a vendor's tenant says - for whoever runs the scenario that reads it (개정 2); no money. */
|
|
16
|
+
{ id: 'saas.syncing', grants: [{ category: 'saas-sync', axes: ['mutation'] }] }
|
|
15
17
|
];
|
|
16
18
|
//# sourceMappingURL=role-tasks.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"role-tasks.js","sourceRoot":"","sources":["../server/role-tasks.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAIU,QAAA,UAAU,GAAe;IACpC,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE;IACnH,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,CAAC,EAAE;IAC3I,EAAE,EAAE,EAAE,oBAAoB,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,CAAC,EAAE;
|
|
1
|
+
{"version":3,"file":"role-tasks.js","sourceRoot":"","sources":["../server/role-tasks.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAIU,QAAA,UAAU,GAAe;IACpC,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE;IACnH,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,CAAC,EAAE;IAC3I,EAAE,EAAE,EAAE,oBAAoB,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,CAAC,EAAE;IAC9F,oHAAoH;IACpH,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE;CAChF,CAAA","sourcesContent":["/*\n * The work this module names, for the seats applications build (ADR-0139 decision 11, ADR-0177 decision 8).\n *\n * `saas.administering` is for every seat: what it opens is only the accounts the signed-in person is named an admin of\n * (the service scopes it). Data only - `server/index.ts` registers it - so an application's tests read it without\n * starting the framework.\n */\n\nimport type { RoleTask } from '@things-factory/auth-base'\n\nexport const ROLE_TASKS: RoleTask[] = [\n { id: 'saas.reading', grants: [{ category: 'saas', axes: ['query'] }, { category: 'saas-self', axes: ['query'] }] },\n { id: 'saas.keeping', grants: [{ category: 'saas', axes: ['query', 'mutation'] }, { category: 'saas-self', axes: ['query', 'mutation'] }] },\n { id: 'saas.administering', grants: [{ category: 'saas-self', axes: ['query', 'mutation'] }] },\n /* Seats and quantities as a vendor's tenant says - for whoever runs the scenario that reads it (개정 2); no money. */\n { id: 'saas.syncing', grants: [{ category: 'saas-sync', axes: ['mutation'] }] }\n]\n"]}
|
|
@@ -16,7 +16,10 @@ export declare function saasSeatsOfLeavers(tx: EntityManager, domain: Domain, to
|
|
|
16
16
|
}[]>;
|
|
17
17
|
/** Accounts in use with nobody left to administer them - no admin named, or every admin retired. */
|
|
18
18
|
export declare function saasAccountsWithoutAdmin(tx: EntityManager, domain: Domain, today: string): Promise<SaasAccount[]>;
|
|
19
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* Seat plans in use whose seats held today are not as many as they are billed for. A plan with no price is left out - a
|
|
21
|
+
* free or trial plan a tenant hands out (1,000,000 Power BI Free) costs nothing unused (ADR-0177 개정 2, the user 10-31).
|
|
22
|
+
*/
|
|
20
23
|
export declare function saasSeatCountsDiffer(tx: EntityManager, domain: Domain, today: string): Promise<{
|
|
21
24
|
subscription: SaasSubscription;
|
|
22
25
|
account: SaasAccount;
|
|
@@ -55,10 +55,13 @@ async function saasAccountsWithoutAdmin(tx, domain, today) {
|
|
|
55
55
|
const retired = await retiredOf(tx, domain, [...new Set(accounts.flatMap(one => (one.admins ?? []).map(admin => admin.id)))], today);
|
|
56
56
|
return accounts.filter(account => !(account.admins ?? []).some(admin => !retired.has(admin.id)));
|
|
57
57
|
}
|
|
58
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* Seat plans in use whose seats held today are not as many as they are billed for. A plan with no price is left out - a
|
|
60
|
+
* free or trial plan a tenant hands out (1,000,000 Power BI Free) costs nothing unused (ADR-0177 개정 2, the user 10-31).
|
|
61
|
+
*/
|
|
59
62
|
async function saasSeatCountsDiffer(tx, domain, today) {
|
|
60
63
|
const { accounts, subs } = await inUse(tx, domain);
|
|
61
|
-
const plans = subs.filter(one => one.billing === saas_rules_1.SaasBilling.SEAT && one.startOn <= today);
|
|
64
|
+
const plans = subs.filter(one => one.billing === saas_rules_1.SaasBilling.SEAT && one.startOn <= today && one.unitPrice !== null && one.unitPrice !== undefined);
|
|
62
65
|
if (!plans.length)
|
|
63
66
|
return [];
|
|
64
67
|
const seats = await tx.getRepository(saas_seat_1.SaasSeat).find({ where: { domain: { id: domain.id }, subscription: { id: (0, typeorm_1.In)(plans.map(one => one.id)) } } });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checks.js","sourceRoot":"","sources":["../../server/service/checks.ts"],"names":[],"mappings":"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","sourcesContent":["import { Employee } from '@things-factory/organization'\nimport { Domain } from '@things-factory/shell'\nimport { EntityManager, In } from 'typeorm'\n\nimport { SaasAccount } from './saas-account'\nimport { SaasBill } from './saas-bill'\nimport { billedIn, renewalDue, SaasAccountStatus, SaasBilling, SaasSubscriptionStatus, seatHeld, shiftMonth } from './saas-rules'\nimport { SaasSeat } from './saas-seat'\nimport { SaasSubscription } from './saas-subscription'\n\n/*\n * The subscriptions' part of an application's management check (ADR-0177 decisions 6, 7, 9): judged here, counted there.\n * Each takes the day it judges on.\n */\n\n/** The employees who have retired by a day. */\nasync function retiredOf(tx: EntityManager, domain: Domain, ids: string[], today: string): Promise<Set<string>> {\n if (!ids.length) return new Set()\n const employees = await tx.getRepository(Employee).find({ where: { domain: { id: domain.id }, id: In(ids) } as any })\n return new Set(employees.filter(one => one.retiredOn && one.retiredOn <= today).map(one => one.id))\n}\n\nasync function inUse(tx: EntityManager, domain: Domain) {\n const accounts = await tx.getRepository(SaasAccount).find({ where: { domain: { id: domain.id }, status: SaasAccountStatus.ACTIVE } as any, relations: ['admins'] })\n const subs = accounts.length\n ? await tx.getRepository(SaasSubscription).find({ where: { domain: { id: domain.id }, account: { id: In(accounts.map(one => one.id)) }, status: In([SaasSubscriptionStatus.ACTIVE, SaasSubscriptionStatus.CANCELLING]) } as any })\n : []\n return { accounts, subs }\n}\n\n/** Subscriptions in use whose renewal is near - from their notice days before it to the day (decision 7). */\nexport async function saasRenewalsDue(tx: EntityManager, domain: Domain, today: string) {\n const { accounts, subs } = await inUse(tx, domain)\n return subs.filter(sub => renewalDue(sub, today)).map(sub => ({ subscription: sub, account: accounts.find(one => one.id === sub.accountId)! }))\n}\n\n/** Seats still held by people who have retired. */\nexport async function saasSeatsOfLeavers(tx: EntityManager, domain: Domain, today: string) {\n const { accounts, subs } = await inUse(tx, domain)\n if (!subs.length) return []\n const seats = (await tx.getRepository(SaasSeat).find({ where: { domain: { id: domain.id }, subscription: { id: In(subs.map(one => one.id)) } } as any, relations: ['employee'] })).filter(\n seat => seat.employeeId && seatHeld(seat, today)\n )\n const retired = await retiredOf(tx, domain, [...new Set(seats.map(one => one.employeeId!))], today)\n return seats\n .filter(seat => retired.has(seat.employeeId!))\n .map(seat => {\n const subscription = subs.find(one => one.id === seat.subscriptionId)!\n return { seat, subscription, account: accounts.find(one => one.id === subscription.accountId)! }\n })\n}\n\n/** Accounts in use with nobody left to administer them - no admin named, or every admin retired. */\nexport async function saasAccountsWithoutAdmin(tx: EntityManager, domain: Domain, today: string) {\n const { accounts } = await inUse(tx, domain)\n const retired = await retiredOf(tx, domain, [...new Set(accounts.flatMap(one => (one.admins ?? []).map(admin => admin.id)))], today)\n return accounts.filter(account => !(account.admins ?? []).some(admin => !retired.has(admin.id)))\n}\n\n/** Seat plans in use whose seats held today are not as many as they are billed for. */\nexport async function saasSeatCountsDiffer(tx: EntityManager, domain: Domain, today: string) {\n const { accounts, subs } = await inUse(tx, domain)\n const plans = subs.filter(one => one.billing === SaasBilling.SEAT && one.startOn <= today)\n if (!plans.length) return []\n const seats = await tx.getRepository(SaasSeat).find({ where: { domain: { id: domain.id }, subscription: { id: In(plans.map(one => one.id)) } } as any })\n return plans\n .map(sub => ({ subscription: sub, account: accounts.find(one => one.id === sub.accountId)!, held: seats.filter(seat => seat.subscriptionId === sub.id && seatHeld(seat, today)).length }))\n .filter(one => one.held !== Number(one.subscription.quantity ?? 0))\n}\n\n/**\n * Accounts in use that were to be billed last month and have no bill for it (decision 9) - the trend holds only while the\n * bills are written every month.\n */\nexport async function saasBillsMissing(tx: EntityManager, domain: Domain, today: string) {\n const { accounts, subs } = await inUse(tx, domain)\n const month = shiftMonth(today.slice(0, 7), -1)\n const [year, m] = month.split('-').map(Number)\n const due = accounts.filter(account => !account.parentId && subs.some(sub => sub.accountId === account.id && sub.billing !== SaasBilling.OWNED && billedIn(sub, year, m, account.billingDay)))\n if (!due.length) return []\n const billed = new Set(\n (await tx.getRepository(SaasBill).find({ where: { domain: { id: domain.id }, month, account: { id: In(due.map(one => one.id)) } } as any })).map(one => one.accountId)\n )\n return due.filter(one => !billed.has(one.id)).map(account => ({ account, month }))\n}\n"]}
|
|
1
|
+
{"version":3,"file":"checks.js","sourceRoot":"","sources":["../../server/service/checks.ts"],"names":[],"mappings":"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","sourcesContent":["import { Employee } from '@things-factory/organization'\nimport { Domain } from '@things-factory/shell'\nimport { EntityManager, In } from 'typeorm'\n\nimport { SaasAccount } from './saas-account'\nimport { SaasBill } from './saas-bill'\nimport { billedIn, renewalDue, SaasAccountStatus, SaasBilling, SaasSubscriptionStatus, seatHeld, shiftMonth } from './saas-rules'\nimport { SaasSeat } from './saas-seat'\nimport { SaasSubscription } from './saas-subscription'\n\n/*\n * The subscriptions' part of an application's management check (ADR-0177 decisions 6, 7, 9): judged here, counted there.\n * Each takes the day it judges on.\n */\n\n/** The employees who have retired by a day. */\nasync function retiredOf(tx: EntityManager, domain: Domain, ids: string[], today: string): Promise<Set<string>> {\n if (!ids.length) return new Set()\n const employees = await tx.getRepository(Employee).find({ where: { domain: { id: domain.id }, id: In(ids) } as any })\n return new Set(employees.filter(one => one.retiredOn && one.retiredOn <= today).map(one => one.id))\n}\n\nasync function inUse(tx: EntityManager, domain: Domain) {\n const accounts = await tx.getRepository(SaasAccount).find({ where: { domain: { id: domain.id }, status: SaasAccountStatus.ACTIVE } as any, relations: ['admins'] })\n const subs = accounts.length\n ? await tx.getRepository(SaasSubscription).find({ where: { domain: { id: domain.id }, account: { id: In(accounts.map(one => one.id)) }, status: In([SaasSubscriptionStatus.ACTIVE, SaasSubscriptionStatus.CANCELLING]) } as any })\n : []\n return { accounts, subs }\n}\n\n/** Subscriptions in use whose renewal is near - from their notice days before it to the day (decision 7). */\nexport async function saasRenewalsDue(tx: EntityManager, domain: Domain, today: string) {\n const { accounts, subs } = await inUse(tx, domain)\n return subs.filter(sub => renewalDue(sub, today)).map(sub => ({ subscription: sub, account: accounts.find(one => one.id === sub.accountId)! }))\n}\n\n/** Seats still held by people who have retired. */\nexport async function saasSeatsOfLeavers(tx: EntityManager, domain: Domain, today: string) {\n const { accounts, subs } = await inUse(tx, domain)\n if (!subs.length) return []\n const seats = (await tx.getRepository(SaasSeat).find({ where: { domain: { id: domain.id }, subscription: { id: In(subs.map(one => one.id)) } } as any, relations: ['employee'] })).filter(\n seat => seat.employeeId && seatHeld(seat, today)\n )\n const retired = await retiredOf(tx, domain, [...new Set(seats.map(one => one.employeeId!))], today)\n return seats\n .filter(seat => retired.has(seat.employeeId!))\n .map(seat => {\n const subscription = subs.find(one => one.id === seat.subscriptionId)!\n return { seat, subscription, account: accounts.find(one => one.id === subscription.accountId)! }\n })\n}\n\n/** Accounts in use with nobody left to administer them - no admin named, or every admin retired. */\nexport async function saasAccountsWithoutAdmin(tx: EntityManager, domain: Domain, today: string) {\n const { accounts } = await inUse(tx, domain)\n const retired = await retiredOf(tx, domain, [...new Set(accounts.flatMap(one => (one.admins ?? []).map(admin => admin.id)))], today)\n return accounts.filter(account => !(account.admins ?? []).some(admin => !retired.has(admin.id)))\n}\n\n/**\n * Seat plans in use whose seats held today are not as many as they are billed for. A plan with no price is left out - a\n * free or trial plan a tenant hands out (1,000,000 Power BI Free) costs nothing unused (ADR-0177 개정 2, the user 10-31).\n */\nexport async function saasSeatCountsDiffer(tx: EntityManager, domain: Domain, today: string) {\n const { accounts, subs } = await inUse(tx, domain)\n const plans = subs.filter(one => one.billing === SaasBilling.SEAT && one.startOn <= today && one.unitPrice !== null && one.unitPrice !== undefined)\n if (!plans.length) return []\n const seats = await tx.getRepository(SaasSeat).find({ where: { domain: { id: domain.id }, subscription: { id: In(plans.map(one => one.id)) } } as any })\n return plans\n .map(sub => ({ subscription: sub, account: accounts.find(one => one.id === sub.accountId)!, held: seats.filter(seat => seat.subscriptionId === sub.id && seatHeld(seat, today)).length }))\n .filter(one => one.held !== Number(one.subscription.quantity ?? 0))\n}\n\n/**\n * Accounts in use that were to be billed last month and have no bill for it (decision 9) - the trend holds only while the\n * bills are written every month.\n */\nexport async function saasBillsMissing(tx: EntityManager, domain: Domain, today: string) {\n const { accounts, subs } = await inUse(tx, domain)\n const month = shiftMonth(today.slice(0, 7), -1)\n const [year, m] = month.split('-').map(Number)\n const due = accounts.filter(account => !account.parentId && subs.some(sub => sub.accountId === account.id && sub.billing !== SaasBilling.OWNED && billedIn(sub, year, m, account.billingDay)))\n if (!due.length) return []\n const billed = new Set(\n (await tx.getRepository(SaasBill).find({ where: { domain: { id: domain.id }, month, account: { id: In(due.map(one => one.id)) } } as any })).map(one => one.accountId)\n )\n return due.filter(one => !billed.has(one.id)).map(account => ({ account, month }))\n}\n"]}
|
|
@@ -3,18 +3,21 @@ export * from './saas-account';
|
|
|
3
3
|
export * from './saas-subscription';
|
|
4
4
|
export * from './saas-seat';
|
|
5
5
|
export * from './saas-bill';
|
|
6
|
+
export * from './saas-hidden-vendor';
|
|
6
7
|
export * from './saas-type';
|
|
7
8
|
export * from './saas-trend-type';
|
|
8
9
|
export * from './saas-access';
|
|
9
10
|
export * from './saas-service';
|
|
11
|
+
export * from './saas-sync';
|
|
10
12
|
export * from './checks';
|
|
11
13
|
import { SaasAccount } from './saas-account';
|
|
12
14
|
import { SaasBill, SaasBillLine } from './saas-bill';
|
|
15
|
+
import { SaasHiddenVendor } from './saas-hidden-vendor';
|
|
13
16
|
import { SaasMutation } from './saas-mutation';
|
|
14
17
|
import { SaasAccountQuery } from './saas-query';
|
|
15
18
|
import { SaasSeat } from './saas-seat';
|
|
16
19
|
import { SaasSubscription } from './saas-subscription';
|
|
17
|
-
export declare const entities: (typeof SaasAccount | typeof SaasSubscription | typeof SaasSeat | typeof SaasBill | typeof SaasBillLine)[];
|
|
20
|
+
export declare const entities: (typeof SaasAccount | typeof SaasSubscription | typeof SaasSeat | typeof SaasBill | typeof SaasBillLine | typeof SaasHiddenVendor)[];
|
|
18
21
|
export declare const schema: {
|
|
19
22
|
resolverClasses: (typeof SaasMutation | typeof SaasAccountQuery)[];
|
|
20
23
|
};
|
|
@@ -8,14 +8,17 @@ tslib_1.__exportStar(require("./saas-account"), exports);
|
|
|
8
8
|
tslib_1.__exportStar(require("./saas-subscription"), exports);
|
|
9
9
|
tslib_1.__exportStar(require("./saas-seat"), exports);
|
|
10
10
|
tslib_1.__exportStar(require("./saas-bill"), exports);
|
|
11
|
+
tslib_1.__exportStar(require("./saas-hidden-vendor"), exports);
|
|
11
12
|
tslib_1.__exportStar(require("./saas-type"), exports);
|
|
12
13
|
tslib_1.__exportStar(require("./saas-trend-type"), exports);
|
|
13
14
|
tslib_1.__exportStar(require("./saas-access"), exports);
|
|
14
15
|
tslib_1.__exportStar(require("./saas-service"), exports);
|
|
16
|
+
tslib_1.__exportStar(require("./saas-sync"), exports);
|
|
15
17
|
tslib_1.__exportStar(require("./checks"), exports);
|
|
16
18
|
/* IMPORT ENTITIES AND RESOLVERS */
|
|
17
19
|
const saas_account_1 = require("./saas-account");
|
|
18
20
|
const saas_bill_1 = require("./saas-bill");
|
|
21
|
+
const saas_hidden_vendor_1 = require("./saas-hidden-vendor");
|
|
19
22
|
const saas_mutation_1 = require("./saas-mutation");
|
|
20
23
|
const saas_query_1 = require("./saas-query");
|
|
21
24
|
const saas_seat_1 = require("./saas-seat");
|
|
@@ -26,7 +29,8 @@ exports.entities = [
|
|
|
26
29
|
saas_subscription_1.SaasSubscription,
|
|
27
30
|
saas_seat_1.SaasSeat,
|
|
28
31
|
saas_bill_1.SaasBill,
|
|
29
|
-
saas_bill_1.SaasBillLine
|
|
32
|
+
saas_bill_1.SaasBillLine,
|
|
33
|
+
saas_hidden_vendor_1.SaasHiddenVendor
|
|
30
34
|
];
|
|
31
35
|
exports.schema = {
|
|
32
36
|
resolverClasses: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/service/index.ts"],"names":[],"mappings":";;;;AAAA,yBAAyB;AACzB,uDAA4B;AAC5B,yDAA8B;AAC9B,8DAAmC;AACnC,sDAA2B;AAC3B,sDAA2B;AAC3B,sDAA2B;AAC3B,4DAAiC;AACjC,wDAA6B;AAC7B,yDAA8B;AAC9B,mDAAwB;AAExB,mCAAmC;AACnC,iDAA4C;AAC5C,2CAAoD;AACpD,mDAA8C;AAC9C,6CAA+C;AAC/C,2CAAsC;AACtC,2DAAsD;AAEzC,QAAA,QAAQ,GAAG;IACtB,cAAc;IACd,0BAAW;IACX,oCAAgB;IAChB,oBAAQ;IACR,oBAAQ;IACR,wBAAY;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/service/index.ts"],"names":[],"mappings":";;;;AAAA,yBAAyB;AACzB,uDAA4B;AAC5B,yDAA8B;AAC9B,8DAAmC;AACnC,sDAA2B;AAC3B,sDAA2B;AAC3B,+DAAoC;AACpC,sDAA2B;AAC3B,4DAAiC;AACjC,wDAA6B;AAC7B,yDAA8B;AAC9B,sDAA2B;AAC3B,mDAAwB;AAExB,mCAAmC;AACnC,iDAA4C;AAC5C,2CAAoD;AACpD,6DAAuD;AACvD,mDAA8C;AAC9C,6CAA+C;AAC/C,2CAAsC;AACtC,2DAAsD;AAEzC,QAAA,QAAQ,GAAG;IACtB,cAAc;IACd,0BAAW;IACX,oCAAgB;IAChB,oBAAQ;IACR,oBAAQ;IACR,wBAAY;IACZ,qCAAgB;CACjB,CAAA;AAEY,QAAA,MAAM,GAAG;IACpB,eAAe,EAAE;QACf,sBAAsB;QACtB,6BAAgB;QAChB,4BAAY;KACb;CACF,CAAA","sourcesContent":["/* EXPORT ENTITY TYPES */\nexport * from './saas-rules'\nexport * from './saas-account'\nexport * from './saas-subscription'\nexport * from './saas-seat'\nexport * from './saas-bill'\nexport * from './saas-hidden-vendor'\nexport * from './saas-type'\nexport * from './saas-trend-type'\nexport * from './saas-access'\nexport * from './saas-service'\nexport * from './saas-sync'\nexport * from './checks'\n\n/* IMPORT ENTITIES AND RESOLVERS */\nimport { SaasAccount } from './saas-account'\nimport { SaasBill, SaasBillLine } from './saas-bill'\nimport { SaasHiddenVendor } from './saas-hidden-vendor'\nimport { SaasMutation } from './saas-mutation'\nimport { SaasAccountQuery } from './saas-query'\nimport { SaasSeat } from './saas-seat'\nimport { SaasSubscription } from './saas-subscription'\n\nexport const entities = [\n /* ENTITIES */\n SaasAccount,\n SaasSubscription,\n SaasSeat,\n SaasBill,\n SaasBillLine,\n SaasHiddenVendor\n]\n\nexport const schema = {\n resolverClasses: [\n /* RESOLVER CLASSES */\n SaasAccountQuery,\n SaasMutation\n ]\n}\n"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { User } from '@things-factory/auth-base';
|
|
2
|
+
import { Counterparty } from '@things-factory/biz-base';
|
|
3
|
+
import { Domain } from '@things-factory/shell';
|
|
4
|
+
/**
|
|
5
|
+
* Whom a keeper said is no subscription - paid month after month but a cleaner, an accountant, a landlord - so the books
|
|
6
|
+
* stop offering it as one (ADR-0177 개정 1): a counterparty, or the name written on lines no counterparty is linked to.
|
|
7
|
+
* Shown again, the row goes.
|
|
8
|
+
*/
|
|
9
|
+
export declare class SaasHiddenVendor {
|
|
10
|
+
readonly id: string;
|
|
11
|
+
domain?: Domain;
|
|
12
|
+
domainId?: string;
|
|
13
|
+
counterparty?: Counterparty;
|
|
14
|
+
counterpartyId?: string;
|
|
15
|
+
/** The written name's key (biz-base `nameKey`), for lines no counterparty is linked to. */
|
|
16
|
+
nameKey?: string;
|
|
17
|
+
createdAt?: Date;
|
|
18
|
+
creator?: User;
|
|
19
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SaasHiddenVendor = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const auth_base_1 = require("@things-factory/auth-base");
|
|
6
|
+
const biz_base_1 = require("@things-factory/biz-base");
|
|
7
|
+
const shell_1 = require("@things-factory/shell");
|
|
8
|
+
const typeorm_1 = require("typeorm");
|
|
9
|
+
/**
|
|
10
|
+
* Whom a keeper said is no subscription - paid month after month but a cleaner, an accountant, a landlord - so the books
|
|
11
|
+
* stop offering it as one (ADR-0177 개정 1): a counterparty, or the name written on lines no counterparty is linked to.
|
|
12
|
+
* Shown again, the row goes.
|
|
13
|
+
*/
|
|
14
|
+
let SaasHiddenVendor = class SaasHiddenVendor {
|
|
15
|
+
};
|
|
16
|
+
exports.SaasHiddenVendor = SaasHiddenVendor;
|
|
17
|
+
tslib_1.__decorate([
|
|
18
|
+
(0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
|
|
19
|
+
tslib_1.__metadata("design:type", String)
|
|
20
|
+
], SaasHiddenVendor.prototype, "id", void 0);
|
|
21
|
+
tslib_1.__decorate([
|
|
22
|
+
(0, typeorm_1.ManyToOne)(type => shell_1.Domain),
|
|
23
|
+
tslib_1.__metadata("design:type", shell_1.Domain)
|
|
24
|
+
], SaasHiddenVendor.prototype, "domain", void 0);
|
|
25
|
+
tslib_1.__decorate([
|
|
26
|
+
(0, typeorm_1.RelationId)((row) => row.domain),
|
|
27
|
+
tslib_1.__metadata("design:type", String)
|
|
28
|
+
], SaasHiddenVendor.prototype, "domainId", void 0);
|
|
29
|
+
tslib_1.__decorate([
|
|
30
|
+
(0, typeorm_1.ManyToOne)(type => biz_base_1.Counterparty, { nullable: true, onDelete: 'CASCADE' }),
|
|
31
|
+
tslib_1.__metadata("design:type", biz_base_1.Counterparty)
|
|
32
|
+
], SaasHiddenVendor.prototype, "counterparty", void 0);
|
|
33
|
+
tslib_1.__decorate([
|
|
34
|
+
(0, typeorm_1.RelationId)((row) => row.counterparty),
|
|
35
|
+
tslib_1.__metadata("design:type", String)
|
|
36
|
+
], SaasHiddenVendor.prototype, "counterpartyId", void 0);
|
|
37
|
+
tslib_1.__decorate([
|
|
38
|
+
(0, typeorm_1.Column)({ nullable: true }),
|
|
39
|
+
tslib_1.__metadata("design:type", String)
|
|
40
|
+
], SaasHiddenVendor.prototype, "nameKey", void 0);
|
|
41
|
+
tslib_1.__decorate([
|
|
42
|
+
(0, typeorm_1.CreateDateColumn)(),
|
|
43
|
+
tslib_1.__metadata("design:type", Date)
|
|
44
|
+
], SaasHiddenVendor.prototype, "createdAt", void 0);
|
|
45
|
+
tslib_1.__decorate([
|
|
46
|
+
(0, typeorm_1.ManyToOne)(type => auth_base_1.User, { nullable: true }),
|
|
47
|
+
tslib_1.__metadata("design:type", auth_base_1.User)
|
|
48
|
+
], SaasHiddenVendor.prototype, "creator", void 0);
|
|
49
|
+
exports.SaasHiddenVendor = SaasHiddenVendor = tslib_1.__decorate([
|
|
50
|
+
(0, typeorm_1.Entity)(),
|
|
51
|
+
(0, typeorm_1.Index)('ix_saas_hidden_vendor_0', (row) => [row.domain, row.counterparty, row.nameKey])
|
|
52
|
+
], SaasHiddenVendor);
|
|
53
|
+
//# sourceMappingURL=saas-hidden-vendor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"saas-hidden-vendor.js","sourceRoot":"","sources":["../../server/service/saas-hidden-vendor.ts"],"names":[],"mappings":";;;;AAAA,yDAAgD;AAChD,uDAAuD;AACvD,iDAA8C;AAC9C,qCAAgH;AAEhH;;;;GAIG;AAGI,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;CAyB5B,CAAA;AAzBY,4CAAgB;AAElB;IADR,IAAA,gCAAsB,EAAC,MAAM,CAAC;;4CACZ;AAGnB;IADC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,cAAM,CAAC;sCACjB,cAAM;gDAAA;AAGf;IADC,IAAA,oBAAU,EAAC,CAAC,GAAqB,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC;;kDACjC;AAGjB;IADC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,uBAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;sCAC1D,uBAAY;sDAAA;AAG3B;IADC,IAAA,oBAAU,EAAC,CAAC,GAAqB,EAAE,EAAE,CAAC,GAAG,CAAC,YAAY,CAAC;;wDACjC;AAIvB;IADC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;iDACX;AAGhB;IADC,IAAA,0BAAgB,GAAE;sCACP,IAAI;mDAAA;AAGhB;IADC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,gBAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;sCAClC,gBAAI;iDAAA;2BAxBH,gBAAgB;IAF5B,IAAA,gBAAM,GAAE;IACR,IAAA,eAAK,EAAC,yBAAyB,EAAE,CAAC,GAAqB,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,YAAY,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;GAC5F,gBAAgB,CAyB5B","sourcesContent":["import { User } from '@things-factory/auth-base'\nimport { Counterparty } from '@things-factory/biz-base'\nimport { Domain } from '@things-factory/shell'\nimport { Column, CreateDateColumn, Entity, Index, ManyToOne, PrimaryGeneratedColumn, RelationId } from 'typeorm'\n\n/**\n * Whom a keeper said is no subscription - paid month after month but a cleaner, an accountant, a landlord - so the books\n * stop offering it as one (ADR-0177 개정 1): a counterparty, or the name written on lines no counterparty is linked to.\n * Shown again, the row goes.\n */\n@Entity()\n@Index('ix_saas_hidden_vendor_0', (row: SaasHiddenVendor) => [row.domain, row.counterparty, row.nameKey])\nexport class SaasHiddenVendor {\n @PrimaryGeneratedColumn('uuid')\n readonly id: string\n\n @ManyToOne(type => Domain)\n domain?: Domain\n\n @RelationId((row: SaasHiddenVendor) => row.domain)\n domainId?: string\n\n @ManyToOne(type => Counterparty, { nullable: true, onDelete: 'CASCADE' })\n counterparty?: Counterparty\n\n @RelationId((row: SaasHiddenVendor) => row.counterparty)\n counterpartyId?: string\n\n /** The written name's key (biz-base `nameKey`), for lines no counterparty is linked to. */\n @Column({ nullable: true })\n nameKey?: string\n\n @CreateDateColumn()\n createdAt?: Date\n\n @ManyToOne(type => User, { nullable: true })\n creator?: User\n}\n"]}
|
|
@@ -2,9 +2,12 @@ import { SaasAccount } from './saas-account';
|
|
|
2
2
|
import { SaasBill } from './saas-bill';
|
|
3
3
|
import { SaasSeat } from './saas-seat';
|
|
4
4
|
import { SaasSubscription } from './saas-subscription';
|
|
5
|
-
import { SaasAccountPatch, SaasBillInput, SaasSeatPatch, SaasSubscriptionPatch } from './saas-type';
|
|
5
|
+
import { SaasAccountPatch, SaasBillInput, SaasLicensesInput, SaasSeatPatch, SaasSubscriptionPatch } from './saas-type';
|
|
6
6
|
export declare class SaasMutation {
|
|
7
|
+
syncSaasLicenses(licenses: SaasLicensesInput, context: ResolverContext): Promise<import("./saas-sync").LicenseSyncResult>;
|
|
7
8
|
updateMultipleSaasAccount(patches: SaasAccountPatch[], context: ResolverContext): Promise<SaasAccount[]>;
|
|
9
|
+
createSaasAccountsFromCandidates(keys: string[], context: ResolverContext): Promise<SaasAccount[]>;
|
|
10
|
+
hideSaasCandidates(keys: string[], hide: boolean, context: ResolverContext): Promise<boolean>;
|
|
8
11
|
updateMultipleSaasSubscription(accountId: string, patches: SaasSubscriptionPatch[], context: ResolverContext): Promise<SaasSubscription[]>;
|
|
9
12
|
updateMultipleSaasSeat(subscriptionId: string, patches: SaasSeatPatch[], context: ResolverContext): Promise<SaasSeat[]>;
|
|
10
13
|
saveSaasBill(accountId: string, bill: SaasBillInput, context: ResolverContext): Promise<SaasBill>;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.SaasMutation = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
+
const auth_base_1 = require("@things-factory/auth-base");
|
|
5
6
|
const shell_1 = require("@things-factory/shell");
|
|
6
7
|
const type_graphql_1 = require("type-graphql");
|
|
7
8
|
const saas_access_1 = require("./saas-access");
|
|
@@ -10,16 +11,38 @@ const saas_bill_1 = require("./saas-bill");
|
|
|
10
11
|
const saas_service_1 = require("./saas-service");
|
|
11
12
|
const saas_seat_1 = require("./saas-seat");
|
|
12
13
|
const saas_subscription_1 = require("./saas-subscription");
|
|
14
|
+
const saas_sync_1 = require("./saas-sync");
|
|
13
15
|
const saas_type_1 = require("./saas-type");
|
|
16
|
+
/** The bank's fact (ADR-0139) is read only by whoever reads bank lines. */
|
|
17
|
+
async function mustReadBank(state) {
|
|
18
|
+
const { domain, user, unsafeIP, prohibitedPrivileges } = state;
|
|
19
|
+
if (!(await (0, auth_base_1.checkPermission)({ category: 'bank', privilege: 'query', owner: false }, user, domain, unsafeIP, prohibitedPrivileges)))
|
|
20
|
+
throw new shell_1.Refusal('saas-candidates-need-bank', {}, 'Making accounts from the books needs reading the bank lines');
|
|
21
|
+
}
|
|
14
22
|
/*
|
|
15
23
|
* The accounts are the keepers'. What is under an account - its subscriptions, their seats, its bills - is also its
|
|
16
24
|
* admins', whatever their seat (ADR-0177 Q4): those doors ask `saas-self`, and the service keeps an admin to their own.
|
|
17
25
|
*/
|
|
18
26
|
let SaasMutation = class SaasMutation {
|
|
27
|
+
/* A scenario's step (ADR-0177 개정 2): seats and quantities only, so its own category - the system admin runs it. */
|
|
28
|
+
syncSaasLicenses(licenses, context) {
|
|
29
|
+
const { tx, domain, user } = context.state;
|
|
30
|
+
return (0, saas_sync_1.syncSaasLicenses)(tx, domain, user, licenses, new Date().toISOString().slice(0, 10));
|
|
31
|
+
}
|
|
19
32
|
updateMultipleSaasAccount(patches, context) {
|
|
20
33
|
const { tx, domain, user } = context.state;
|
|
21
34
|
return (0, saas_service_1.saveSaasAccounts)(tx, domain, user, patches);
|
|
22
35
|
}
|
|
36
|
+
/* The candidates are read from the bank and card lines - a keeper who also reads them (checked in the service). */
|
|
37
|
+
async createSaasAccountsFromCandidates(keys, context) {
|
|
38
|
+
const { tx, domain, user } = context.state;
|
|
39
|
+
await mustReadBank(context.state);
|
|
40
|
+
return (0, saas_service_1.createSaasAccountsFromCandidates)(tx, domain, user, keys, new Date().toISOString().slice(0, 10));
|
|
41
|
+
}
|
|
42
|
+
async hideSaasCandidates(keys, hide, context) {
|
|
43
|
+
const { tx, domain, user } = context.state;
|
|
44
|
+
return (0, saas_service_1.hideSaasCandidates)(tx, domain, user, keys, hide);
|
|
45
|
+
}
|
|
23
46
|
async updateMultipleSaasSubscription(accountId, patches, context) {
|
|
24
47
|
const { tx, domain, user } = context.state;
|
|
25
48
|
return (0, saas_service_1.saveSaasSubscriptions)(tx, domain, user, await (0, saas_access_1.scopeOf)(context.state, 'mutation', tx), accountId, patches);
|
|
@@ -38,6 +61,16 @@ let SaasMutation = class SaasMutation {
|
|
|
38
61
|
}
|
|
39
62
|
};
|
|
40
63
|
exports.SaasMutation = SaasMutation;
|
|
64
|
+
tslib_1.__decorate([
|
|
65
|
+
(0, type_graphql_1.Directive)('@transaction'),
|
|
66
|
+
(0, type_graphql_1.Directive)('@privilege(category: "saas-sync", privilege: "mutation", domainOwnerGranted: true)'),
|
|
67
|
+
(0, type_graphql_1.Mutation)(type => saas_type_1.SaasLicenseSync, { description: "To keep an account's seats and quantities as its vendor tenant says - what it bought and who holds each" }),
|
|
68
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('licenses', type => saas_type_1.SaasLicensesInput)),
|
|
69
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
70
|
+
tslib_1.__metadata("design:type", Function),
|
|
71
|
+
tslib_1.__metadata("design:paramtypes", [saas_type_1.SaasLicensesInput, Object]),
|
|
72
|
+
tslib_1.__metadata("design:returntype", void 0)
|
|
73
|
+
], SaasMutation.prototype, "syncSaasLicenses", null);
|
|
41
74
|
tslib_1.__decorate([
|
|
42
75
|
(0, type_graphql_1.Directive)('@transaction'),
|
|
43
76
|
(0, type_graphql_1.Directive)('@privilege(category: "saas", privilege: "mutation", domainOwnerGranted: true)'),
|
|
@@ -49,6 +82,27 @@ tslib_1.__decorate([
|
|
|
49
82
|
tslib_1.__metadata("design:paramtypes", [Array, Object]),
|
|
50
83
|
tslib_1.__metadata("design:returntype", void 0)
|
|
51
84
|
], SaasMutation.prototype, "updateMultipleSaasAccount", null);
|
|
85
|
+
tslib_1.__decorate([
|
|
86
|
+
(0, type_graphql_1.Directive)('@transaction'),
|
|
87
|
+
(0, type_graphql_1.Directive)('@privilege(category: "saas", privilege: "mutation", domainOwnerGranted: true)'),
|
|
88
|
+
(0, type_graphql_1.Mutation)(type => [saas_account_1.SaasAccount], { description: 'To make an account, with one usage subscription at the monthly average, of each candidate (by its key)' }),
|
|
89
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('keys', type => [String])),
|
|
90
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
91
|
+
tslib_1.__metadata("design:type", Function),
|
|
92
|
+
tslib_1.__metadata("design:paramtypes", [Array, Object]),
|
|
93
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
94
|
+
], SaasMutation.prototype, "createSaasAccountsFromCandidates", null);
|
|
95
|
+
tslib_1.__decorate([
|
|
96
|
+
(0, type_graphql_1.Directive)('@transaction'),
|
|
97
|
+
(0, type_graphql_1.Directive)('@privilege(category: "saas", privilege: "mutation", domainOwnerGranted: true)'),
|
|
98
|
+
(0, type_graphql_1.Mutation)(type => Boolean, { description: 'To hide candidates (by their keys), or with hide false to show them again' }),
|
|
99
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('keys', type => [String])),
|
|
100
|
+
tslib_1.__param(1, (0, type_graphql_1.Arg)('hide')),
|
|
101
|
+
tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
|
|
102
|
+
tslib_1.__metadata("design:type", Function),
|
|
103
|
+
tslib_1.__metadata("design:paramtypes", [Array, Boolean, Object]),
|
|
104
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
105
|
+
], SaasMutation.prototype, "hideSaasCandidates", null);
|
|
52
106
|
tslib_1.__decorate([
|
|
53
107
|
(0, type_graphql_1.Directive)('@transaction'),
|
|
54
108
|
(0, type_graphql_1.Directive)('@privilege(category: "saas-self", privilege: "mutation", domainOwnerGranted: true)'),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"saas-mutation.js","sourceRoot":"","sources":["../../server/service/saas-mutation.ts"],"names":[],"mappings":"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","sourcesContent":["import { SpeakRefusals } from '@things-factory/shell'\nimport { Arg, Ctx, Directive, Mutation, Resolver, UseMiddleware } from 'type-graphql'\n\nimport { scopeOf } from './saas-access'\nimport { SaasAccount } from './saas-account'\nimport { SaasBill } from './saas-bill'\nimport { deleteSaasBill, saveSaasAccounts, saveSaasBill, saveSaasSeats, saveSaasSubscriptions } from './saas-service'\nimport { SaasSeat } from './saas-seat'\nimport { SaasSubscription } from './saas-subscription'\nimport { SaasAccountPatch, SaasBillInput, SaasSeatPatch, SaasSubscriptionPatch } from './saas-type'\n\n/*\n * The accounts are the keepers'. What is under an account - its subscriptions, their seats, its bills - is also its\n * admins', whatever their seat (ADR-0177 Q4): those doors ask `saas-self`, and the service keeps an admin to their own.\n */\n@UseMiddleware(SpeakRefusals)\n@Resolver(SaasAccount)\nexport class SaasMutation {\n @Directive('@transaction')\n @Directive('@privilege(category: \"saas\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@auditTarget(kind: \"SaasAccount\", arg: \"patches\")')\n @Mutation(type => [SaasAccount], { description: 'To save the accounts grid - new, changed and deleted rows together' })\n updateMultipleSaasAccount(@Arg('patches', type => [SaasAccountPatch]) patches: SaasAccountPatch[], @Ctx() context: ResolverContext) {\n const { tx, domain, user } = context.state\n return saveSaasAccounts(tx, domain, user, patches)\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"saas-self\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@auditTarget(kind: \"SaasAccount\", arg: \"accountId\")')\n @Mutation(type => [SaasSubscription], { description: \"To save an account's subscriptions grid\" })\n async updateMultipleSaasSubscription(@Arg('accountId') accountId: string, @Arg('patches', type => [SaasSubscriptionPatch]) patches: SaasSubscriptionPatch[], @Ctx() context: ResolverContext) {\n const { tx, domain, user } = context.state\n return saveSaasSubscriptions(tx, domain, user, await scopeOf(context.state, 'mutation', tx), accountId, patches)\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"saas-self\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@auditTarget(kind: \"SaasSubscription\", arg: \"subscriptionId\")')\n @Mutation(type => [SaasSeat], { description: \"To save a subscription's seats grid\" })\n async updateMultipleSaasSeat(@Arg('subscriptionId') subscriptionId: string, @Arg('patches', type => [SaasSeatPatch]) patches: SaasSeatPatch[], @Ctx() context: ResolverContext) {\n const { tx, domain, user } = context.state\n return saveSaasSeats(tx, domain, user, await scopeOf(context.state, 'mutation', tx), subscriptionId, patches)\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"saas-self\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@auditTarget(kind: \"SaasAccount\", arg: \"accountId\")')\n @Mutation(type => SaasBill, { description: \"To write an account's bill for a month, its lines whole\" })\n async saveSaasBill(@Arg('accountId') accountId: string, @Arg('bill', type => SaasBillInput) bill: SaasBillInput, @Ctx() context: ResolverContext) {\n const { tx, domain, user } = context.state\n return saveSaasBill(tx, domain, user, await scopeOf(context.state, 'mutation', tx), accountId, bill)\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"saas-self\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@auditTarget(kind: \"SaasBill\", arg: \"id\")')\n @Mutation(type => Boolean, { description: 'To delete a bill' })\n async deleteSaasBill(@Arg('id') id: string, @Ctx() context: ResolverContext) {\n const { tx, domain } = context.state\n return deleteSaasBill(tx, domain, await scopeOf(context.state, 'mutation', tx), id)\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"saas-mutation.js","sourceRoot":"","sources":["../../server/service/saas-mutation.ts"],"names":[],"mappings":"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","sourcesContent":["import { checkPermission } from '@things-factory/auth-base'\nimport { Refusal, SpeakRefusals } from '@things-factory/shell'\nimport { Arg, Ctx, Directive, Mutation, Resolver, UseMiddleware } from 'type-graphql'\n\nimport { scopeOf } from './saas-access'\nimport { SaasAccount } from './saas-account'\nimport { SaasBill } from './saas-bill'\nimport { createSaasAccountsFromCandidates, deleteSaasBill, hideSaasCandidates, saveSaasAccounts, saveSaasBill, saveSaasSeats, saveSaasSubscriptions } from './saas-service'\nimport { SaasSeat } from './saas-seat'\nimport { SaasSubscription } from './saas-subscription'\nimport { syncSaasLicenses } from './saas-sync'\nimport { SaasAccountPatch, SaasBillInput, SaasLicenseSync, SaasLicensesInput, SaasSeatPatch, SaasSubscriptionPatch } from './saas-type'\n\n/** The bank's fact (ADR-0139) is read only by whoever reads bank lines. */\nasync function mustReadBank(state: any) {\n const { domain, user, unsafeIP, prohibitedPrivileges } = state\n if (!(await checkPermission({ category: 'bank', privilege: 'query', owner: false } as any, user, domain, unsafeIP, prohibitedPrivileges)))\n throw new Refusal('saas-candidates-need-bank', {}, 'Making accounts from the books needs reading the bank lines')\n}\n\n/*\n * The accounts are the keepers'. What is under an account - its subscriptions, their seats, its bills - is also its\n * admins', whatever their seat (ADR-0177 Q4): those doors ask `saas-self`, and the service keeps an admin to their own.\n */\n@UseMiddleware(SpeakRefusals)\n@Resolver(SaasAccount)\nexport class SaasMutation {\n /* A scenario's step (ADR-0177 개정 2): seats and quantities only, so its own category - the system admin runs it. */\n @Directive('@transaction')\n @Directive('@privilege(category: \"saas-sync\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(type => SaasLicenseSync, { description: \"To keep an account's seats and quantities as its vendor tenant says - what it bought and who holds each\" })\n syncSaasLicenses(@Arg('licenses', type => SaasLicensesInput) licenses: SaasLicensesInput, @Ctx() context: ResolverContext) {\n const { tx, domain, user } = context.state\n return syncSaasLicenses(tx, domain, user, licenses, new Date().toISOString().slice(0, 10))\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"saas\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@auditTarget(kind: \"SaasAccount\", arg: \"patches\")')\n @Mutation(type => [SaasAccount], { description: 'To save the accounts grid - new, changed and deleted rows together' })\n updateMultipleSaasAccount(@Arg('patches', type => [SaasAccountPatch]) patches: SaasAccountPatch[], @Ctx() context: ResolverContext) {\n const { tx, domain, user } = context.state\n return saveSaasAccounts(tx, domain, user, patches)\n }\n\n /* The candidates are read from the bank and card lines - a keeper who also reads them (checked in the service). */\n @Directive('@transaction')\n @Directive('@privilege(category: \"saas\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(type => [SaasAccount], { description: 'To make an account, with one usage subscription at the monthly average, of each candidate (by its key)' })\n async createSaasAccountsFromCandidates(@Arg('keys', type => [String]) keys: string[], @Ctx() context: ResolverContext) {\n const { tx, domain, user } = context.state\n await mustReadBank(context.state)\n return createSaasAccountsFromCandidates(tx, domain, user, keys, new Date().toISOString().slice(0, 10))\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"saas\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(type => Boolean, { description: 'To hide candidates (by their keys), or with hide false to show them again' })\n async hideSaasCandidates(@Arg('keys', type => [String]) keys: string[], @Arg('hide') hide: boolean, @Ctx() context: ResolverContext) {\n const { tx, domain, user } = context.state\n return hideSaasCandidates(tx, domain, user, keys, hide)\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"saas-self\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@auditTarget(kind: \"SaasAccount\", arg: \"accountId\")')\n @Mutation(type => [SaasSubscription], { description: \"To save an account's subscriptions grid\" })\n async updateMultipleSaasSubscription(@Arg('accountId') accountId: string, @Arg('patches', type => [SaasSubscriptionPatch]) patches: SaasSubscriptionPatch[], @Ctx() context: ResolverContext) {\n const { tx, domain, user } = context.state\n return saveSaasSubscriptions(tx, domain, user, await scopeOf(context.state, 'mutation', tx), accountId, patches)\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"saas-self\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@auditTarget(kind: \"SaasSubscription\", arg: \"subscriptionId\")')\n @Mutation(type => [SaasSeat], { description: \"To save a subscription's seats grid\" })\n async updateMultipleSaasSeat(@Arg('subscriptionId') subscriptionId: string, @Arg('patches', type => [SaasSeatPatch]) patches: SaasSeatPatch[], @Ctx() context: ResolverContext) {\n const { tx, domain, user } = context.state\n return saveSaasSeats(tx, domain, user, await scopeOf(context.state, 'mutation', tx), subscriptionId, patches)\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"saas-self\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@auditTarget(kind: \"SaasAccount\", arg: \"accountId\")')\n @Mutation(type => SaasBill, { description: \"To write an account's bill for a month, its lines whole\" })\n async saveSaasBill(@Arg('accountId') accountId: string, @Arg('bill', type => SaasBillInput) bill: SaasBillInput, @Ctx() context: ResolverContext) {\n const { tx, domain, user } = context.state\n return saveSaasBill(tx, domain, user, await scopeOf(context.state, 'mutation', tx), accountId, bill)\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"saas-self\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@auditTarget(kind: \"SaasBill\", arg: \"id\")')\n @Mutation(type => Boolean, { description: 'To delete a bill' })\n async deleteSaasBill(@Arg('id') id: string, @Ctx() context: ResolverContext) {\n const { tx, domain } = context.state\n return deleteSaasBill(tx, domain, await scopeOf(context.state, 'mutation', tx), id)\n }\n}\n"]}
|
|
@@ -6,7 +6,7 @@ import { SaasAccount } from './saas-account';
|
|
|
6
6
|
import { SaasBill } from './saas-bill';
|
|
7
7
|
import { SaasSeat } from './saas-seat';
|
|
8
8
|
import { SaasSubscription } from './saas-subscription';
|
|
9
|
-
import { SaasAccountList, SaasChange } from './saas-type';
|
|
9
|
+
import { SaasAccountList, SaasCandidate, SaasChange } from './saas-type';
|
|
10
10
|
export declare class SaasAccountQuery {
|
|
11
11
|
saasAccounts(params: ListParam, context: ResolverContext): Promise<SaasAccountList>;
|
|
12
12
|
mySaasAccounts(context: ResolverContext): Promise<SaasAccount[]>;
|
|
@@ -16,6 +16,7 @@ export declare class SaasAccountQuery {
|
|
|
16
16
|
saasBills(accountId: string, context: ResolverContext): Promise<SaasBill[]>;
|
|
17
17
|
saasChanges(accountId: string, context: ResolverContext): Promise<SaasChange[]>;
|
|
18
18
|
saasPayments(accountId: string, context: ResolverContext): Promise<Transaction[]>;
|
|
19
|
+
saasCandidates(hidden: boolean, context: ResolverContext): Promise<SaasCandidate[]>;
|
|
19
20
|
saasCostTrend(from: string, to: string, context: ResolverContext): Promise<{
|
|
20
21
|
months: string[];
|
|
21
22
|
all: import("./saas-rules").TrendSeries[];
|
|
@@ -72,6 +72,13 @@ let SaasAccountQuery = class SaasAccountQuery {
|
|
|
72
72
|
const manager = (0, shell_1.getRepository)(saas_account_1.SaasAccount).manager;
|
|
73
73
|
return (0, saas_service_1.saasPaymentsOf)(manager, context.state.domain, await (0, saas_access_1.scopeOf)(context.state, 'query', manager), accountId);
|
|
74
74
|
}
|
|
75
|
+
/* Read from the bank and card lines (ADR-0139): the bank's door; the candidates are the keepers' (`saas`) on top. */
|
|
76
|
+
async saasCandidates(hidden, context) {
|
|
77
|
+
const manager = (0, shell_1.getRepository)(saas_account_1.SaasAccount).manager;
|
|
78
|
+
if ((await (0, saas_access_1.scopeOf)(context.state, 'query', manager)) !== 'all')
|
|
79
|
+
return [];
|
|
80
|
+
return (0, saas_service_1.saasCandidatesOf)(manager, context.state.domain, today(), !!hidden);
|
|
81
|
+
}
|
|
75
82
|
saasCostTrend(from, to, context) {
|
|
76
83
|
return (0, saas_service_1.saasCostTrend)((0, shell_1.getRepository)(saas_account_1.SaasAccount).manager, context.state.domain, from, to);
|
|
77
84
|
}
|
|
@@ -163,6 +170,15 @@ tslib_1.__decorate([
|
|
|
163
170
|
tslib_1.__metadata("design:paramtypes", [String, Object]),
|
|
164
171
|
tslib_1.__metadata("design:returntype", Promise)
|
|
165
172
|
], SaasAccountQuery.prototype, "saasPayments", null);
|
|
173
|
+
tslib_1.__decorate([
|
|
174
|
+
(0, type_graphql_1.Directive)('@privilege(category: "bank", privilege: "query", domainOwnerGranted: false)'),
|
|
175
|
+
(0, type_graphql_1.Query)(type => [saas_type_1.SaasCandidate], { description: 'The vendors the bank and card lines show paid month after month that are no account or recurring item yet; with hidden, the ones hidden' }),
|
|
176
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('hidden', { nullable: true })),
|
|
177
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
178
|
+
tslib_1.__metadata("design:type", Function),
|
|
179
|
+
tslib_1.__metadata("design:paramtypes", [Boolean, Object]),
|
|
180
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
181
|
+
], SaasAccountQuery.prototype, "saasCandidates", null);
|
|
166
182
|
tslib_1.__decorate([
|
|
167
183
|
(0, type_graphql_1.Directive)('@privilege(category: "saas", privilege: "query", domainOwnerGranted: true)'),
|
|
168
184
|
(0, type_graphql_1.Query)(type => saas_type_1.SaasCostTrend, { description: 'The cost trend from the bills, month by month from one month to another (YYYY-MM)' }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"saas-query.js","sourceRoot":"","sources":["../../server/service/saas-query.ts"],"names":[],"mappings":";;;;AAAA,2DAAqE;AACrE,yDAAiE;AACjE,uDAAuD;AACvD,iDAAsH;AACtH,+CAA6G;AAC7G,qCAA4B;AAE5B,+CAAkE;AAClE,iDAA4C;AAC5C,2CAAsC;AACtC,iDAA0I;AAC1I,2CAAsC;AACtC,2DAAsD;AACtD,2CAAwE;AAExE,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;AAEzD,6GAA6G;AAC7G,KAAK,UAAU,UAAU,CAAC,EAAO,EAAE,KAAU,EAAE,KAAoB;IACjE,IAAI,CAAC,KAAK,CAAC,MAAM;QAAE,OAAO,KAAK,CAAA;IAC/B,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,oBAAoB,EAAE,GAAG,KAAK,CAAA;IAC9D,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,0BAAW,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,IAAA,YAAE,EAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;IAC7H,gHAAgH;IAChH,MAAM,QAAQ,GAAG,MAAM,IAAA,2BAAe,EAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAS,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,oBAAoB,CAAC,CAAA;IACnJ,MAAM,MAAM,GAAG,MAAM,IAAA,2BAAY,EAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,QAAQ,CAAC,CAAA;IACvE,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,CAAC,EAAE,MAAM,IAAI,EAAE,CAAA;QAC9D,GAAG,CAAC,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAChC,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAIM,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;IAGrB,AAAN,KAAK,CAAC,YAAY,CAA0B,MAAiB,EAAS,OAAwB;QAC5F,MAAM,KAAK,GAAG,IAAA,qCAA6B,EAAC,EAAE,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,IAAA,qBAAa,EAAC,0BAAW,CAAC,EAAE,WAAW,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,aAAa,CAAC,EAAE,CAAC,CAAA;QAC5M,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,KAAK,CAAC,eAAe,EAAE,CAAA;QACpD,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC,IAAA,qBAAa,EAAC,0BAAW,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,CAAA;IACrG,CAAC;IAIK,AAAN,KAAK,CAAC,cAAc,CAAQ,OAAwB;QAClD,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QACtC,MAAM,OAAO,GAAG,IAAA,qBAAa,EAAC,0BAAW,CAAC,CAAC,OAAO,CAAA;QAClD,MAAM,GAAG,GAAG,MAAM,IAAA,4BAAc,EAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,CAAA;QAC3D,IAAI,CAAC,GAAG,CAAC,MAAM;YAAE,OAAO,EAAE,CAAA;QAC1B,OAAO,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,IAAA,qBAAa,EAAC,0BAAW,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,IAAA,YAAE,EAAC,GAAG,CAAC,EAAS,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,EAAS,EAAE,CAAC,CAAC,CAAA;IAC/K,CAAC;IAIK,AAAN,KAAK,CAAC,WAAW,CAAY,EAAU,EAAS,OAAwB;QACtE,MAAM,OAAO,GAAG,IAAA,qBAAa,EAAC,0BAAW,CAAC,CAAC,OAAO,CAAA;QAClD,MAAM,OAAO,GAAG,MAAM,IAAA,uBAAS,EAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,IAAA,qBAAO,EAAC,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAA;QAClH,OAAO,CAAC,MAAM,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IACjE,CAAC;IAIK,AAAN,KAAK,CAAC,iBAAiB,CAAmB,SAAiB,EAAS,OAAwB;QAC1F,MAAM,OAAO,GAAG,IAAA,qBAAa,EAAC,0BAAW,CAAC,CAAC,OAAO,CAAA;QAClD,OAAO,IAAA,kCAAmB,EAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,IAAA,qBAAO,EAAC,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAA;IAC/H,CAAC;IAIK,AAAN,KAAK,CAAC,SAAS,CAAwB,cAAsB,EAAS,OAAwB;QAC5F,MAAM,OAAO,GAAG,IAAA,qBAAa,EAAC,0BAAW,CAAC,CAAC,OAAO,CAAA;QAClD,OAAO,IAAA,0BAAW,EAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,IAAA,qBAAO,EAAC,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,cAAc,CAAC,CAAA;IACnH,CAAC;IAIK,AAAN,KAAK,CAAC,SAAS,CAAmB,SAAiB,EAAS,OAAwB;QAClF,MAAM,OAAO,GAAG,IAAA,qBAAa,EAAC,0BAAW,CAAC,CAAC,OAAO,CAAA;QAClD,OAAO,IAAA,0BAAW,EAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,IAAA,qBAAO,EAAC,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,SAAS,CAAC,CAAA;IAC9G,CAAC;IAIK,AAAN,KAAK,CAAC,WAAW,CAAmB,SAAiB,EAAS,OAAwB;QACpF,MAAM,OAAO,GAAG,IAAA,qBAAa,EAAC,0BAAW,CAAC,CAAC,OAAO,CAAA;QAClD,MAAM,IAAI,GAAG,MAAM,IAAA,4BAAa,EAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,IAAA,qBAAO,EAAC,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,SAAS,CAAC,CAAA;QAC1H,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAQ,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;IACjM,CAAC;IAED,sHAAsH;IAGhH,AAAN,KAAK,CAAC,YAAY,CAAmB,SAAiB,EAAS,OAAwB;QACrF,MAAM,OAAO,GAAG,IAAA,qBAAa,EAAC,0BAAW,CAAC,CAAC,OAAO,CAAA;QAClD,OAAO,IAAA,6BAAc,EAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,IAAA,qBAAO,EAAC,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,SAAS,CAAC,CAAA;IACjH,CAAC;IAID,aAAa,CAAc,IAAY,EAAa,EAAU,EAAS,OAAwB;QAC7F,OAAO,IAAA,4BAAa,EAAC,IAAA,qBAAa,EAAC,0BAAW,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,CAAA;IAC1F,CAAC;IAGD,YAAY,CAAS,GAAgB;QACnC,OAAO,GAAG,CAAC,YAAY,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,IAAA,qBAAa,EAAC,uBAAY,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;IACjI,CAAC;IAGD,MAAM,CAAS,GAAgB;QAC7B,OAAO,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAA,qBAAa,EAAC,0BAAW,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;IAC9G,CAAC;IAGD,cAAc,CAAS,GAAgB;QACrC,OAAO,GAAG,CAAC,cAAc,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAA,qBAAa,EAAC,wBAAW,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;IACtI,CAAC;IAGD,MAAM,CAAS,GAAgB;QAC7B,OAAO,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAA,qBAAa,EAAC,cAAM,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;IACzG,CAAC;IAGD,OAAO,CAAS,GAAgB;QAC9B,OAAO,GAAG,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,IAAA,qBAAa,EAAC,gBAAI,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;IAC1G,CAAC;CACF,CAAA;AA9FY,4CAAgB;AAGrB;IAFL,IAAA,wBAAS,EAAC,4EAA4E,CAAC;IACvF,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,2BAAe,EAAE,EAAE,WAAW,EAAE,+DAA+D,EAAE,CAAC;IAC7F,mBAAA,IAAA,mBAAI,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAS,CAAC,CAAA;IAAqB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;6CAAjB,iBAAS;;oDAI5D;AAIK;IAFL,IAAA,wBAAS,EAAC,iFAAiF,CAAC;IAC5F,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,0BAAW,CAAC,EAAE,EAAE,WAAW,EAAE,wDAAwD,EAAE,CAAC;IAClF,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;sDAM1B;AAIK;IAFL,IAAA,wBAAS,EAAC,iFAAiF,CAAC;IAC5F,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,0BAAW,EAAE,EAAE,WAAW,EAAE,sDAAsD,EAAE,CAAC;IACjF,mBAAA,IAAA,kBAAG,EAAC,IAAI,CAAC,CAAA;IAAc,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;mDAI9C;AAIK;IAFL,IAAA,wBAAS,EAAC,iFAAiF,CAAC;IAC5F,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,oCAAgB,CAAC,EAAE,EAAE,WAAW,EAAE,4DAA4D,EAAE,CAAC;IACxF,mBAAA,IAAA,kBAAG,EAAC,WAAW,CAAC,CAAA;IAAqB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;yDAGlE;AAIK;IAFL,IAAA,wBAAS,EAAC,iFAAiF,CAAC;IAC5F,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,oBAAQ,CAAC,EAAE,EAAE,WAAW,EAAE,6BAA6B,EAAE,CAAC;IACzD,mBAAA,IAAA,kBAAG,EAAC,gBAAgB,CAAC,CAAA;IAA0B,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;iDAGpE;AAIK;IAFL,IAAA,wBAAS,EAAC,iFAAiF,CAAC;IAC5F,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,oBAAQ,CAAC,EAAE,EAAE,WAAW,EAAE,yDAAyD,EAAE,CAAC;IACrF,mBAAA,IAAA,kBAAG,EAAC,WAAW,CAAC,CAAA;IAAqB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;iDAG1D;AAIK;IAFL,IAAA,wBAAS,EAAC,iFAAiF,CAAC;IAC5F,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,sBAAU,CAAC,EAAE,EAAE,WAAW,EAAE,8DAA8D,EAAE,CAAC;IAC1F,mBAAA,IAAA,kBAAG,EAAC,WAAW,CAAC,CAAA;IAAqB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;mDAI5D;AAKK;IAFL,IAAA,wBAAS,EAAC,6EAA6E,CAAC;IACxF,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,wBAAW,CAAC,EAAE,EAAE,WAAW,EAAE,4DAA4D,EAAE,CAAC;IACxF,mBAAA,IAAA,kBAAG,EAAC,WAAW,CAAC,CAAA;IAAqB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;oDAG7D;AAID;IAFC,IAAA,wBAAS,EAAC,4EAA4E,CAAC;IACvF,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,yBAAa,EAAE,EAAE,WAAW,EAAE,mFAAmF,EAAE,CAAC;IACpH,mBAAA,IAAA,kBAAG,EAAC,MAAM,CAAC,CAAA;IAAgB,mBAAA,IAAA,kBAAG,EAAC,IAAI,CAAC,CAAA;IAAc,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;qDAErE;AAGD;IADC,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,uBAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1C,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAM,0BAAW;;oDAEpC;AAGD;IADC,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,0BAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC/C,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAM,0BAAW;;8CAE9B;AAGD;IADC,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,wBAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACvC,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAM,0BAAW;;sDAEtC;AAGD;IADC,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,cAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1C,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAM,0BAAW;;8CAE9B;AAGD;IADC,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,gBAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACvC,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAM,0BAAW;;+CAE/B;2BA7FU,gBAAgB;IAF5B,IAAA,4BAAa,EAAC,qBAAa,CAAC;IAC5B,IAAA,uBAAQ,EAAC,0BAAW,CAAC;GACT,gBAAgB,CA8F5B","sourcesContent":["import { BankAccount, Transaction } from '@things-factory/accounting'\nimport { checkPermission, User } from '@things-factory/auth-base'\nimport { Counterparty } from '@things-factory/biz-base'\nimport { Domain, getQueryBuilderFromListParams, getRepository, ListParam, SpeakRefusals } from '@things-factory/shell'\nimport { Arg, Args, Ctx, Directive, FieldResolver, Query, Resolver, Root, UseMiddleware } from 'type-graphql'\nimport { In } from 'typeorm'\n\nimport { accountIn, administeredBy, scopeOf } from './saas-access'\nimport { SaasAccount } from './saas-account'\nimport { SaasBill } from './saas-bill'\nimport { saasBillsOf, saasChangesOf, saasCostTrend, saasPaymentsOf, saasSeatsOf, saasSubscriptionsOf, saasTrendsOf } from './saas-service'\nimport { SaasSeat } from './saas-seat'\nimport { SaasSubscription } from './saas-subscription'\nimport { SaasAccountList, SaasChange, SaasCostTrend } from './saas-type'\n\nconst today = () => new Date().toISOString().slice(0, 10)\n\n/** The accounts with their admins and their months (decision 10) - the list's relations in one read each. */\nasync function withAdmins(tx: any, state: any, items: SaasAccount[]) {\n if (!items.length) return items\n const { domain, user, unsafeIP, prohibitedPrivileges } = state\n const rows = await tx.getRepository(SaasAccount).find({ where: { id: In(items.map(one => one.id)) }, relations: ['admins'] })\n /* What left the bank is the bank's fact (ADR-0139) - read into the months only for whoever reads bank lines. */\n const withBank = await checkPermission({ category: 'bank', privilege: 'query', owner: false } as any, user, domain, unsafeIP, prohibitedPrivileges)\n const trends = await saasTrendsOf(tx, domain, items, today(), withBank)\n for (const one of items) {\n one.admins = rows.find(row => row.id === one.id)?.admins ?? []\n one.trend = trends.get(one.id)\n }\n return items\n}\n\n@UseMiddleware(SpeakRefusals)\n@Resolver(SaasAccount)\nexport class SaasAccountQuery {\n @Directive('@privilege(category: \"saas\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(type => SaasAccountList, { description: 'To fetch a page of the accounts the domain holds with vendors' })\n async saasAccounts(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<SaasAccountList> {\n const query = getQueryBuilderFromListParams({ domain: context.state.domain, params, repository: getRepository(SaasAccount), searchables: ['name', 'identifier', 'purpose', 'billingEmail', 'description'] })\n const [items, total] = await query.getManyAndCount()\n return { items: await withAdmins(getRepository(SaasAccount).manager, context.state, items), total }\n }\n\n @Directive('@privilege(category: \"saas-self\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(type => [SaasAccount], { description: 'The accounts the signed-in person is named an admin of' })\n async mySaasAccounts(@Ctx() context: ResolverContext): Promise<SaasAccount[]> {\n const { domain, user } = context.state\n const manager = getRepository(SaasAccount).manager\n const ids = await administeredBy(manager, domain, user?.id)\n if (!ids.length) return []\n return withAdmins(manager, context.state, await getRepository(SaasAccount).find({ where: { domain: { id: domain.id }, id: In(ids) } as any, order: { name: 'ASC' } as any }))\n }\n\n @Directive('@privilege(category: \"saas-self\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(type => SaasAccount, { description: 'To fetch an account - a reader’s any, an admin’s own' })\n async saasAccount(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<SaasAccount> {\n const manager = getRepository(SaasAccount).manager\n const account = await accountIn(manager, context.state.domain, await scopeOf(context.state, 'query', manager), id)\n return (await withAdmins(manager, context.state, [account]))[0]\n }\n\n @Directive('@privilege(category: \"saas-self\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(type => [SaasSubscription], { description: 'The subscriptions of an account, with the seats held today' })\n async saasSubscriptions(@Arg('accountId') accountId: string, @Ctx() context: ResolverContext): Promise<SaasSubscription[]> {\n const manager = getRepository(SaasAccount).manager\n return saasSubscriptionsOf(manager, context.state.domain, await scopeOf(context.state, 'query', manager), accountId, today())\n }\n\n @Directive('@privilege(category: \"saas-self\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(type => [SaasSeat], { description: 'The seats of a subscription' })\n async saasSeats(@Arg('subscriptionId') subscriptionId: string, @Ctx() context: ResolverContext): Promise<SaasSeat[]> {\n const manager = getRepository(SaasAccount).manager\n return saasSeatsOf(manager, context.state.domain, await scopeOf(context.state, 'query', manager), subscriptionId)\n }\n\n @Directive('@privilege(category: \"saas-self\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(type => [SaasBill], { description: 'The bills of an account, latest first, with their lines' })\n async saasBills(@Arg('accountId') accountId: string, @Ctx() context: ResolverContext): Promise<SaasBill[]> {\n const manager = getRepository(SaasAccount).manager\n return saasBillsOf(manager, context.state.domain, await scopeOf(context.state, 'query', manager), accountId)\n }\n\n @Directive('@privilege(category: \"saas-self\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(type => [SaasChange], { description: 'What moved on an account and its subscriptions, newest first' })\n async saasChanges(@Arg('accountId') accountId: string, @Ctx() context: ResolverContext): Promise<SaasChange[]> {\n const manager = getRepository(SaasAccount).manager\n const rows = await saasChangesOf(manager, context.state.domain, await scopeOf(context.state, 'query', manager), accountId)\n return rows.map((one: any) => ({ subject: one.subject, factKind: one.factKind, field: one.field, fromValue: one.fromValue, toValue: one.toValue, at: one.at, changedBy: one.changedBy?.name }))\n }\n\n /* The bank lines are the bank's facts (ADR-0139): this door asks the bank's privilege, the account's scope on top. */\n @Directive('@privilege(category: \"bank\", privilege: \"query\", domainOwnerGranted: false)')\n @Query(type => [Transaction], { description: \"The bank lines that paid an account's vendor, newest first\" })\n async saasPayments(@Arg('accountId') accountId: string, @Ctx() context: ResolverContext): Promise<Transaction[]> {\n const manager = getRepository(SaasAccount).manager\n return saasPaymentsOf(manager, context.state.domain, await scopeOf(context.state, 'query', manager), accountId)\n }\n\n @Directive('@privilege(category: \"saas\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(type => SaasCostTrend, { description: 'The cost trend from the bills, month by month from one month to another (YYYY-MM)' })\n saasCostTrend(@Arg('from') from: string, @Arg('to') to: string, @Ctx() context: ResolverContext) {\n return saasCostTrend(getRepository(SaasAccount).manager, context.state.domain, from, to)\n }\n\n @FieldResolver(type => Counterparty, { nullable: true })\n counterparty(@Root() row: SaasAccount) {\n return row.counterparty ?? (row.counterpartyId ? getRepository(Counterparty).findOneBy({ id: row.counterpartyId }) : undefined)\n }\n\n @FieldResolver(type => SaasAccount, { nullable: true })\n parent(@Root() row: SaasAccount) {\n return row.parent ?? (row.parentId ? getRepository(SaasAccount).findOneBy({ id: row.parentId }) : undefined)\n }\n\n @FieldResolver(type => BankAccount, { nullable: true })\n paymentAccount(@Root() row: SaasAccount) {\n return row.paymentAccount ?? (row.paymentAccountId ? getRepository(BankAccount).findOneBy({ id: row.paymentAccountId }) : undefined)\n }\n\n @FieldResolver(type => Domain, { nullable: true })\n domain(@Root() row: SaasAccount) {\n return row.domain ?? (row.domainId ? getRepository(Domain).findOneBy({ id: row.domainId }) : undefined)\n }\n\n @FieldResolver(type => User, { nullable: true })\n updater(@Root() row: SaasAccount) {\n return row.updater ?? (row.updaterId ? getRepository(User).findOneBy({ id: row.updaterId }) : undefined)\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"saas-query.js","sourceRoot":"","sources":["../../server/service/saas-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { BankAccount, Transaction } from '@things-factory/accounting'\nimport { checkPermission, User } from '@things-factory/auth-base'\nimport { Counterparty } from '@things-factory/biz-base'\nimport { Domain, getQueryBuilderFromListParams, getRepository, ListParam, SpeakRefusals } from '@things-factory/shell'\nimport { Arg, Args, Ctx, Directive, FieldResolver, Query, Resolver, Root, UseMiddleware } from 'type-graphql'\nimport { In } from 'typeorm'\n\nimport { accountIn, administeredBy, scopeOf } from './saas-access'\nimport { SaasAccount } from './saas-account'\nimport { SaasBill } from './saas-bill'\nimport { saasBillsOf, saasCandidatesOf, saasChangesOf, saasCostTrend, saasPaymentsOf, saasSeatsOf, saasSubscriptionsOf, saasTrendsOf } from './saas-service'\nimport { SaasSeat } from './saas-seat'\nimport { SaasSubscription } from './saas-subscription'\nimport { SaasAccountList, SaasCandidate, SaasChange, SaasCostTrend } from './saas-type'\n\nconst today = () => new Date().toISOString().slice(0, 10)\n\n/** The accounts with their admins and their months (decision 10) - the list's relations in one read each. */\nasync function withAdmins(tx: any, state: any, items: SaasAccount[]) {\n if (!items.length) return items\n const { domain, user, unsafeIP, prohibitedPrivileges } = state\n const rows = await tx.getRepository(SaasAccount).find({ where: { id: In(items.map(one => one.id)) }, relations: ['admins'] })\n /* What left the bank is the bank's fact (ADR-0139) - read into the months only for whoever reads bank lines. */\n const withBank = await checkPermission({ category: 'bank', privilege: 'query', owner: false } as any, user, domain, unsafeIP, prohibitedPrivileges)\n const trends = await saasTrendsOf(tx, domain, items, today(), withBank)\n for (const one of items) {\n one.admins = rows.find(row => row.id === one.id)?.admins ?? []\n one.trend = trends.get(one.id)\n }\n return items\n}\n\n@UseMiddleware(SpeakRefusals)\n@Resolver(SaasAccount)\nexport class SaasAccountQuery {\n @Directive('@privilege(category: \"saas\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(type => SaasAccountList, { description: 'To fetch a page of the accounts the domain holds with vendors' })\n async saasAccounts(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<SaasAccountList> {\n const query = getQueryBuilderFromListParams({ domain: context.state.domain, params, repository: getRepository(SaasAccount), searchables: ['name', 'identifier', 'purpose', 'billingEmail', 'description'] })\n const [items, total] = await query.getManyAndCount()\n return { items: await withAdmins(getRepository(SaasAccount).manager, context.state, items), total }\n }\n\n @Directive('@privilege(category: \"saas-self\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(type => [SaasAccount], { description: 'The accounts the signed-in person is named an admin of' })\n async mySaasAccounts(@Ctx() context: ResolverContext): Promise<SaasAccount[]> {\n const { domain, user } = context.state\n const manager = getRepository(SaasAccount).manager\n const ids = await administeredBy(manager, domain, user?.id)\n if (!ids.length) return []\n return withAdmins(manager, context.state, await getRepository(SaasAccount).find({ where: { domain: { id: domain.id }, id: In(ids) } as any, order: { name: 'ASC' } as any }))\n }\n\n @Directive('@privilege(category: \"saas-self\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(type => SaasAccount, { description: 'To fetch an account - a reader’s any, an admin’s own' })\n async saasAccount(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<SaasAccount> {\n const manager = getRepository(SaasAccount).manager\n const account = await accountIn(manager, context.state.domain, await scopeOf(context.state, 'query', manager), id)\n return (await withAdmins(manager, context.state, [account]))[0]\n }\n\n @Directive('@privilege(category: \"saas-self\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(type => [SaasSubscription], { description: 'The subscriptions of an account, with the seats held today' })\n async saasSubscriptions(@Arg('accountId') accountId: string, @Ctx() context: ResolverContext): Promise<SaasSubscription[]> {\n const manager = getRepository(SaasAccount).manager\n return saasSubscriptionsOf(manager, context.state.domain, await scopeOf(context.state, 'query', manager), accountId, today())\n }\n\n @Directive('@privilege(category: \"saas-self\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(type => [SaasSeat], { description: 'The seats of a subscription' })\n async saasSeats(@Arg('subscriptionId') subscriptionId: string, @Ctx() context: ResolverContext): Promise<SaasSeat[]> {\n const manager = getRepository(SaasAccount).manager\n return saasSeatsOf(manager, context.state.domain, await scopeOf(context.state, 'query', manager), subscriptionId)\n }\n\n @Directive('@privilege(category: \"saas-self\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(type => [SaasBill], { description: 'The bills of an account, latest first, with their lines' })\n async saasBills(@Arg('accountId') accountId: string, @Ctx() context: ResolverContext): Promise<SaasBill[]> {\n const manager = getRepository(SaasAccount).manager\n return saasBillsOf(manager, context.state.domain, await scopeOf(context.state, 'query', manager), accountId)\n }\n\n @Directive('@privilege(category: \"saas-self\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(type => [SaasChange], { description: 'What moved on an account and its subscriptions, newest first' })\n async saasChanges(@Arg('accountId') accountId: string, @Ctx() context: ResolverContext): Promise<SaasChange[]> {\n const manager = getRepository(SaasAccount).manager\n const rows = await saasChangesOf(manager, context.state.domain, await scopeOf(context.state, 'query', manager), accountId)\n return rows.map((one: any) => ({ subject: one.subject, factKind: one.factKind, field: one.field, fromValue: one.fromValue, toValue: one.toValue, at: one.at, changedBy: one.changedBy?.name }))\n }\n\n /* The bank lines are the bank's facts (ADR-0139): this door asks the bank's privilege, the account's scope on top. */\n @Directive('@privilege(category: \"bank\", privilege: \"query\", domainOwnerGranted: false)')\n @Query(type => [Transaction], { description: \"The bank lines that paid an account's vendor, newest first\" })\n async saasPayments(@Arg('accountId') accountId: string, @Ctx() context: ResolverContext): Promise<Transaction[]> {\n const manager = getRepository(SaasAccount).manager\n return saasPaymentsOf(manager, context.state.domain, await scopeOf(context.state, 'query', manager), accountId)\n }\n\n /* Read from the bank and card lines (ADR-0139): the bank's door; the candidates are the keepers' (`saas`) on top. */\n @Directive('@privilege(category: \"bank\", privilege: \"query\", domainOwnerGranted: false)')\n @Query(type => [SaasCandidate], { description: 'The vendors the bank and card lines show paid month after month that are no account or recurring item yet; with hidden, the ones hidden' })\n async saasCandidates(@Arg('hidden', { nullable: true }) hidden: boolean, @Ctx() context: ResolverContext): Promise<SaasCandidate[]> {\n const manager = getRepository(SaasAccount).manager\n if ((await scopeOf(context.state, 'query', manager)) !== 'all') return []\n return saasCandidatesOf(manager, context.state.domain, today(), !!hidden) as any\n }\n\n @Directive('@privilege(category: \"saas\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(type => SaasCostTrend, { description: 'The cost trend from the bills, month by month from one month to another (YYYY-MM)' })\n saasCostTrend(@Arg('from') from: string, @Arg('to') to: string, @Ctx() context: ResolverContext) {\n return saasCostTrend(getRepository(SaasAccount).manager, context.state.domain, from, to)\n }\n\n @FieldResolver(type => Counterparty, { nullable: true })\n counterparty(@Root() row: SaasAccount) {\n return row.counterparty ?? (row.counterpartyId ? getRepository(Counterparty).findOneBy({ id: row.counterpartyId }) : undefined)\n }\n\n @FieldResolver(type => SaasAccount, { nullable: true })\n parent(@Root() row: SaasAccount) {\n return row.parent ?? (row.parentId ? getRepository(SaasAccount).findOneBy({ id: row.parentId }) : undefined)\n }\n\n @FieldResolver(type => BankAccount, { nullable: true })\n paymentAccount(@Root() row: SaasAccount) {\n return row.paymentAccount ?? (row.paymentAccountId ? getRepository(BankAccount).findOneBy({ id: row.paymentAccountId }) : undefined)\n }\n\n @FieldResolver(type => Domain, { nullable: true })\n domain(@Root() row: SaasAccount) {\n return row.domain ?? (row.domainId ? getRepository(Domain).findOneBy({ id: row.domainId }) : undefined)\n }\n\n @FieldResolver(type => User, { nullable: true })\n updater(@Root() row: SaasAccount) {\n return row.updater ?? (row.updaterId ? getRepository(User).findOneBy({ id: row.updaterId }) : undefined)\n }\n}\n"]}
|
|
@@ -136,3 +136,44 @@ export declare const seatHeld: (seat: {
|
|
|
136
136
|
fromOn?: string | null;
|
|
137
137
|
untilOn?: string | null;
|
|
138
138
|
}, today: string) => boolean;
|
|
139
|
+
/**
|
|
140
|
+
* A line of money out - a bank withdrawal or a card's charge - and whom it paid: its counterparty, or for a line no
|
|
141
|
+
* counterparty is linked to, the name written on it (`key` is the counterparty id, else `name:` and the name's key).
|
|
142
|
+
*/
|
|
143
|
+
export interface VendorLine {
|
|
144
|
+
key: string;
|
|
145
|
+
counterpartyId?: string | null;
|
|
146
|
+
name?: string | null;
|
|
147
|
+
transactionDate: string;
|
|
148
|
+
amount: number;
|
|
149
|
+
currency?: string | null;
|
|
150
|
+
bankAccountId?: string | null;
|
|
151
|
+
}
|
|
152
|
+
export interface CandidateFacts {
|
|
153
|
+
key: string;
|
|
154
|
+
/** The counterparty paid; none when the lines only name it - a new account registers it. */
|
|
155
|
+
counterpartyId: string | null;
|
|
156
|
+
/** The name written most on the lines. */
|
|
157
|
+
name: string | null;
|
|
158
|
+
/** The months money went out in, of the window. */
|
|
159
|
+
months: number;
|
|
160
|
+
/** What went out a month, on average over those months. */
|
|
161
|
+
average: number;
|
|
162
|
+
/** The first line of the window - the subscription is known to have started by then. */
|
|
163
|
+
firstDate: string;
|
|
164
|
+
lastDate: string;
|
|
165
|
+
lastAmount: number;
|
|
166
|
+
currency: string;
|
|
167
|
+
/** The account or card it went out of most. */
|
|
168
|
+
paymentAccountId: string | null;
|
|
169
|
+
/** The day of the month it went out on most; a month's last day is 31. */
|
|
170
|
+
billingDay: number | null;
|
|
171
|
+
}
|
|
172
|
+
/** At least this many months of the window paid one vendor before it looks like a subscription. */
|
|
173
|
+
export declare const CANDIDATE_MIN_MONTHS = 3;
|
|
174
|
+
/**
|
|
175
|
+
* Whom the lines say is paid month after month - in at least `CANDIDATE_MIN_MONTHS` months, in the currency paid most -
|
|
176
|
+
* each with what a new account and its subscription would start from. Those whose key is in `skip` (already an
|
|
177
|
+
* account, a recurring item, hidden) are not candidates. Largest first.
|
|
178
|
+
*/
|
|
179
|
+
export declare function candidatesOf(lines: readonly VendorLine[], skip: ReadonlySet<string>): CandidateFacts[];
|