@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"saas-service.js","sourceRoot":"","sources":["../../server/service/saas-service.ts"],"names":[],"mappings":"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","sourcesContent":["import { BankAccount, CashFlowType, Transaction, TransactionCategory } from '@things-factory/accounting'\nimport { Asset } from '@things-factory/asset'\n/* The register grids' save, the asset module's - this module saves its grids the same way (one implementation). */\nimport { amountOf, applyPatches, dayOf, Patch, textOf, touched } from '@things-factory/asset/dist-server/service/patches.js'\nimport { Counterparty } from '@things-factory/biz-base'\nimport { fieldChanges, readFactChanges, recordFactChanges } from '@things-factory/fact-change'\nimport { Department, Employee } from '@things-factory/organization'\nimport { Domain, Refusal } from '@things-factory/shell'\nimport { EntityManager, In } from 'typeorm'\n\nimport { accountIn, SaasScope } from './saas-access'\nimport { SaasAccount } from './saas-account'\nimport { SaasBill, SaasBillLine } from './saas-bill'\nimport {\n alertsOf,\n BillFacts,\n billTotal,\n expectedOfMonth,\n MONTH,\n monthsFrom,\n SaasAccountStatus,\n SaasBilling,\n SaasSubscriptionStatus,\n seatHeld,\n shiftMonth,\n trendOf\n} from './saas-rules'\nimport { SaasSeat } from './saas-seat'\nimport { SaasSubscription } from './saas-subscription'\nimport { SaasTrend } from './saas-trend-type'\n\nconst currencyOf = (value: any, fallback: string | null) => {\n const text = String(value ?? '').trim().toUpperCase()\n if (!text) return fallback\n if (!/^[A-Z]{3}$/.test(text)) throw new Refusal('saas-currency-invalid', { value: text }, `'${text}' is not a currency code (KRW, USD)`)\n return text\n}\n\nconst intOf = (value: any, code: string, min: number, max: number): number | null => {\n if (value === null || value === undefined || value === '') return null\n const number = Number(value)\n if (!Number.isInteger(number) || number < min || number > max) throw new Refusal(code, { min, max }, `Give a whole number from ${min} to ${max}`)\n return number\n}\n\nasync function oneOf<T>(tx: EntityManager, target: any, domain: Domain, id: string | null | undefined, code: string): Promise<T | null> {\n if (!id) return null\n const found = await tx.getRepository(target).findOne({ where: { domain: { id: domain.id }, id } as any })\n if (!found) throw new Refusal(code, {}, 'What it points at was not found')\n return found as T\n}\n\nconst field = (patch: Patch, name: string, old?: any) => (patch[name] !== undefined ? patch[name] : old?.[name])\n\n/*\n * What moved on an account or a subscription, field by field (ADR-0177 decision 11) - the fact-change module keeps it.\n * A row's relations are told by their id; a new row has no history yet.\n */\nexport const SAAS_ACCOUNT_FACT = 'saas-account'\nexport const SAAS_SUBSCRIPTION_FACT = 'saas-subscription'\nconst ACCOUNT_TRACKED = ['name', 'counterpartyId', 'identifier', 'parentId', 'paymentAccountId', 'currency', 'billingDay', 'increaseAlertRate', 'status', 'closedOn'] as const\nconst SUBSCRIPTION_TRACKED = ['name', 'billing', 'quantity', 'unitPrice', 'amount', 'budget', 'everyMonths', 'startOn', 'renewalOn', 'autoRenew', 'noticeDays', 'departmentId', 'assetId', 'status', 'endedOn'] as const\nconst idsOf = (row: Record<string, any>) =>\n 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])))\n\nasync function recordChanges(tx: EntityManager, domain: Domain, user: any, factKind: string, old: any, row: Record<string, any>, fields: readonly string[]) {\n if (!old) return\n const after = { ...old, ...idsOf(row) }\n await recordFactChanges(tx, domain, { factKind, factName: old.id, changes: fieldChanges(old, after, fields as any) }, { user, source: 'saas' })\n}\n\n/* ----------------------------------------------------------------------------------------------------------------- */\n/* Accounts (decision 2) - kept by `saas` keepers only */\n\nexport function saveSaasAccounts(tx: EntityManager, domain: Domain, user: any, patches: Patch[]) {\n return applyPatches(\n tx,\n SaasAccount,\n domain,\n user,\n patches,\n async (patch, old) => {\n const row: Record<string, any> = {}\n const name = touched(patch, 'name', old) ? textOf(patch.name) : old!.name\n if (!name) throw new Refusal('saas-account-name-required', {}, 'Name the service')\n row.name = name\n for (const one of ['identifier', 'purpose', 'billingEmail', 'secretLocation', 'description']) if (touched(patch, one, old)) row[one] = textOf(patch[one])\n if (touched(patch, 'currency', old)) row.currency = currencyOf(patch.currency, 'KRW')\n if (touched(patch, 'billingDay', old)) row.billingDay = intOf(patch.billingDay, 'saas-billing-day-invalid', 1, 31)\n if (touched(patch, 'increaseAlertRate', old)) {\n const rate = amountOf(patch.increaseAlertRate, 'saas-alert-rate-invalid')\n if (rate !== null && rate > 10) throw new Refusal('saas-alert-rate-invalid', {}, 'Give the rate as a part - 0.2 for 20%')\n row.increaseAlertRate = rate\n }\n if (touched(patch, 'counterpartyId', old)) row.counterparty = await oneOf(tx, Counterparty, domain, patch.counterpartyId, 'saas-counterparty-not-found')\n if (touched(patch, 'paymentAccountId', old)) row.paymentAccount = await oneOf(tx, BankAccount, domain, patch.paymentAccountId, 'saas-payment-account-not-found')\n if (touched(patch, 'parentId', old)) {\n const parent = await oneOf<SaasAccount>(tx, SaasAccount, domain, patch.parentId, 'saas-parent-not-found')\n if (parent && (parent.id === old?.id || (await tx.getRepository(SaasAccount).findOne({ where: { id: parent.id }, relations: ['parent'] }))?.parent))\n throw new Refusal('saas-parent-invalid', {}, 'An account is under a top account only, and not under itself')\n if (parent && old && (await tx.getRepository(SaasSubscription).count({ where: { account: { id: old.id } } as any })))\n throw new Refusal('saas-parent-has-subscriptions', {}, 'An account with subscriptions is billed itself - it cannot go under another')\n row.parent = parent\n }\n if (touched(patch, 'adminIds', old)) {\n const ids: string[] = [...new Set<string>((patch.adminIds ?? []).filter(Boolean))]\n const admins = ids.length ? await tx.getRepository(Employee).find({ where: { id: In(ids), domain: { id: domain.id } } as any }) : []\n if (admins.length !== ids.length) throw new Refusal('saas-admin-not-found', {}, 'An admin is no employee of this domain')\n row.admins = admins\n }\n if (touched(patch, 'status', old)) row.status = patch.status ?? SaasAccountStatus.ACTIVE\n if (touched(patch, 'closedOn', old)) row.closedOn = dayOf(patch.closedOn, 'saas-day-invalid')\n if ((row.status ?? old?.status) === SaasAccountStatus.CLOSED && !(row.closedOn !== undefined ? row.closedOn : old?.closedOn))\n throw new Refusal('saas-closed-on-required', {}, 'Give the day it was closed')\n await recordChanges(tx, domain, user, SAAS_ACCOUNT_FACT, old, row, ACCOUNT_TRACKED)\n return row\n },\n 'saas-account-not-found'\n )\n}\n\n/* ----------------------------------------------------------------------------------------------------------------- */\n/* Subscriptions (decision 3) - by keepers, and by the account's admins */\n\nexport async function saveSaasSubscriptions(tx: EntityManager, domain: Domain, user: any, scope: SaasScope, accountId: string, patches: Patch[]) {\n const account = await accountIn(tx, domain, scope, accountId)\n if (account.parentId && patches.some(one => one.cuFlag !== '-'))\n throw new Refusal('saas-subscription-on-sub-account', {}, 'An account under another is billed by its parent - subscribe there')\n return applyPatches(\n tx,\n SaasSubscription,\n domain,\n user,\n patches,\n async (patch, old) => {\n const row: Record<string, any> = old ? {} : { account }\n const name = touched(patch, 'name', old) ? textOf(patch.name) : old!.name\n if (!name) throw new Refusal('saas-subscription-name-required', {}, 'Name the product or plan')\n row.name = name\n const billing = (field(patch, 'billing', old) ?? SaasBilling.FIXED) as SaasBilling\n if (!Object.values(SaasBilling).includes(billing)) throw new Refusal('saas-billing-invalid', {}, 'Say how it is paid for')\n row.billing = billing\n for (const one of ['quantity', 'unitPrice', 'amount', 'budget']) if (touched(patch, one, old)) row[one] = amountOf(patch[one], 'saas-amount-invalid')\n const value = (name: string) => (row[name] !== undefined ? row[name] : old?.[name])\n if (billing === SaasBilling.SEAT && !(Number(value('quantity')) > 0 && value('unitPrice') !== null && value('unitPrice') !== undefined))\n throw new Refusal('saas-seat-price-required', {}, 'A seat plan takes its seats and the price of one')\n if ((billing === SaasBilling.FIXED || billing === SaasBilling.COMMITMENT) && (value('amount') === null || value('amount') === undefined))\n throw new Refusal('saas-amount-required', {}, 'Give what one billing costs')\n if (touched(patch, 'everyMonths', old)) row.everyMonths = intOf(patch.everyMonths, 'saas-every-months-invalid', 1, 120) ?? 1\n row.startOn = touched(patch, 'startOn', old) ? dayOf(patch.startOn, 'saas-start-on-invalid', true) : old!.startOn\n if (touched(patch, 'renewalOn', old)) row.renewalOn = dayOf(patch.renewalOn, 'saas-day-invalid')\n if (touched(patch, 'endedOn', old)) row.endedOn = dayOf(patch.endedOn, 'saas-day-invalid')\n if (touched(patch, 'autoRenew', old)) row.autoRenew = patch.autoRenew !== false\n if (touched(patch, 'noticeDays', old)) row.noticeDays = intOf(patch.noticeDays, 'saas-notice-days-invalid', 0, 365)\n if (touched(patch, 'description', old)) row.description = textOf(patch.description)\n if (touched(patch, 'departmentId', old)) row.department = await oneOf(tx, Department, domain, patch.departmentId, 'saas-department-not-found')\n if (touched(patch, 'assetId', old)) row.asset = await oneOf(tx, Asset, domain, patch.assetId, 'saas-asset-not-found')\n if (billing === SaasBilling.OWNED && !(row.asset !== undefined ? row.asset : old?.assetId))\n throw new Refusal('saas-owned-asset-required', {}, 'A license owned points at its asset in the register - its cost is there')\n if (billing === SaasBilling.COMMITMENT && !value('renewalOn')) throw new Refusal('saas-term-end-required', {}, 'A commitment takes the day its term ends')\n if (touched(patch, 'status', old)) row.status = patch.status ?? SaasSubscriptionStatus.ACTIVE\n const status = row.status ?? old?.status ?? SaasSubscriptionStatus.ACTIVE\n if (status === SaasSubscriptionStatus.CANCELLED && !value('endedOn')) throw new Refusal('saas-ended-on-required', {}, 'Give the day it ended')\n if (status === SaasSubscriptionStatus.CANCELLING && !value('renewalOn')) throw new Refusal('saas-renewal-on-required', {}, 'Not renewing needs the day it would renew')\n if (value('endedOn') && value('endedOn') < row.startOn) throw new Refusal('saas-ended-before-start', {}, 'It ended before it started')\n await recordChanges(tx, domain, user, SAAS_SUBSCRIPTION_FACT, old, row, SUBSCRIPTION_TRACKED)\n return row\n },\n 'saas-subscription-not-found',\n { account: { id: account.id } }\n )\n}\n\n/** The subscriptions of an account, with the seats held today. */\nexport async function saasSubscriptionsOf(tx: EntityManager, domain: Domain, scope: SaasScope, accountId: string, today: string) {\n const account = await accountIn(tx, domain, scope, accountId)\n const subs = await tx.getRepository(SaasSubscription).find({ where: { domain: { id: domain.id }, account: { id: account.id } } as any, relations: ['department', 'asset'], order: { name: 'ASC' } as any })\n const seats = subs.length ? await tx.getRepository(SaasSeat).find({ where: { domain: { id: domain.id }, subscription: { id: In(subs.map(one => one.id)) } } as any }) : []\n for (const sub of subs) sub.seatsHeld = seats.filter(seat => seat.subscriptionId === sub.id && seatHeld(seat, today)).length\n return subs\n}\n\n/* ----------------------------------------------------------------------------------------------------------------- */\n/* Seats (decision 6) */\n\nasync function subscriptionIn(tx: EntityManager, domain: Domain, scope: SaasScope, subscriptionId: string) {\n const sub = subscriptionId ? await tx.getRepository(SaasSubscription).findOne({ where: { domain: { id: domain.id }, id: subscriptionId } as any }) : null\n if (!sub || (scope !== 'all' && !scope.has(sub.accountId!))) throw new Refusal('saas-subscription-not-found', {}, 'The subscription was not found - reload and try again')\n return sub\n}\n\nexport async function saveSaasSeats(tx: EntityManager, domain: Domain, user: any, scope: SaasScope, subscriptionId: string, patches: Patch[]) {\n const subscription = await subscriptionIn(tx, domain, scope, subscriptionId)\n return applyPatches(\n tx,\n SaasSeat,\n domain,\n user,\n patches,\n async (patch, old) => {\n const row: Record<string, any> = old ? {} : { subscription }\n if (touched(patch, 'employeeId', old)) row.employee = await oneOf(tx, Employee, domain, patch.employeeId, 'saas-seat-employee-not-found')\n for (const one of ['holder', 'description']) if (touched(patch, one, old)) row[one] = textOf(patch[one])\n if (!(row.employee !== undefined ? row.employee : old?.employeeId) && !(row.holder !== undefined ? row.holder : old?.holder))\n throw new Refusal('saas-seat-holder-required', {}, 'Say who holds the seat - an employee, or a name')\n if (touched(patch, 'fromOn', old)) row.fromOn = dayOf(patch.fromOn, 'saas-day-invalid')\n if (touched(patch, 'untilOn', old)) row.untilOn = dayOf(patch.untilOn, 'saas-day-invalid')\n const from = row.fromOn !== undefined ? row.fromOn : old?.fromOn\n const until = row.untilOn !== undefined ? row.untilOn : old?.untilOn\n if (from && until && until < from) throw new Refusal('saas-seat-until-before-from', {}, 'It was taken back before it was given')\n return row\n },\n 'saas-seat-not-found',\n { subscription: { id: subscription.id } }\n )\n}\n\nexport async function saasSeatsOf(tx: EntityManager, domain: Domain, scope: SaasScope, subscriptionId: string) {\n const sub = await subscriptionIn(tx, domain, scope, subscriptionId)\n return tx.getRepository(SaasSeat).find({ where: { domain: { id: domain.id }, subscription: { id: sub.id } } as any, relations: ['employee'], order: { fromOn: 'DESC' } as any })\n}\n\n/* ----------------------------------------------------------------------------------------------------------------- */\n/* Bills (decisions 5, 9) - one an account a month, its lines replaced whole */\n\nexport interface SaasBillFields {\n id?: string | null\n month: string\n billedOn?: string | null\n description?: string | null\n lines: { subscriptionId?: string | null; label?: string | null; amount: number }[]\n}\n\nexport async function saveSaasBill(tx: EntityManager, domain: Domain, user: any, scope: SaasScope, accountId: string, input: SaasBillFields) {\n const account = await accountIn(tx, domain, scope, accountId)\n if (account.parentId) throw new Refusal('saas-bill-on-sub-account', {}, 'An account under another is billed by its parent')\n const month = String(input.month ?? '').trim()\n if (!MONTH.test(month)) throw new Refusal('saas-month-invalid', { value: month }, 'Write the month as YYYY-MM')\n const bills = tx.getRepository(SaasBill)\n const old = input.id ? await bills.findOne({ where: { domain: { id: domain.id }, id: input.id, account: { id: account.id } } as any }) : null\n if (input.id && !old) throw new Refusal('saas-bill-not-found', {}, 'The bill was not found - reload and try again')\n const twin = await bills.findOne({ where: { domain: { id: domain.id }, account: { id: account.id }, month } as any })\n if (twin && twin.id !== old?.id) throw new Refusal('saas-bill-month-taken', { month }, `The account already has a bill for ${month} - change that one`)\n const lines = (input.lines ?? []).filter(line => line && (line.subscriptionId || textOf(line.label) || Number(line.amount)))\n if (!lines.length) throw new Refusal('saas-bill-lines-required', {}, 'A bill takes at least one line')\n const subIds = [...new Set(lines.map(line => line.subscriptionId).filter(Boolean))] as string[]\n if (subIds.length) {\n const found = await tx.getRepository(SaasSubscription).count({ where: { domain: { id: domain.id }, account: { id: account.id }, id: In(subIds) } as any })\n if (found !== subIds.length) throw new Refusal('saas-bill-subscription-not-found', {}, 'A line names a subscription not of this account')\n }\n for (const line of lines) if (!Number.isFinite(Number(line.amount))) throw new Refusal('saas-amount-invalid', {}, 'Give the amount as a number')\n const bill = await bills.save({\n ...(old ?? { domain, account, creator: user, currency: account.currency }),\n month,\n billedOn: dayOf(input.billedOn, 'saas-day-invalid'),\n description: textOf(input.description),\n updater: user\n } as any)\n await tx.getRepository(SaasBillLine).delete({ bill: { id: bill.id } } as any)\n await tx.getRepository(SaasBillLine).save(\n lines.map(line => ({ domain, bill: { id: bill.id }, subscription: line.subscriptionId ? { id: line.subscriptionId } : null, label: textOf(line.label), amount: Number(line.amount) })) as any\n )\n return billsOf(tx, domain, [account.id]).then(all => all.find(one => one.id === bill.id)!)\n}\n\nexport async function deleteSaasBill(tx: EntityManager, domain: Domain, scope: SaasScope, id: string): Promise<boolean> {\n const bill = await tx.getRepository(SaasBill).findOne({ where: { domain: { id: domain.id }, id } as any })\n if (!bill || (scope !== 'all' && !scope.has(bill.accountId!))) throw new Refusal('saas-bill-not-found', {}, 'The bill was not found - reload and try again')\n await tx.getRepository(SaasBill).softDelete({ id })\n return true\n}\n\n/** The bills of some accounts (all when none named) from a month on, with their lines and totals, latest first. */\nexport async function billsOf(tx: EntityManager, domain: Domain, accountIds?: string[], from?: string, to?: string): Promise<SaasBill[]> {\n const query = tx\n .getRepository(SaasBill)\n .createQueryBuilder('bill')\n .leftJoinAndSelect('bill.lines', 'line')\n .leftJoinAndSelect('line.subscription', 'subscription')\n .where('bill.domain = :domain', { domain: domain.id })\n if (accountIds) {\n if (!accountIds.length) return []\n query.andWhere('bill.account IN (:...accounts)', { accounts: accountIds })\n }\n if (from) query.andWhere('bill.month >= :from', { from })\n if (to) query.andWhere('bill.month <= :to', { to })\n const bills = await query.orderBy('bill.month', 'DESC').getMany()\n for (const bill of bills) bill.total = billTotal(bill.lines ?? [])\n return bills\n}\n\nexport async function saasBillsOf(tx: EntityManager, domain: Domain, scope: SaasScope, accountId: string) {\n const account = await accountIn(tx, domain, scope, accountId)\n return billsOf(tx, domain, [account.id])\n}\n\nconst factsOf = (bill: SaasBill): BillFacts => ({\n accountId: bill.accountId!,\n month: bill.month,\n currency: bill.currency,\n lines: (bill.lines ?? []).map(line => ({ subscriptionId: line.subscriptionId ?? null, amount: Number(line.amount) }))\n})\n\n/* ----------------------------------------------------------------------------------------------------------------- */\n/* What is still to come (decision 4) - read by an application's expected cash */\n\nexport interface SaasExpectedRow {\n accountId: string\n accountName: string\n counterpartyId?: string | null\n paymentAccountId?: string | null\n month: string\n day: string | null\n amount: number\n currency: string\n /** A bill is written for the month: the amount is the bill's, not an estimate. */\n billed: boolean\n}\n\n/**\n * What each account is expected to be billed, month by month from `from` to `to`: the bill when one is written for the\n * month, else what its subscriptions say (usage at the average of its latest bills).\n */\nexport async function saasExpected(tx: EntityManager, domain: Domain, from: string, to: string): Promise<SaasExpectedRow[]> {\n const accounts = await tx.getRepository(SaasAccount).find({ where: { domain: { id: domain.id }, status: SaasAccountStatus.ACTIVE } as any })\n const top = accounts.filter(one => !one.parentId)\n if (!top.length) return []\n const subs = await tx.getRepository(SaasSubscription).find({ where: { domain: { id: domain.id }, account: { id: In(top.map(one => one.id)) } } as any })\n const bills = await billsOf(tx, domain, top.map(one => one.id), shiftMonth(from, -12), to)\n const billed = new Map<string, { month: string; amount: number }[]>()\n for (const bill of bills)\n if (bill.month < from)\n for (const line of bill.lines ?? []) if (line.subscriptionId) billed.set(line.subscriptionId, [...(billed.get(line.subscriptionId) ?? []), { month: bill.month, amount: Number(line.amount) }])\n const rows: SaasExpectedRow[] = []\n for (const account of top) {\n const own = subs.filter(one => one.accountId === account.id)\n for (const month of monthsFrom(from, to)) {\n const [year, m] = month.split('-').map(Number)\n const bill = bills.find(one => one.accountId === account.id && one.month === month)\n const expected = expectedOfMonth(account, own, billed, year, m)\n if (!bill && !expected) continue\n rows.push({\n accountId: account.id,\n accountName: account.name,\n counterpartyId: account.counterpartyId ?? null,\n paymentAccountId: account.paymentAccountId ?? null,\n month,\n day: bill?.billedOn ?? expected?.day ?? null,\n amount: bill ? bill.total! : expected!.amount,\n currency: account.currency,\n billed: !!bill\n })\n }\n }\n return rows\n}\n\n/* ----------------------------------------------------------------------------------------------------------------- */\n/* The cost trend (decision 9) */\n\n/** Whose department each employee is in. */\nasync function departmentsOfEmployees(tx: EntityManager, domain: Domain, ids: string[]): Promise<Map<string, { id: string; name: string }>> {\n if (!ids.length) return new Map()\n const employees = await tx.getRepository(Employee).find({ where: { domain: { id: domain.id }, id: In(ids) } as any, relations: ['department'] })\n return new Map(employees.filter(one => one.department).map(one => [one.id, { id: one.department!.id, name: one.department!.name }]))\n}\n\n/**\n * The bills of the months from `from` to `to` as series - all, an account, a subscription - and a department series: a\n * line of a seat plan split by the seats held at the month's end by department, any other line its subscription's\n * department. Plus what the latest month's bills are worth telling.\n */\nexport async function saasCostTrend(tx: EntityManager, domain: Domain, from: string, to: string) {\n if (!MONTH.test(from) || !MONTH.test(to) || from > to) throw new Refusal('saas-month-invalid', {}, 'Give the months as YYYY-MM, the first before the last')\n if (monthsFrom(from, to).length > 60) throw new Refusal('saas-trend-too-long', { max: 60 }, 'Up to 60 months at once')\n const bills = await billsOf(tx, domain, undefined, shiftMonth(from, -1), to)\n const facts = bills.map(factsOf)\n const trend = trendOf(facts, from, to)\n\n const accounts = await tx.getRepository(SaasAccount).find({ where: { domain: { id: domain.id } } as any, withDeleted: true })\n const subs = await tx.getRepository(SaasSubscription).find({ where: { domain: { id: domain.id } } as any, relations: ['department'], withDeleted: true })\n const seats = subs.length ? await tx.getRepository(SaasSeat).find({ where: { domain: { id: domain.id }, subscription: { id: In(subs.map(one => one.id)) } } as any }) : []\n const departmentOf = await departmentsOfEmployees(tx, domain, [...new Set(seats.map(one => one.employeeId).filter(Boolean))] as string[])\n\n const months = trend.months\n const departments = new Map<string, { key: string; departmentId: string | null; name: string | null; currency: string; amounts: number[] }>()\n const addTo = (id: string | null, name: string | null, currency: string, at: number, amount: number) => {\n const key = `${id ?? ''}|${currency}`\n let one = departments.get(key)\n if (!one) departments.set(key, (one = { key, departmentId: id, name, currency, amounts: months.map(() => 0) }))\n one.amounts[at] += amount\n }\n for (const bill of facts) {\n const at = months.indexOf(bill.month)\n if (at < 0) continue\n const monthEnd = `${bill.month}-31`\n for (const line of bill.lines) {\n const sub = subs.find(one => one.id === line.subscriptionId)\n const held = sub?.billing === SaasBilling.SEAT ? seats.filter(seat => seat.subscriptionId === sub.id && seatHeld(seat, monthEnd) && (!seat.fromOn || seat.fromOn <= monthEnd)) : []\n if (held.length) {\n for (const seat of held) {\n const department = seat.employeeId ? departmentOf.get(seat.employeeId) : undefined\n addTo(department?.id ?? sub?.department?.id ?? null, department?.name ?? sub?.department?.name ?? null, bill.currency, at, line.amount / held.length)\n }\n } else addTo(sub?.department?.id ?? null, sub?.department?.name ?? null, bill.currency, at, line.amount)\n }\n }\n\n const latest = facts.filter(one => one.month <= to).map(one => one.month).sort().pop()\n const alerts = latest\n ? facts\n .filter(one => one.month === latest)\n .flatMap(bill => {\n const account = accounts.find(one => one.id === bill.accountId)\n if (!account) return []\n const previous = facts.find(one => one.accountId === bill.accountId && one.month === shiftMonth(bill.month, -1))\n return alertsOf(account, subs.filter(one => one.accountId === account.id), bill, previous).map(alert => ({ ...alert, accountId: account.id, month: bill.month }))\n })\n : []\n\n const name = (id?: string | null) => accounts.find(one => one.id === id)?.name ?? null\n const subName = (id?: string | null) => subs.find(one => one.id === id)?.name ?? null\n return {\n months,\n all: trend.all,\n accounts: trend.accounts.map(one => ({ ...one, name: name(one.accountId) })),\n subscriptions: trend.subscriptions.map(one => ({ ...one, name: subName(one.subscriptionId), accountName: name(one.accountId) })),\n departments: [...departments.values()].map(one => ({ ...one, total: one.amounts.reduce((sum, amount) => sum + amount, 0) })).sort((a, b) => b.total - a.total),\n alerts: alerts.map(alert => ({ ...alert, accountName: name(alert.accountId), subscriptionName: subName(alert.subscriptionId) }))\n }\n}\n\n/* ----------------------------------------------------------------------------------------------------------------- */\n/* A row's months for the list and the 360 (decision 10) and what moved on it (decision 11) */\n\n/**\n * What left the bank for an account's vendor (ADR-0177 decision 10, the user 2026-10-30: 「이테크 입금 이력이 있을텐데」)\n * - the bank lines (accounting, confirmed) of money out to the account's counterparty, newest first. Only lines in the\n * account's currency count toward its months.\n */\nexport async function bankPaymentsOf(tx: EntityManager, domain: Domain, counterpartyIds: string[], from?: string, to?: string): Promise<Transaction[]> {\n if (!counterpartyIds.length) return []\n const query = tx\n .getRepository(Transaction)\n .createQueryBuilder('line')\n .where('line.domain = :domain', { domain: domain.id })\n .andWhere('line.category = :category', { category: TransactionCategory.CONFIRMED })\n .andWhere('line.type = :type', { type: CashFlowType.EXPENSE })\n .andWhere('line.counterparty IN (:...parties)', { parties: counterpartyIds })\n if (from) query.andWhere('line.transactionDate >= :from', { from })\n if (to) query.andWhere('line.transactionDate <= :to', { to })\n return query.orderBy('line.transactionDate', 'DESC').addOrderBy('line.amount', 'DESC').getMany()\n}\n\n/** The bank lines that paid an account's vendor, every one - for its 360. */\nexport async function saasPaymentsOf(tx: EntityManager, domain: Domain, scope: SaasScope, accountId: string) {\n const account = await accountIn(tx, domain, scope, accountId)\n return account.counterpartyId ? bankPaymentsOf(tx, domain, [account.counterpartyId]) : []\n}\n\n/**\n * Each account's last twelve months before this one and the next three expected (`saasExpected`). A month is its bill\n * when one is written; else, for a reader of the bank lines (`withBank`), what left the bank for its vendor that month\n * (decision 10); else empty. One read for all the accounts of a list.\n */\nexport async function saasTrendsOf(tx: EntityManager, domain: Domain, accounts: SaasAccount[], today: string, withBank = false): Promise<Map<string, SaasTrend>> {\n const trends = new Map<string, SaasTrend>()\n if (!accounts.length) return trends\n const now = today.slice(0, 7)\n const months = monthsFrom(shiftMonth(now, -12), shiftMonth(now, -1))\n const nextMonths = monthsFrom(now, shiftMonth(now, 2))\n const bills = await billsOf(tx, domain, accounts.map(one => one.id), months[0], months[months.length - 1])\n const expected = await saasExpected(tx, domain, nextMonths[0], nextMonths[nextMonths.length - 1])\n const parties = [...new Set(accounts.map(one => one.counterpartyId).filter(Boolean))] as string[]\n const paid = withBank ? await bankPaymentsOf(tx, domain, parties, `${months[0]}-01`, `${months[months.length - 1]}-31`) : []\n for (const account of accounts) {\n const own = bills.filter(one => one.accountId === account.id)\n const lines = paid.filter(line => line.counterpartyId === account.counterpartyId && (line.currency || 'KRW') === account.currency)\n const banked = (month: string) => {\n const of = lines.filter(line => line.transactionDate?.slice(0, 7) === month)\n return of.length ? of.reduce((sum, line) => sum + Number(line.amount), 0) : null\n }\n const values = months.map(month => own.find(one => one.month === month)?.total ?? banked(month))\n trends.set(account.id, {\n months,\n values,\n sources: months.map((month, i) => (own.some(one => one.month === month) ? 'bill' : values[i] === null ? null : 'bank')),\n nextMonths,\n expected: nextMonths.map(month => expected.find(one => one.accountId === account.id && one.month === month)?.amount ?? null),\n currency: account.currency\n })\n }\n return trends\n}\n\n/** What moved on an account and on each of its subscriptions, newest first. */\nexport async function saasChangesOf(tx: EntityManager, domain: Domain, scope: SaasScope, accountId: string) {\n const account = await accountIn(tx, domain, scope, accountId)\n const subs = await tx.getRepository(SaasSubscription).find({ where: { domain: { id: domain.id }, account: { id: account.id } } as any, withDeleted: true })\n const rows = [\n ...(await readFactChanges(tx, domain, SAAS_ACCOUNT_FACT, account.id)).map(one => Object.assign(one, { subject: account.name })),\n ...(await Promise.all(subs.map(async sub => (await readFactChanges(tx, domain, SAAS_SUBSCRIPTION_FACT, sub.id)).map(one => Object.assign(one, { subject: sub.name }))))).flat()\n ]\n return rows.sort((a, b) => new Date(b.at).getTime() - new Date(a.at).getTime())\n}\n"]}
|
|
1
|
+
{"version":3,"file":"saas-service.js","sourceRoot":"","sources":["../../server/service/saas-service.ts"],"names":[],"mappings":"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","sourcesContent":["import { BankAccount, CashFlowType, linkLinesByName, RecurringCashItem, Transaction, TransactionCategory } from '@things-factory/accounting'\nimport { Asset } from '@things-factory/asset'\n/* The register grids' save, the asset module's - this module saves its grids the same way (one implementation). */\nimport { amountOf, applyPatches, dayOf, Patch, textOf, touched } from '@things-factory/asset/dist-server/service/patches.js'\nimport { Counterparty, CounterpartyKind, looksLikePersonName, nameKey, partyNamed, saveCounterparties } from '@things-factory/biz-base'\nimport { fieldChanges, readFactChanges, recordFactChanges } from '@things-factory/fact-change'\nimport { Department, Employee } from '@things-factory/organization'\nimport { Domain, Refusal } from '@things-factory/shell'\nimport { EntityManager, In } from 'typeorm'\n\nimport { accountIn, SaasScope } from './saas-access'\nimport { SaasAccount } from './saas-account'\nimport { SaasBill, SaasBillLine } from './saas-bill'\nimport { SaasHiddenVendor } from './saas-hidden-vendor'\nimport {\n alertsOf,\n BillFacts,\n billTotal,\n candidatesOf,\n expectedOfMonth,\n MONTH,\n monthsFrom,\n SaasAccountStatus,\n SaasBilling,\n CandidateFacts,\n SaasSubscriptionStatus,\n seatHeld,\n shiftMonth,\n trendOf\n} from './saas-rules'\nimport { SaasSeat } from './saas-seat'\nimport { SaasSubscription } from './saas-subscription'\nimport { SaasTrend } from './saas-trend-type'\n\nconst currencyOf = (value: any, fallback: string | null) => {\n const text = String(value ?? '').trim().toUpperCase()\n if (!text) return fallback\n if (!/^[A-Z]{3}$/.test(text)) throw new Refusal('saas-currency-invalid', { value: text }, `'${text}' is not a currency code (KRW, USD)`)\n return text\n}\n\nconst intOf = (value: any, code: string, min: number, max: number): number | null => {\n if (value === null || value === undefined || value === '') return null\n const number = Number(value)\n if (!Number.isInteger(number) || number < min || number > max) throw new Refusal(code, { min, max }, `Give a whole number from ${min} to ${max}`)\n return number\n}\n\nasync function oneOf<T>(tx: EntityManager, target: any, domain: Domain, id: string | null | undefined, code: string): Promise<T | null> {\n if (!id) return null\n const found = await tx.getRepository(target).findOne({ where: { domain: { id: domain.id }, id } as any })\n if (!found) throw new Refusal(code, {}, 'What it points at was not found')\n return found as T\n}\n\nconst field = (patch: Patch, name: string, old?: any) => (patch[name] !== undefined ? patch[name] : old?.[name])\n\n/*\n * What moved on an account or a subscription, field by field (ADR-0177 decision 11) - the fact-change module keeps it.\n * A row's relations are told by their id; a new row has no history yet.\n */\nexport const SAAS_ACCOUNT_FACT = 'saas-account'\nexport const SAAS_SUBSCRIPTION_FACT = 'saas-subscription'\nconst ACCOUNT_TRACKED = ['name', 'counterpartyId', 'identifier', 'parentId', 'paymentAccountId', 'currency', 'billingDay', 'increaseAlertRate', 'status', 'closedOn'] as const\nconst SUBSCRIPTION_TRACKED = ['name', 'billing', 'vendorKey', 'trial', 'quantity', 'unitPrice', 'amount', 'budget', 'everyMonths', 'startOn', 'renewalOn', 'autoRenew', 'noticeDays', 'departmentId', 'assetId', 'status', 'endedOn'] as const\nconst idsOf = (row: Record<string, any>) =>\n 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])))\n\nasync function recordChanges(tx: EntityManager, domain: Domain, user: any, factKind: string, old: any, row: Record<string, any>, fields: readonly string[]) {\n if (!old) return\n const after = { ...old, ...idsOf(row) }\n await recordFactChanges(tx, domain, { factKind, factName: old.id, changes: fieldChanges(old, after, fields as any) }, { user, source: 'saas' })\n}\n\n/* ----------------------------------------------------------------------------------------------------------------- */\n/* Accounts (decision 2) - kept by `saas` keepers only */\n\nexport async function saveSaasAccounts(tx: EntityManager, domain: Domain, user: any, patches: Patch[]) {\n const saved = await applyPatches(\n tx,\n SaasAccount,\n domain,\n user,\n patches,\n async (patch, old) => {\n const row: Record<string, any> = {}\n const name = touched(patch, 'name', old) ? textOf(patch.name) : old!.name\n if (!name) throw new Refusal('saas-account-name-required', {}, 'Name the service')\n row.name = name\n for (const one of ['identifier', 'purpose', 'billingEmail', 'secretLocation', 'description']) if (touched(patch, one, old)) row[one] = textOf(patch[one])\n if (touched(patch, 'currency', old)) row.currency = currencyOf(patch.currency, 'KRW')\n if (touched(patch, 'billingDay', old)) row.billingDay = intOf(patch.billingDay, 'saas-billing-day-invalid', 1, 31)\n if (touched(patch, 'increaseAlertRate', old)) {\n const rate = amountOf(patch.increaseAlertRate, 'saas-alert-rate-invalid')\n if (rate !== null && rate > 10) throw new Refusal('saas-alert-rate-invalid', {}, 'Give the rate as a part - 0.2 for 20%')\n row.increaseAlertRate = rate\n }\n if (touched(patch, 'counterpartyId', old)) row.counterparty = await oneOf(tx, Counterparty, domain, patch.counterpartyId, 'saas-counterparty-not-found')\n if (touched(patch, 'paymentAccountId', old)) row.paymentAccount = await oneOf(tx, BankAccount, domain, patch.paymentAccountId, 'saas-payment-account-not-found')\n if (touched(patch, 'parentId', old)) {\n const parent = await oneOf<SaasAccount>(tx, SaasAccount, domain, patch.parentId, 'saas-parent-not-found')\n if (parent && (parent.id === old?.id || (await tx.getRepository(SaasAccount).findOne({ where: { id: parent.id }, relations: ['parent'] }))?.parent))\n throw new Refusal('saas-parent-invalid', {}, 'An account is under a top account only, and not under itself')\n if (parent && old && (await tx.getRepository(SaasSubscription).count({ where: { account: { id: old.id } } as any })))\n throw new Refusal('saas-parent-has-subscriptions', {}, 'An account with subscriptions is billed itself - it cannot go under another')\n row.parent = parent\n }\n if (touched(patch, 'adminIds', old)) {\n const ids: string[] = [...new Set<string>((patch.adminIds ?? []).filter(Boolean))]\n const admins = ids.length ? await tx.getRepository(Employee).find({ where: { id: In(ids), domain: { id: domain.id } } as any }) : []\n if (admins.length !== ids.length) throw new Refusal('saas-admin-not-found', {}, 'An admin is no employee of this domain')\n row.admins = admins\n }\n if (touched(patch, 'status', old)) row.status = patch.status ?? SaasAccountStatus.ACTIVE\n if (touched(patch, 'closedOn', old)) row.closedOn = dayOf(patch.closedOn, 'saas-day-invalid')\n if ((row.status ?? old?.status) === SaasAccountStatus.CLOSED && !(row.closedOn !== undefined ? row.closedOn : old?.closedOn))\n throw new Refusal('saas-closed-on-required', {}, 'Give the day it was closed')\n await recordChanges(tx, domain, user, SAAS_ACCOUNT_FACT, old, row, ACCOUNT_TRACKED)\n return row\n },\n 'saas-account-not-found'\n )\n /* The vendor's lines written with its name and not linked yet are the account's months (개정 1). */\n const vendors = patches.filter(one => one.cuFlag !== '-' && one.counterpartyId).map(one => one.counterpartyId as string)\n if (vendors.length) await linkLinesByName(tx, domain, user, vendors)\n return saved\n}\n\n/* ----------------------------------------------------------------------------------------------------------------- */\n/* Subscriptions (decision 3) - by keepers, and by the account's admins */\n\nexport async function saveSaasSubscriptions(tx: EntityManager, domain: Domain, user: any, scope: SaasScope, accountId: string, patches: Patch[]) {\n const account = await accountIn(tx, domain, scope, accountId)\n if (account.parentId && patches.some(one => one.cuFlag !== '-'))\n throw new Refusal('saas-subscription-on-sub-account', {}, 'An account under another is billed by its parent - subscribe there')\n return applyPatches(\n tx,\n SaasSubscription,\n domain,\n user,\n patches,\n async (patch, old) => {\n const row: Record<string, any> = old ? {} : { account }\n const name = touched(patch, 'name', old) ? textOf(patch.name) : old!.name\n if (!name) throw new Refusal('saas-subscription-name-required', {}, 'Name the product or plan')\n row.name = name\n const billing = (field(patch, 'billing', old) ?? SaasBilling.FIXED) as SaasBilling\n if (!Object.values(SaasBilling).includes(billing)) throw new Refusal('saas-billing-invalid', {}, 'Say how it is paid for')\n row.billing = billing\n for (const one of ['quantity', 'unitPrice', 'amount', 'budget']) if (touched(patch, one, old)) row[one] = amountOf(patch[one], 'saas-amount-invalid')\n /* `vendorKey` and `trial` are a sync's (개정 2) - the GraphQL patch does not carry them. */\n if (touched(patch, 'vendorKey', old)) row.vendorKey = textOf(patch.vendorKey)\n if (touched(patch, 'trial', old)) row.trial = patch.trial === true\n const value = (name: string) => (row[name] !== undefined ? row[name] : old?.[name])\n /* A plan read from the vendor's tenant may wait for its price (개정 2) - it is expected at nothing until then. */\n const priced = value('unitPrice') !== null && value('unitPrice') !== undefined\n if (billing === SaasBilling.SEAT && !(Number(value('quantity')) > 0 && (priced || value('vendorKey'))))\n throw new Refusal('saas-seat-price-required', {}, 'A seat plan takes its seats and the price of one')\n if ((billing === SaasBilling.FIXED || billing === SaasBilling.COMMITMENT) && (value('amount') === null || value('amount') === undefined))\n throw new Refusal('saas-amount-required', {}, 'Give what one billing costs')\n if (touched(patch, 'everyMonths', old)) row.everyMonths = intOf(patch.everyMonths, 'saas-every-months-invalid', 1, 120) ?? 1\n row.startOn = touched(patch, 'startOn', old) ? dayOf(patch.startOn, 'saas-start-on-invalid', true) : old!.startOn\n if (touched(patch, 'renewalOn', old)) row.renewalOn = dayOf(patch.renewalOn, 'saas-day-invalid')\n if (touched(patch, 'endedOn', old)) row.endedOn = dayOf(patch.endedOn, 'saas-day-invalid')\n if (touched(patch, 'autoRenew', old)) row.autoRenew = patch.autoRenew !== false\n if (touched(patch, 'noticeDays', old)) row.noticeDays = intOf(patch.noticeDays, 'saas-notice-days-invalid', 0, 365)\n if (touched(patch, 'description', old)) row.description = textOf(patch.description)\n if (touched(patch, 'departmentId', old)) row.department = await oneOf(tx, Department, domain, patch.departmentId, 'saas-department-not-found')\n if (touched(patch, 'assetId', old)) row.asset = await oneOf(tx, Asset, domain, patch.assetId, 'saas-asset-not-found')\n if (billing === SaasBilling.OWNED && !(row.asset !== undefined ? row.asset : old?.assetId))\n throw new Refusal('saas-owned-asset-required', {}, 'A license owned points at its asset in the register - its cost is there')\n if (billing === SaasBilling.COMMITMENT && !value('renewalOn')) throw new Refusal('saas-term-end-required', {}, 'A commitment takes the day its term ends')\n if (touched(patch, 'status', old)) row.status = patch.status ?? SaasSubscriptionStatus.ACTIVE\n const status = row.status ?? old?.status ?? SaasSubscriptionStatus.ACTIVE\n if (status === SaasSubscriptionStatus.CANCELLED && !value('endedOn')) throw new Refusal('saas-ended-on-required', {}, 'Give the day it ended')\n if (status === SaasSubscriptionStatus.CANCELLING && !value('renewalOn')) throw new Refusal('saas-renewal-on-required', {}, 'Not renewing needs the day it would renew')\n if (value('endedOn') && value('endedOn') < row.startOn) throw new Refusal('saas-ended-before-start', {}, 'It ended before it started')\n await recordChanges(tx, domain, user, SAAS_SUBSCRIPTION_FACT, old, row, SUBSCRIPTION_TRACKED)\n return row\n },\n 'saas-subscription-not-found',\n { account: { id: account.id } }\n )\n}\n\n/** The subscriptions of an account, with the seats held today. */\nexport async function saasSubscriptionsOf(tx: EntityManager, domain: Domain, scope: SaasScope, accountId: string, today: string) {\n const account = await accountIn(tx, domain, scope, accountId)\n const subs = await tx.getRepository(SaasSubscription).find({ where: { domain: { id: domain.id }, account: { id: account.id } } as any, relations: ['department', 'asset'], order: { name: 'ASC' } as any })\n const seats = subs.length ? await tx.getRepository(SaasSeat).find({ where: { domain: { id: domain.id }, subscription: { id: In(subs.map(one => one.id)) } } as any }) : []\n for (const sub of subs) sub.seatsHeld = seats.filter(seat => seat.subscriptionId === sub.id && seatHeld(seat, today)).length\n return subs\n}\n\n/* ----------------------------------------------------------------------------------------------------------------- */\n/* Seats (decision 6) */\n\nasync function subscriptionIn(tx: EntityManager, domain: Domain, scope: SaasScope, subscriptionId: string) {\n const sub = subscriptionId ? await tx.getRepository(SaasSubscription).findOne({ where: { domain: { id: domain.id }, id: subscriptionId } as any }) : null\n if (!sub || (scope !== 'all' && !scope.has(sub.accountId!))) throw new Refusal('saas-subscription-not-found', {}, 'The subscription was not found - reload and try again')\n return sub\n}\n\nexport async function saveSaasSeats(tx: EntityManager, domain: Domain, user: any, scope: SaasScope, subscriptionId: string, patches: Patch[]) {\n const subscription = await subscriptionIn(tx, domain, scope, subscriptionId)\n return applyPatches(\n tx,\n SaasSeat,\n domain,\n user,\n patches,\n async (patch, old) => {\n const row: Record<string, any> = old ? {} : { subscription }\n if (touched(patch, 'employeeId', old)) row.employee = await oneOf(tx, Employee, domain, patch.employeeId, 'saas-seat-employee-not-found')\n /* `login` is a sync's (개정 2) - the GraphQL patch does not carry it. */\n for (const one of ['holder', 'login', 'description']) if (touched(patch, one, old)) row[one] = textOf(patch[one])\n if (!(row.employee !== undefined ? row.employee : old?.employeeId) && !(row.holder !== undefined ? row.holder : old?.holder))\n throw new Refusal('saas-seat-holder-required', {}, 'Say who holds the seat - an employee, or a name')\n if (touched(patch, 'fromOn', old)) row.fromOn = dayOf(patch.fromOn, 'saas-day-invalid')\n if (touched(patch, 'untilOn', old)) row.untilOn = dayOf(patch.untilOn, 'saas-day-invalid')\n const from = row.fromOn !== undefined ? row.fromOn : old?.fromOn\n const until = row.untilOn !== undefined ? row.untilOn : old?.untilOn\n if (from && until && until < from) throw new Refusal('saas-seat-until-before-from', {}, 'It was taken back before it was given')\n return row\n },\n 'saas-seat-not-found',\n { subscription: { id: subscription.id } }\n )\n}\n\nexport async function saasSeatsOf(tx: EntityManager, domain: Domain, scope: SaasScope, subscriptionId: string) {\n const sub = await subscriptionIn(tx, domain, scope, subscriptionId)\n return tx.getRepository(SaasSeat).find({ where: { domain: { id: domain.id }, subscription: { id: sub.id } } as any, relations: ['employee'], order: { fromOn: 'DESC' } as any })\n}\n\n/* ----------------------------------------------------------------------------------------------------------------- */\n/* Bills (decisions 5, 9) - one an account a month, its lines replaced whole */\n\nexport interface SaasBillFields {\n id?: string | null\n month: string\n billedOn?: string | null\n description?: string | null\n lines: { subscriptionId?: string | null; label?: string | null; amount: number }[]\n}\n\nexport async function saveSaasBill(tx: EntityManager, domain: Domain, user: any, scope: SaasScope, accountId: string, input: SaasBillFields) {\n const account = await accountIn(tx, domain, scope, accountId)\n if (account.parentId) throw new Refusal('saas-bill-on-sub-account', {}, 'An account under another is billed by its parent')\n const month = String(input.month ?? '').trim()\n if (!MONTH.test(month)) throw new Refusal('saas-month-invalid', { value: month }, 'Write the month as YYYY-MM')\n const bills = tx.getRepository(SaasBill)\n const old = input.id ? await bills.findOne({ where: { domain: { id: domain.id }, id: input.id, account: { id: account.id } } as any }) : null\n if (input.id && !old) throw new Refusal('saas-bill-not-found', {}, 'The bill was not found - reload and try again')\n const twin = await bills.findOne({ where: { domain: { id: domain.id }, account: { id: account.id }, month } as any })\n if (twin && twin.id !== old?.id) throw new Refusal('saas-bill-month-taken', { month }, `The account already has a bill for ${month} - change that one`)\n const lines = (input.lines ?? []).filter(line => line && (line.subscriptionId || textOf(line.label) || Number(line.amount)))\n if (!lines.length) throw new Refusal('saas-bill-lines-required', {}, 'A bill takes at least one line')\n const subIds = [...new Set(lines.map(line => line.subscriptionId).filter(Boolean))] as string[]\n if (subIds.length) {\n const found = await tx.getRepository(SaasSubscription).count({ where: { domain: { id: domain.id }, account: { id: account.id }, id: In(subIds) } as any })\n if (found !== subIds.length) throw new Refusal('saas-bill-subscription-not-found', {}, 'A line names a subscription not of this account')\n }\n for (const line of lines) if (!Number.isFinite(Number(line.amount))) throw new Refusal('saas-amount-invalid', {}, 'Give the amount as a number')\n const bill = await bills.save({\n ...(old ?? { domain, account, creator: user, currency: account.currency }),\n month,\n billedOn: dayOf(input.billedOn, 'saas-day-invalid'),\n description: textOf(input.description),\n updater: user\n } as any)\n await tx.getRepository(SaasBillLine).delete({ bill: { id: bill.id } } as any)\n await tx.getRepository(SaasBillLine).save(\n lines.map(line => ({ domain, bill: { id: bill.id }, subscription: line.subscriptionId ? { id: line.subscriptionId } : null, label: textOf(line.label), amount: Number(line.amount) })) as any\n )\n return billsOf(tx, domain, [account.id]).then(all => all.find(one => one.id === bill.id)!)\n}\n\nexport async function deleteSaasBill(tx: EntityManager, domain: Domain, scope: SaasScope, id: string): Promise<boolean> {\n const bill = await tx.getRepository(SaasBill).findOne({ where: { domain: { id: domain.id }, id } as any })\n if (!bill || (scope !== 'all' && !scope.has(bill.accountId!))) throw new Refusal('saas-bill-not-found', {}, 'The bill was not found - reload and try again')\n await tx.getRepository(SaasBill).softDelete({ id })\n return true\n}\n\n/** The bills of some accounts (all when none named) from a month on, with their lines and totals, latest first. */\nexport async function billsOf(tx: EntityManager, domain: Domain, accountIds?: string[], from?: string, to?: string): Promise<SaasBill[]> {\n const query = tx\n .getRepository(SaasBill)\n .createQueryBuilder('bill')\n .leftJoinAndSelect('bill.lines', 'line')\n .leftJoinAndSelect('line.subscription', 'subscription')\n .where('bill.domain = :domain', { domain: domain.id })\n if (accountIds) {\n if (!accountIds.length) return []\n query.andWhere('bill.account IN (:...accounts)', { accounts: accountIds })\n }\n if (from) query.andWhere('bill.month >= :from', { from })\n if (to) query.andWhere('bill.month <= :to', { to })\n const bills = await query.orderBy('bill.month', 'DESC').getMany()\n for (const bill of bills) bill.total = billTotal(bill.lines ?? [])\n return bills\n}\n\nexport async function saasBillsOf(tx: EntityManager, domain: Domain, scope: SaasScope, accountId: string) {\n const account = await accountIn(tx, domain, scope, accountId)\n return billsOf(tx, domain, [account.id])\n}\n\nconst factsOf = (bill: SaasBill): BillFacts => ({\n accountId: bill.accountId!,\n month: bill.month,\n currency: bill.currency,\n lines: (bill.lines ?? []).map(line => ({ subscriptionId: line.subscriptionId ?? null, amount: Number(line.amount) }))\n})\n\n/* ----------------------------------------------------------------------------------------------------------------- */\n/* What is still to come (decision 4) - read by an application's expected cash */\n\nexport interface SaasExpectedRow {\n accountId: string\n accountName: string\n counterpartyId?: string | null\n paymentAccountId?: string | null\n month: string\n day: string | null\n amount: number\n currency: string\n /** A bill is written for the month: the amount is the bill's, not an estimate. */\n billed: boolean\n}\n\n/**\n * What each account is expected to be billed, month by month from `from` to `to`: the bill when one is written for the\n * month, else what its subscriptions say (usage at the average of its latest bills).\n */\nexport async function saasExpected(tx: EntityManager, domain: Domain, from: string, to: string): Promise<SaasExpectedRow[]> {\n const accounts = await tx.getRepository(SaasAccount).find({ where: { domain: { id: domain.id }, status: SaasAccountStatus.ACTIVE } as any })\n const top = accounts.filter(one => !one.parentId)\n if (!top.length) return []\n const subs = await tx.getRepository(SaasSubscription).find({ where: { domain: { id: domain.id }, account: { id: In(top.map(one => one.id)) } } as any })\n const bills = await billsOf(tx, domain, top.map(one => one.id), shiftMonth(from, -12), to)\n const billed = new Map<string, { month: string; amount: number }[]>()\n for (const bill of bills)\n if (bill.month < from)\n for (const line of bill.lines ?? []) if (line.subscriptionId) billed.set(line.subscriptionId, [...(billed.get(line.subscriptionId) ?? []), { month: bill.month, amount: Number(line.amount) }])\n const rows: SaasExpectedRow[] = []\n for (const account of top) {\n const own = subs.filter(one => one.accountId === account.id)\n for (const month of monthsFrom(from, to)) {\n const [year, m] = month.split('-').map(Number)\n const bill = bills.find(one => one.accountId === account.id && one.month === month)\n const expected = expectedOfMonth(account, own, billed, year, m)\n if (!bill && !expected) continue\n rows.push({\n accountId: account.id,\n accountName: account.name,\n counterpartyId: account.counterpartyId ?? null,\n paymentAccountId: account.paymentAccountId ?? null,\n month,\n day: bill?.billedOn ?? expected?.day ?? null,\n amount: bill ? bill.total! : expected!.amount,\n currency: account.currency,\n billed: !!bill\n })\n }\n }\n return rows\n}\n\n/* ----------------------------------------------------------------------------------------------------------------- */\n/* The cost trend (decision 9) */\n\n/** Whose department each employee is in. */\nasync function departmentsOfEmployees(tx: EntityManager, domain: Domain, ids: string[]): Promise<Map<string, { id: string; name: string }>> {\n if (!ids.length) return new Map()\n const employees = await tx.getRepository(Employee).find({ where: { domain: { id: domain.id }, id: In(ids) } as any, relations: ['department'] })\n return new Map(employees.filter(one => one.department).map(one => [one.id, { id: one.department!.id, name: one.department!.name }]))\n}\n\n/**\n * The bills of the months from `from` to `to` as series - all, an account, a subscription - and a department series: a\n * line of a seat plan split by the seats held at the month's end by department, any other line its subscription's\n * department. Plus what the latest month's bills are worth telling.\n */\nexport async function saasCostTrend(tx: EntityManager, domain: Domain, from: string, to: string) {\n if (!MONTH.test(from) || !MONTH.test(to) || from > to) throw new Refusal('saas-month-invalid', {}, 'Give the months as YYYY-MM, the first before the last')\n if (monthsFrom(from, to).length > 60) throw new Refusal('saas-trend-too-long', { max: 60 }, 'Up to 60 months at once')\n const bills = await billsOf(tx, domain, undefined, shiftMonth(from, -1), to)\n const facts = bills.map(factsOf)\n const trend = trendOf(facts, from, to)\n\n const accounts = await tx.getRepository(SaasAccount).find({ where: { domain: { id: domain.id } } as any, withDeleted: true })\n const subs = await tx.getRepository(SaasSubscription).find({ where: { domain: { id: domain.id } } as any, relations: ['department'], withDeleted: true })\n const seats = subs.length ? await tx.getRepository(SaasSeat).find({ where: { domain: { id: domain.id }, subscription: { id: In(subs.map(one => one.id)) } } as any }) : []\n const departmentOf = await departmentsOfEmployees(tx, domain, [...new Set(seats.map(one => one.employeeId).filter(Boolean))] as string[])\n\n const months = trend.months\n const departments = new Map<string, { key: string; departmentId: string | null; name: string | null; currency: string; amounts: number[] }>()\n const addTo = (id: string | null, name: string | null, currency: string, at: number, amount: number) => {\n const key = `${id ?? ''}|${currency}`\n let one = departments.get(key)\n if (!one) departments.set(key, (one = { key, departmentId: id, name, currency, amounts: months.map(() => 0) }))\n one.amounts[at] += amount\n }\n for (const bill of facts) {\n const at = months.indexOf(bill.month)\n if (at < 0) continue\n const monthEnd = `${bill.month}-31`\n for (const line of bill.lines) {\n const sub = subs.find(one => one.id === line.subscriptionId)\n const held = sub?.billing === SaasBilling.SEAT ? seats.filter(seat => seat.subscriptionId === sub.id && seatHeld(seat, monthEnd) && (!seat.fromOn || seat.fromOn <= monthEnd)) : []\n if (held.length) {\n for (const seat of held) {\n const department = seat.employeeId ? departmentOf.get(seat.employeeId) : undefined\n addTo(department?.id ?? sub?.department?.id ?? null, department?.name ?? sub?.department?.name ?? null, bill.currency, at, line.amount / held.length)\n }\n } else addTo(sub?.department?.id ?? null, sub?.department?.name ?? null, bill.currency, at, line.amount)\n }\n }\n\n const latest = facts.filter(one => one.month <= to).map(one => one.month).sort().pop()\n const alerts = latest\n ? facts\n .filter(one => one.month === latest)\n .flatMap(bill => {\n const account = accounts.find(one => one.id === bill.accountId)\n if (!account) return []\n const previous = facts.find(one => one.accountId === bill.accountId && one.month === shiftMonth(bill.month, -1))\n return alertsOf(account, subs.filter(one => one.accountId === account.id), bill, previous).map(alert => ({ ...alert, accountId: account.id, month: bill.month }))\n })\n : []\n\n const name = (id?: string | null) => accounts.find(one => one.id === id)?.name ?? null\n const subName = (id?: string | null) => subs.find(one => one.id === id)?.name ?? null\n return {\n months,\n all: trend.all,\n accounts: trend.accounts.map(one => ({ ...one, name: name(one.accountId) })),\n subscriptions: trend.subscriptions.map(one => ({ ...one, name: subName(one.subscriptionId), accountName: name(one.accountId) })),\n departments: [...departments.values()].map(one => ({ ...one, total: one.amounts.reduce((sum, amount) => sum + amount, 0) })).sort((a, b) => b.total - a.total),\n alerts: alerts.map(alert => ({ ...alert, accountName: name(alert.accountId), subscriptionName: subName(alert.subscriptionId) }))\n }\n}\n\n/* ----------------------------------------------------------------------------------------------------------------- */\n/* A row's months for the list and the 360 (decision 10) and what moved on it (decision 11) */\n\n/**\n * What went out to an account's vendor (ADR-0177 decision 10, the user 2026-10-30: 「이테크 입금 이력이 있을텐데」;\n * 개정 1) - the bank withdrawals and the card charges (accounting, CONFIRMED and CARD) to the account's counterparty,\n * newest first. A line takes its counterparty when it lands (accounting `saveTransactions`), so a vendor's lines are\n * its linked ones. Only lines in the account's currency count toward its months.\n */\nexport async function vendorLinesOf(tx: EntityManager, domain: Domain, counterpartyIds: string[], from?: string, to?: string): Promise<Transaction[]> {\n if (!counterpartyIds.length) return []\n const query = tx\n .getRepository(Transaction)\n .createQueryBuilder('line')\n .leftJoinAndSelect('line.bankAccount', 'bankAccount')\n .where('line.domain = :domain', { domain: domain.id })\n .andWhere('line.category IN (:...categories)', { categories: [TransactionCategory.CONFIRMED, TransactionCategory.CARD] })\n .andWhere('line.type = :type', { type: CashFlowType.EXPENSE })\n .andWhere('line.counterparty IN (:...parties)', { parties: counterpartyIds })\n if (from) query.andWhere('line.transactionDate >= :from', { from })\n if (to) query.andWhere('line.transactionDate <= :to', { to })\n return query.orderBy('line.transactionDate', 'DESC').addOrderBy('line.amount', 'DESC').getMany()\n}\n\n/** The bank and card lines that paid an account's vendor, every one - for its 360. */\nexport async function saasPaymentsOf(tx: EntityManager, domain: Domain, scope: SaasScope, accountId: string) {\n const account = await accountIn(tx, domain, scope, accountId)\n return account.counterpartyId ? vendorLinesOf(tx, domain, [account.counterpartyId]) : []\n}\n\n/**\n * Each account's last twelve months before this one and the next three expected (`saasExpected`). A month is its bill\n * when one is written; else, for a reader of the bank lines (`withBank`), what went out to its vendor that month from\n * the bank or a card (decision 10, 개정 1); else empty. One read for all the accounts of a list.\n */\nexport async function saasTrendsOf(tx: EntityManager, domain: Domain, accounts: SaasAccount[], today: string, withBank = false): Promise<Map<string, SaasTrend>> {\n const trends = new Map<string, SaasTrend>()\n if (!accounts.length) return trends\n const now = today.slice(0, 7)\n const months = monthsFrom(shiftMonth(now, -12), shiftMonth(now, -1))\n const nextMonths = monthsFrom(now, shiftMonth(now, 2))\n const bills = await billsOf(tx, domain, accounts.map(one => one.id), months[0], months[months.length - 1])\n const expected = await saasExpected(tx, domain, nextMonths[0], nextMonths[nextMonths.length - 1])\n const parties = [...new Set(accounts.map(one => one.counterpartyId).filter(Boolean))] as string[]\n const paid = withBank ? await vendorLinesOf(tx, domain, parties, `${months[0]}-01`, `${months[months.length - 1]}-31`) : []\n for (const account of accounts) {\n const own = bills.filter(one => one.accountId === account.id)\n const lines = paid.filter(line => line.counterpartyId === account.counterpartyId && (line.currency || 'KRW') === account.currency)\n const banked = (month: string) => {\n const of = lines.filter(line => line.transactionDate?.slice(0, 7) === month)\n return of.length ? of.reduce((sum, line) => sum + Number(line.amount), 0) : null\n }\n const values = months.map(month => own.find(one => one.month === month)?.total ?? banked(month))\n trends.set(account.id, {\n months,\n values,\n sources: months.map((month, i) =>\n own.some(one => one.month === month)\n ? 'bill'\n : values[i] === null\n ? null\n : lines.some(line => line.transactionDate?.slice(0, 7) === month && line.category === TransactionCategory.CONFIRMED)\n ? 'bank'\n : 'card'\n ),\n nextMonths,\n expected: nextMonths.map(month => expected.find(one => one.accountId === account.id && one.month === month)?.amount ?? null),\n currency: account.currency\n })\n }\n return trends\n}\n\n/** What moved on an account and on each of its subscriptions, newest first. */\nexport async function saasChangesOf(tx: EntityManager, domain: Domain, scope: SaasScope, accountId: string) {\n const account = await accountIn(tx, domain, scope, accountId)\n const subs = await tx.getRepository(SaasSubscription).find({ where: { domain: { id: domain.id }, account: { id: account.id } } as any, withDeleted: true })\n const rows = [\n ...(await readFactChanges(tx, domain, SAAS_ACCOUNT_FACT, account.id)).map(one => Object.assign(one, { subject: account.name })),\n ...(await Promise.all(subs.map(async sub => (await readFactChanges(tx, domain, SAAS_SUBSCRIPTION_FACT, sub.id)).map(one => Object.assign(one, { subject: sub.name }))))).flat()\n ]\n return rows.sort((a, b) => new Date(b.at).getTime() - new Date(a.at).getTime())\n}\n\n/* ----------------------------------------------------------------------------------------------------------------- */\n/* What the books already say is subscribed to (개정 1) */\n\n/** A candidate with its vendor's name, for the list. */\nexport type SaasCandidateRow = CandidateFacts & { counterpartyName: string; hidden: boolean }\n\n\n/**\n * Whom the bank and card lines of the last twelve months show paid month after month that is no account yet and no\n * recurring item - what a keeper may make an account of with one press. A line on a subject outside profit and loss\n * (a card bill, a tax, a transfer, a loan) pays no vendor, and a person (salary, expenses) is no vendor. With `hidden`,\n * the ones a keeper hid instead.\n */\nexport async function saasCandidatesOf(tx: EntityManager, domain: Domain, today: string, hidden = false): Promise<SaasCandidateRow[]> {\n const now = today.slice(0, 7)\n const from = `${shiftMonth(now, -12)}-01`\n const lines = await tx\n .getRepository(Transaction)\n .createQueryBuilder('line')\n .leftJoinAndSelect('line.account', 'subject')\n .where('line.domain = :domain', { domain: domain.id })\n .andWhere('line.category IN (:...categories)', { categories: [TransactionCategory.CONFIRMED, TransactionCategory.CARD] })\n .andWhere('line.type = :type', { type: CashFlowType.EXPENSE })\n .andWhere('line.transactionDate >= :from', { from })\n .getMany()\n const accounts = await tx.getRepository(SaasAccount).find({ where: { domain: { id: domain.id } } as any })\n const recurring = await tx.getRepository(RecurringCashItem).find({ where: { domain: { id: domain.id } } as any })\n const hiddenKeys = new Set((await tx.getRepository(SaasHiddenVendor).find({ where: { domain: { id: domain.id } } as any })).map(one => one.counterpartyId ?? `name:${one.nameKey}`))\n const skip = new Set([...accounts.map(one => one.counterpartyId), ...recurring.map(one => one.counterpartyId), ...(hidden ? [] : hiddenKeys)].filter(Boolean) as string[])\n const parties = await tx.getRepository(Counterparty).find({ where: { domain: { id: domain.id } } as any, select: ['id', 'name', 'aliases', 'kind'] })\n const named = partyNamed(parties)\n const people = new Set(parties.filter(one => one.kind === CounterpartyKind.PERSON).map(one => one.id))\n /* Whom a line paid: its counterparty, else the one its written name is (the rule a line is linked by), else the name. */\n const vendorOf = (line: Transaction) => {\n const id = line.counterpartyId ?? named(line.counterpartyName)?.id\n if (id) return people.has(id) ? null : { key: id, counterpartyId: id }\n const key = nameKey(line.counterpartyName)\n return key && !looksLikePersonName(line.counterpartyName!) ? { key: `name:${key}`, counterpartyId: null } : null\n }\n const found = candidatesOf(\n lines\n .filter(line => line.account?.profitAndLoss !== false)\n .flatMap(line => {\n const vendor = vendorOf(line)\n return vendor ? [{ ...vendor, name: line.counterpartyName, transactionDate: line.transactionDate!, amount: Number(line.amount), currency: line.currency, bankAccountId: line.bankAccountId }] : []\n }),\n skip\n ).filter(one => hiddenKeys.has(one.key) === hidden)\n return found.map(one => ({ ...one, counterpartyName: parties.find(party => party.id === one.counterpartyId)?.name ?? one.name ?? '', hidden }))\n}\n\n/**\n * Make an account of each candidate - named after the vendor, paid from where it was paid most, on the day it was paid\n * most - with one usage subscription budgeted at the monthly average, so the months to come are expected at it until\n * bills say otherwise. A vendor the lines only name is registered as a counterparty first; the lines written with its\n * name are linked to it (accounting `linkLinesByName`). One that is no candidate any more is refused.\n */\nexport async function createSaasAccountsFromCandidates(tx: EntityManager, domain: Domain, user: any, keys: string[], today: string): Promise<SaasAccount[]> {\n const candidates = await saasCandidatesOf(tx, domain, today)\n const made: SaasAccount[] = []\n for (const key of [...new Set(keys)]) {\n const one = candidates.find(candidate => candidate.key === key)\n if (!one) throw new Refusal('saas-candidate-not-found', {}, 'It is no candidate any more - reload and try again')\n const counterpartyId = one.counterpartyId ?? (await saveCounterparties(tx, domain, user, [{ cuFlag: '+', name: one.counterpartyName, kind: CounterpartyKind.COMPANY }]))[0].id\n /* Its lines written with its name and not linked yet are its months. */\n await linkLinesByName(tx, domain, user, [counterpartyId])\n const [account] = await saveSaasAccounts(tx, domain, user, [\n { cuFlag: '+', name: one.counterpartyName, counterpartyId, paymentAccountId: one.paymentAccountId, currency: one.currency, billingDay: one.billingDay, status: SaasAccountStatus.ACTIVE }\n ])\n await saveSaasSubscriptions(tx, domain, user, 'all', account.id, [\n { cuFlag: '+', name: one.counterpartyName, billing: SaasBilling.USAGE, budget: one.average, startOn: one.firstDate, status: SaasSubscriptionStatus.ACTIVE }\n ])\n made.push(account)\n }\n return made\n}\n\n/** Hide candidates - by their keys - or show them again. */\nexport async function hideSaasCandidates(tx: EntityManager, domain: Domain, user: any, keys: string[], hide: boolean): Promise<boolean> {\n const repo = tx.getRepository(SaasHiddenVendor)\n const wanted = [...new Set(keys)].filter(Boolean)\n const names = wanted.filter(key => key.startsWith('name:')).map(key => key.slice(5))\n const ids = wanted.filter(key => !key.startsWith('name:'))\n const parties = ids.length ? await tx.getRepository(Counterparty).find({ where: { domain: { id: domain.id }, id: In(ids) } as any }) : []\n if (parties.length !== ids.length) throw new Refusal('saas-counterparty-not-found', {}, 'The vendor was not found - reload and try again')\n const rows = await repo.find({ where: { domain: { id: domain.id } } as any })\n const held = (row: SaasHiddenVendor) => (row.counterpartyId ? ids.includes(row.counterpartyId) : names.includes(row.nameKey!))\n if (!hide) {\n const gone = rows.filter(held)\n if (gone.length) await repo.remove(gone)\n return true\n }\n for (const party of parties) if (!rows.some(row => row.counterpartyId === party.id)) await repo.save({ domain, counterparty: party, creator: user })\n for (const key of names) if (!rows.some(row => !row.counterpartyId && row.nameKey === key)) await repo.save({ domain, nameKey: key, creator: user })\n return true\n}\n"]}
|
|
@@ -51,6 +51,16 @@ tslib_1.__decorate([
|
|
|
51
51
|
(0, type_graphql_1.Field)(type => saas_rules_1.SaasBilling, { description: 'How it is paid for' }),
|
|
52
52
|
tslib_1.__metadata("design:type", String)
|
|
53
53
|
], SaasSubscription.prototype, "billing", void 0);
|
|
54
|
+
tslib_1.__decorate([
|
|
55
|
+
(0, typeorm_1.Column)({ nullable: true }),
|
|
56
|
+
(0, type_graphql_1.Field)({ nullable: true, description: "The vendor's id for the plan - a Microsoft 365 SKU id; set by a sync, which keeps its seats and quantity" }),
|
|
57
|
+
tslib_1.__metadata("design:type", String)
|
|
58
|
+
], SaasSubscription.prototype, "vendorKey", void 0);
|
|
59
|
+
tslib_1.__decorate([
|
|
60
|
+
(0, typeorm_1.Column)({ default: false }),
|
|
61
|
+
(0, type_graphql_1.Field)({ description: 'A trial the vendor hands out - it ends on its renewal day unless bought; set by a sync' }),
|
|
62
|
+
tslib_1.__metadata("design:type", Boolean)
|
|
63
|
+
], SaasSubscription.prototype, "trial", void 0);
|
|
54
64
|
tslib_1.__decorate([
|
|
55
65
|
(0, typeorm_1.Column)({ type: 'float', nullable: true }),
|
|
56
66
|
(0, type_graphql_1.Field)(type => type_graphql_1.Float, { nullable: true, description: 'Seats or units - for a seat plan' }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"saas-subscription.js","sourceRoot":"","sources":["../../server/service/saas-subscription.ts"],"names":[],"mappings":"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","sourcesContent":["import { Asset } from '@things-factory/asset'\nimport { User } from '@things-factory/auth-base'\nimport { Department } from '@things-factory/organization'\nimport { Domain, moneyColumn } from '@things-factory/shell'\nimport { Field, Float, ID, Int, ObjectType } from 'type-graphql'\nimport { Column, CreateDateColumn, DeleteDateColumn, Entity, Index, ManyToOne, PrimaryGeneratedColumn, RelationId, UpdateDateColumn } from 'typeorm'\n\nimport { SaasAccount } from './saas-account'\nimport { SaasBilling, SaasSubscriptionStatus } from './saas-rules'\n\n/**\n * One thing under an account the domain decides on and can cancel (ADR-0177 decisions 1, 3): a plan with seats, a fixed\n * fee, metered usage with a monthly budget, a commitment for a term, or a license owned - which points at the asset\n * register and carries no amount. It is billed in the account's currency, every so many months from the month it started.\n */\n@Entity()\n@Index('ix_saas_subscription_0', (sub: SaasSubscription) => [sub.domain, sub.account])\n@ObjectType({ description: 'Entity for SaasSubscription — a plan, fee, usage, commitment or owned license under an account' })\nexport class SaasSubscription {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier of the subscription' })\n readonly id: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { nullable: true, description: 'The domain the subscription belongs to' })\n domain?: Domain\n\n @RelationId((sub: SaasSubscription) => sub.domain)\n domainId?: string\n\n @ManyToOne(type => SaasAccount, { onDelete: 'CASCADE' })\n @Field(type => SaasAccount, { nullable: true, description: 'The account it is under' })\n account?: SaasAccount\n\n @RelationId((sub: SaasSubscription) => sub.account)\n accountId?: string\n\n @Column()\n @Field({ description: 'The product and plan - Microsoft 365 Business Standard, AWS usage, Savings Plan 1 year, example.com' })\n name: string\n\n @Column({ default: SaasBilling.FIXED })\n @Field(type => SaasBilling, { description: 'How it is paid for' })\n billing: SaasBilling\n\n @Column({ type: 'float', nullable: true })\n @Field(type => Float, { nullable: true, description: 'Seats or units - for a seat plan' })\n quantity?: number\n\n @Column({ ...moneyColumn(), nullable: true })\n @Field(type => Float, { nullable: true, description: 'The price of one seat for one billing - for a seat plan' })\n unitPrice?: number\n\n @Column({ ...moneyColumn(), nullable: true })\n @Field(type => Float, { nullable: true, description: 'What one billing costs - for a fixed fee or a commitment' })\n amount?: number\n\n @Column({ ...moneyColumn(), nullable: true })\n @Field(type => Float, { nullable: true, description: 'What a month of metered usage may cost - told when a bill is over it' })\n budget?: number\n\n @Column({ type: 'int', default: 1 })\n @Field(type => Int, { description: 'Billed every so many months - 1 monthly, 12 yearly' })\n everyMonths: number\n\n @Column()\n @Field({ description: 'The day it started - YYYY-MM-DD; billings count from its month' })\n startOn: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The day it renews or its term ends - YYYY-MM-DD; a domain’s expiry' })\n renewalOn?: string\n\n @Column({ default: true })\n @Field({ description: 'Whether the vendor renews it unless cancelled' })\n autoRenew: boolean\n\n @Column({ type: 'int', nullable: true })\n @Field(type => Int, { nullable: true, description: 'How many days before renewal it must be cancelled - told from then' })\n noticeDays?: number\n\n @ManyToOne(type => Department, { nullable: true, onDelete: 'SET NULL' })\n @Field(type => Department, { nullable: true, description: 'The department it is for - its cost when no seat says whose' })\n department?: Department\n\n @RelationId((sub: SaasSubscription) => sub.department)\n departmentId?: string\n\n @ManyToOne(type => Asset, { nullable: true, onDelete: 'SET NULL' })\n @Field(type => Asset, { nullable: true, description: 'For a license owned: the asset of the register that carries its cost' })\n asset?: Asset\n\n @RelationId((sub: SaasSubscription) => sub.asset)\n assetId?: string\n\n @Column({ default: SaasSubscriptionStatus.ACTIVE })\n @Field(type => SaasSubscriptionStatus, { description: 'In use, not to be renewed, or ended' })\n status: SaasSubscriptionStatus\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The day it ended - YYYY-MM-DD' })\n endedOn?: string\n\n @Column({ type: 'text', nullable: true })\n @Field({ nullable: true, description: 'Notes' })\n description?: string\n\n @Field(type => Int, { nullable: true, description: 'How many seats are held today - filled by the list query' })\n seatsHeld?: number\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'When the subscription was registered' })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true, description: 'When the subscription last changed' })\n updatedAt?: Date\n\n @DeleteDateColumn()\n @Field({ nullable: true, description: 'When the subscription was deleted' })\n deletedAt?: Date\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'Who registered it' })\n creator?: User\n\n @RelationId((sub: SaasSubscription) => sub.creator)\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'Who last changed it' })\n updater?: User\n\n @RelationId((sub: SaasSubscription) => sub.updater)\n updaterId?: string\n}\n"]}
|
|
1
|
+
{"version":3,"file":"saas-subscription.js","sourceRoot":"","sources":["../../server/service/saas-subscription.ts"],"names":[],"mappings":"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","sourcesContent":["import { Asset } from '@things-factory/asset'\nimport { User } from '@things-factory/auth-base'\nimport { Department } from '@things-factory/organization'\nimport { Domain, moneyColumn } from '@things-factory/shell'\nimport { Field, Float, ID, Int, ObjectType } from 'type-graphql'\nimport { Column, CreateDateColumn, DeleteDateColumn, Entity, Index, ManyToOne, PrimaryGeneratedColumn, RelationId, UpdateDateColumn } from 'typeorm'\n\nimport { SaasAccount } from './saas-account'\nimport { SaasBilling, SaasSubscriptionStatus } from './saas-rules'\n\n/**\n * One thing under an account the domain decides on and can cancel (ADR-0177 decisions 1, 3): a plan with seats, a fixed\n * fee, metered usage with a monthly budget, a commitment for a term, or a license owned - which points at the asset\n * register and carries no amount. It is billed in the account's currency, every so many months from the month it started.\n */\n@Entity()\n@Index('ix_saas_subscription_0', (sub: SaasSubscription) => [sub.domain, sub.account])\n@ObjectType({ description: 'Entity for SaasSubscription — a plan, fee, usage, commitment or owned license under an account' })\nexport class SaasSubscription {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier of the subscription' })\n readonly id: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { nullable: true, description: 'The domain the subscription belongs to' })\n domain?: Domain\n\n @RelationId((sub: SaasSubscription) => sub.domain)\n domainId?: string\n\n @ManyToOne(type => SaasAccount, { onDelete: 'CASCADE' })\n @Field(type => SaasAccount, { nullable: true, description: 'The account it is under' })\n account?: SaasAccount\n\n @RelationId((sub: SaasSubscription) => sub.account)\n accountId?: string\n\n @Column()\n @Field({ description: 'The product and plan - Microsoft 365 Business Standard, AWS usage, Savings Plan 1 year, example.com' })\n name: string\n\n @Column({ default: SaasBilling.FIXED })\n @Field(type => SaasBilling, { description: 'How it is paid for' })\n billing: SaasBilling\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: \"The vendor's id for the plan - a Microsoft 365 SKU id; set by a sync, which keeps its seats and quantity\" })\n vendorKey?: string\n\n @Column({ default: false })\n @Field({ description: 'A trial the vendor hands out - it ends on its renewal day unless bought; set by a sync' })\n trial: boolean\n\n @Column({ type: 'float', nullable: true })\n @Field(type => Float, { nullable: true, description: 'Seats or units - for a seat plan' })\n quantity?: number\n\n @Column({ ...moneyColumn(), nullable: true })\n @Field(type => Float, { nullable: true, description: 'The price of one seat for one billing - for a seat plan' })\n unitPrice?: number\n\n @Column({ ...moneyColumn(), nullable: true })\n @Field(type => Float, { nullable: true, description: 'What one billing costs - for a fixed fee or a commitment' })\n amount?: number\n\n @Column({ ...moneyColumn(), nullable: true })\n @Field(type => Float, { nullable: true, description: 'What a month of metered usage may cost - told when a bill is over it' })\n budget?: number\n\n @Column({ type: 'int', default: 1 })\n @Field(type => Int, { description: 'Billed every so many months - 1 monthly, 12 yearly' })\n everyMonths: number\n\n @Column()\n @Field({ description: 'The day it started - YYYY-MM-DD; billings count from its month' })\n startOn: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The day it renews or its term ends - YYYY-MM-DD; a domain’s expiry' })\n renewalOn?: string\n\n @Column({ default: true })\n @Field({ description: 'Whether the vendor renews it unless cancelled' })\n autoRenew: boolean\n\n @Column({ type: 'int', nullable: true })\n @Field(type => Int, { nullable: true, description: 'How many days before renewal it must be cancelled - told from then' })\n noticeDays?: number\n\n @ManyToOne(type => Department, { nullable: true, onDelete: 'SET NULL' })\n @Field(type => Department, { nullable: true, description: 'The department it is for - its cost when no seat says whose' })\n department?: Department\n\n @RelationId((sub: SaasSubscription) => sub.department)\n departmentId?: string\n\n @ManyToOne(type => Asset, { nullable: true, onDelete: 'SET NULL' })\n @Field(type => Asset, { nullable: true, description: 'For a license owned: the asset of the register that carries its cost' })\n asset?: Asset\n\n @RelationId((sub: SaasSubscription) => sub.asset)\n assetId?: string\n\n @Column({ default: SaasSubscriptionStatus.ACTIVE })\n @Field(type => SaasSubscriptionStatus, { description: 'In use, not to be renewed, or ended' })\n status: SaasSubscriptionStatus\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The day it ended - YYYY-MM-DD' })\n endedOn?: string\n\n @Column({ type: 'text', nullable: true })\n @Field({ nullable: true, description: 'Notes' })\n description?: string\n\n @Field(type => Int, { nullable: true, description: 'How many seats are held today - filled by the list query' })\n seatsHeld?: number\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'When the subscription was registered' })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true, description: 'When the subscription last changed' })\n updatedAt?: Date\n\n @DeleteDateColumn()\n @Field({ nullable: true, description: 'When the subscription was deleted' })\n deletedAt?: Date\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'Who registered it' })\n creator?: User\n\n @RelationId((sub: SaasSubscription) => sub.creator)\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'Who last changed it' })\n updater?: User\n\n @RelationId((sub: SaasSubscription) => sub.updater)\n updaterId?: string\n}\n"]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Domain } from '@things-factory/shell';
|
|
2
|
+
import { EntityManager } from 'typeorm';
|
|
3
|
+
export interface LicenseFacts {
|
|
4
|
+
tenantId?: string | null;
|
|
5
|
+
domains?: string[] | null;
|
|
6
|
+
skus: {
|
|
7
|
+
skuId: string;
|
|
8
|
+
name: string;
|
|
9
|
+
enabled: number;
|
|
10
|
+
consumed: number;
|
|
11
|
+
renewalOn?: string | null;
|
|
12
|
+
trial?: boolean | null;
|
|
13
|
+
}[];
|
|
14
|
+
users: {
|
|
15
|
+
login: string;
|
|
16
|
+
mail?: string | null;
|
|
17
|
+
name?: string | null;
|
|
18
|
+
enabled?: boolean | null;
|
|
19
|
+
skuIds: string[];
|
|
20
|
+
}[];
|
|
21
|
+
}
|
|
22
|
+
export interface LicenseSyncResult {
|
|
23
|
+
accountId: string;
|
|
24
|
+
accountName: string;
|
|
25
|
+
subscriptions: number;
|
|
26
|
+
created: number;
|
|
27
|
+
opened: number;
|
|
28
|
+
closed: number;
|
|
29
|
+
/** Open seats held as names that took their employee. */
|
|
30
|
+
linked: number;
|
|
31
|
+
/** Logins no employee's mail matched - held as names. */
|
|
32
|
+
unmatched: string[];
|
|
33
|
+
}
|
|
34
|
+
export declare function syncSaasLicenses(tx: EntityManager, domain: Domain, user: any, facts: LicenseFacts, today: string): Promise<LicenseSyncResult>;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.syncSaasLicenses = syncSaasLicenses;
|
|
4
|
+
const organization_1 = require("@things-factory/organization");
|
|
5
|
+
const shell_1 = require("@things-factory/shell");
|
|
6
|
+
const saas_account_1 = require("./saas-account");
|
|
7
|
+
const saas_rules_1 = require("./saas-rules");
|
|
8
|
+
const saas_seat_1 = require("./saas-seat");
|
|
9
|
+
const saas_service_1 = require("./saas-service");
|
|
10
|
+
const saas_subscription_1 = require("./saas-subscription");
|
|
11
|
+
const lower = (value) => String(value ?? '').trim().toLowerCase();
|
|
12
|
+
/** The account the tenant is: the one whose identifier is the tenant id or a domain its users sign in with. */
|
|
13
|
+
async function accountOfTenant(tx, domain, facts) {
|
|
14
|
+
const names = new Set([facts.tenantId, ...(facts.domains ?? [])].map(lower).filter(Boolean));
|
|
15
|
+
const accounts = (await tx.getRepository(saas_account_1.SaasAccount).find({ where: { domain: { id: domain.id }, status: saas_rules_1.SaasAccountStatus.ACTIVE } })).filter(one => names.has(lower(one.identifier)));
|
|
16
|
+
if (!accounts.length)
|
|
17
|
+
throw new shell_1.Refusal('saas-sync-account-not-found', { names: [...names].join(', ') }, 'No account has the tenant id or one of its domains as its identifier');
|
|
18
|
+
if (accounts.length > 1)
|
|
19
|
+
throw new shell_1.Refusal('saas-sync-account-ambiguous', { names: accounts.map(one => one.name).join(', ') }, 'Two accounts have the tenant as their identifier');
|
|
20
|
+
return accounts[0];
|
|
21
|
+
}
|
|
22
|
+
async function syncSaasLicenses(tx, domain, user, facts, today) {
|
|
23
|
+
const account = await accountOfTenant(tx, domain, facts);
|
|
24
|
+
if (account.parentId)
|
|
25
|
+
throw new shell_1.Refusal('saas-subscription-on-sub-account', {}, 'An account under another is billed by its parent - subscribe there');
|
|
26
|
+
/* Whose mail a login is: an employee's - the mails on their contact card (organization keeps the work mail there), and their user account's. */
|
|
27
|
+
const employees = await tx.getRepository(organization_1.Employee).find({ where: { domain: { id: domain.id } }, relations: ['user', 'contact'] });
|
|
28
|
+
const byMail = new Map();
|
|
29
|
+
for (const one of employees) {
|
|
30
|
+
const mails = [one.user?.email, ...(one.contact?.items ?? []).filter(item => item?.type === 'email').map(item => item.value)];
|
|
31
|
+
for (const mail of mails)
|
|
32
|
+
if (lower(mail))
|
|
33
|
+
byMail.set(lower(mail), one);
|
|
34
|
+
}
|
|
35
|
+
const employeeOf = (holder) => byMail.get(lower(holder.mail)) ?? byMail.get(lower(holder.login));
|
|
36
|
+
const result = { accountId: account.id, accountName: account.name, subscriptions: 0, created: 0, opened: 0, closed: 0, linked: 0, unmatched: [] };
|
|
37
|
+
const subs = await tx.getRepository(saas_subscription_1.SaasSubscription).find({ where: { domain: { id: domain.id }, account: { id: account.id } } });
|
|
38
|
+
for (const sku of facts.skus) {
|
|
39
|
+
let sub = subs.find(one => one.vendorKey === sku.skuId);
|
|
40
|
+
const holders = facts.users.filter(one => one.skuIds.includes(sku.skuId));
|
|
41
|
+
if (!sub) {
|
|
42
|
+
if (!sku.consumed && !holders.length)
|
|
43
|
+
continue;
|
|
44
|
+
[sub] = await (0, saas_service_1.saveSaasSubscriptions)(tx, domain, user, 'all', account.id, [
|
|
45
|
+
{
|
|
46
|
+
cuFlag: '+',
|
|
47
|
+
name: sku.name,
|
|
48
|
+
billing: saas_rules_1.SaasBilling.SEAT,
|
|
49
|
+
vendorKey: sku.skuId,
|
|
50
|
+
quantity: Math.max(sku.enabled, holders.length, 1),
|
|
51
|
+
startOn: today,
|
|
52
|
+
status: saas_rules_1.SaasSubscriptionStatus.ACTIVE,
|
|
53
|
+
...(sku.renewalOn ? { renewalOn: sku.renewalOn } : {}),
|
|
54
|
+
trial: !!sku.trial
|
|
55
|
+
}
|
|
56
|
+
]);
|
|
57
|
+
result.created++;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
/* The quantity, the renewal day and being a trial are the tenant's facts; the rest stays the person's. */
|
|
61
|
+
const change = {};
|
|
62
|
+
if (sku.enabled > 0 && Number(sub.quantity) !== sku.enabled)
|
|
63
|
+
change.quantity = sku.enabled;
|
|
64
|
+
if (sku.renewalOn && sub.renewalOn !== sku.renewalOn)
|
|
65
|
+
change.renewalOn = sku.renewalOn;
|
|
66
|
+
if (sku.trial !== undefined && sku.trial !== null && !!sub.trial !== !!sku.trial)
|
|
67
|
+
change.trial = !!sku.trial;
|
|
68
|
+
if (Object.keys(change).length)
|
|
69
|
+
await (0, saas_service_1.saveSaasSubscriptions)(tx, domain, user, 'all', account.id, [{ id: sub.id, cuFlag: 'M', ...change }]);
|
|
70
|
+
}
|
|
71
|
+
result.subscriptions++;
|
|
72
|
+
const seats = await tx.getRepository(saas_seat_1.SaasSeat).find({ where: { domain: { id: domain.id }, subscription: { id: sub.id } } });
|
|
73
|
+
const synced = seats.filter(one => one.login);
|
|
74
|
+
/* The first sync does not know since when a seat is held. */
|
|
75
|
+
const since = synced.length ? today : null;
|
|
76
|
+
const open = synced.filter(one => !one.untilOn || one.untilOn > today);
|
|
77
|
+
const now = new Set(holders.map(one => lower(one.login)));
|
|
78
|
+
const patches = [];
|
|
79
|
+
for (const holder of holders) {
|
|
80
|
+
const employee = employeeOf(holder);
|
|
81
|
+
if (!employee)
|
|
82
|
+
result.unmatched.push(holder.login);
|
|
83
|
+
const held = open.find(one => lower(one.login) === lower(holder.login));
|
|
84
|
+
if (held) {
|
|
85
|
+
/* A seat held as a name takes its employee once their mail is known - every sync looks again. */
|
|
86
|
+
if (employee && held.employeeId !== employee.id) {
|
|
87
|
+
patches.push({ id: held.id, cuFlag: 'M', employeeId: employee.id, holder: null });
|
|
88
|
+
result.linked++;
|
|
89
|
+
}
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
patches.push({ cuFlag: '+', login: holder.login, employeeId: employee?.id ?? null, holder: employee ? null : holder.name || holder.login, fromOn: since });
|
|
93
|
+
result.opened++;
|
|
94
|
+
}
|
|
95
|
+
for (const seat of open)
|
|
96
|
+
if (!now.has(lower(seat.login))) {
|
|
97
|
+
patches.push({ id: seat.id, cuFlag: 'M', untilOn: seat.fromOn && seat.fromOn > today ? seat.fromOn : today });
|
|
98
|
+
result.closed++;
|
|
99
|
+
}
|
|
100
|
+
if (patches.length)
|
|
101
|
+
await (0, saas_service_1.saveSaasSeats)(tx, domain, user, 'all', sub.id, patches);
|
|
102
|
+
}
|
|
103
|
+
result.unmatched = [...new Set(result.unmatched)];
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=saas-sync.js.map
|