@things-factory/saas 10.1.236 → 10.1.239

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist-client/components/saas-candidates.d.ts +33 -0
  2. package/dist-client/components/saas-candidates.js +157 -0
  3. package/dist-client/components/saas-candidates.js.map +1 -0
  4. package/dist-client/index.d.ts +1 -0
  5. package/dist-client/index.js +1 -0
  6. package/dist-client/index.js.map +1 -1
  7. package/dist-client/pages/saas-account-list.js +3 -0
  8. package/dist-client/pages/saas-account-list.js.map +1 -1
  9. package/dist-client/pages/saas-account-page.js +7 -2
  10. package/dist-client/pages/saas-account-page.js.map +1 -1
  11. package/dist-client/tsconfig.tsbuildinfo +1 -1
  12. package/dist-server/role-tasks.js +3 -1
  13. package/dist-server/role-tasks.js.map +1 -1
  14. package/dist-server/service/checks.d.ts +4 -1
  15. package/dist-server/service/checks.js +5 -2
  16. package/dist-server/service/checks.js.map +1 -1
  17. package/dist-server/service/index.d.ts +4 -1
  18. package/dist-server/service/index.js +5 -1
  19. package/dist-server/service/index.js.map +1 -1
  20. package/dist-server/service/saas-bill.d.ts +1 -0
  21. package/dist-server/service/saas-bill.js +5 -0
  22. package/dist-server/service/saas-bill.js.map +1 -1
  23. package/dist-server/service/saas-hidden-vendor.d.ts +19 -0
  24. package/dist-server/service/saas-hidden-vendor.js +53 -0
  25. package/dist-server/service/saas-hidden-vendor.js.map +1 -0
  26. package/dist-server/service/saas-mutation.d.ts +8 -1
  27. package/dist-server/service/saas-mutation.js +69 -0
  28. package/dist-server/service/saas-mutation.js.map +1 -1
  29. package/dist-server/service/saas-query.d.ts +2 -1
  30. package/dist-server/service/saas-query.js +16 -0
  31. package/dist-server/service/saas-query.js.map +1 -1
  32. package/dist-server/service/saas-rules.d.ts +41 -0
  33. package/dist-server/service/saas-rules.js +49 -1
  34. package/dist-server/service/saas-rules.js.map +1 -1
  35. package/dist-server/service/saas-seat.d.ts +1 -0
  36. package/dist-server/service/saas-seat.js +5 -0
  37. package/dist-server/service/saas-seat.js.map +1 -1
  38. package/dist-server/service/saas-service.d.ts +30 -7
  39. package/dist-server/service/saas-service.js +136 -17
  40. package/dist-server/service/saas-service.js.map +1 -1
  41. package/dist-server/service/saas-subscription.d.ts +2 -0
  42. package/dist-server/service/saas-subscription.js +10 -0
  43. package/dist-server/service/saas-subscription.js.map +1 -1
  44. package/dist-server/service/saas-sync.d.ts +69 -0
  45. package/dist-server/service/saas-sync.js +166 -0
  46. package/dist-server/service/saas-sync.js.map +1 -0
  47. package/dist-server/service/saas-type.d.ts +69 -0
  48. package/dist-server/service/saas-type.js +257 -1
  49. package/dist-server/service/saas-type.js.map +1 -1
  50. package/dist-server/tsconfig.tsbuildinfo +1 -1
  51. package/package.json +4 -4
  52. package/translations/en.json +24 -0
  53. package/translations/es.json +24 -0
  54. package/translations/ja.json +24 -0
  55. package/translations/ko.json +24 -0
  56. package/translations/ms.json +24 -0
  57. package/translations/zh.json +24 -0
@@ -11,6 +11,8 @@ exports.ROLE_TASKS = void 0;
11
11
  exports.ROLE_TASKS = [
12
12
  { id: 'saas.reading', grants: [{ category: 'saas', axes: ['query'] }, { category: 'saas-self', axes: ['query'] }] },
13
13
  { id: 'saas.keeping', grants: [{ category: 'saas', axes: ['query', 'mutation'] }, { category: 'saas-self', axes: ['query', 'mutation'] }] },
14
- { id: 'saas.administering', grants: [{ category: 'saas-self', axes: ['query', 'mutation'] }] }
14
+ { id: 'saas.administering', grants: [{ category: 'saas-self', axes: ['query', 'mutation'] }] },
15
+ /* Seats and quantities as a vendor's tenant says - for whoever runs the scenario that reads it (개정 2); no money. */
16
+ { id: 'saas.syncing', grants: [{ category: 'saas-sync', axes: ['mutation'] }] }
15
17
  ];
16
18
  //# sourceMappingURL=role-tasks.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"role-tasks.js","sourceRoot":"","sources":["../server/role-tasks.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAIU,QAAA,UAAU,GAAe;IACpC,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE;IACnH,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,CAAC,EAAE;IAC3I,EAAE,EAAE,EAAE,oBAAoB,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,CAAC,EAAE;CAC/F,CAAA","sourcesContent":["/*\n * The work this module names, for the seats applications build (ADR-0139 decision 11, ADR-0177 decision 8).\n *\n * `saas.administering` is for every seat: what it opens is only the accounts the signed-in person is named an admin of\n * (the service scopes it). Data only - `server/index.ts` registers it - so an application's tests read it without\n * starting the framework.\n */\n\nimport type { RoleTask } from '@things-factory/auth-base'\n\nexport const ROLE_TASKS: RoleTask[] = [\n { id: 'saas.reading', grants: [{ category: 'saas', axes: ['query'] }, { category: 'saas-self', axes: ['query'] }] },\n { id: 'saas.keeping', grants: [{ category: 'saas', axes: ['query', 'mutation'] }, { category: 'saas-self', axes: ['query', 'mutation'] }] },\n { id: 'saas.administering', grants: [{ category: 'saas-self', axes: ['query', 'mutation'] }] }\n]\n"]}
1
+ {"version":3,"file":"role-tasks.js","sourceRoot":"","sources":["../server/role-tasks.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAIU,QAAA,UAAU,GAAe;IACpC,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE;IACnH,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,CAAC,EAAE;IAC3I,EAAE,EAAE,EAAE,oBAAoB,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,CAAC,EAAE;IAC9F,oHAAoH;IACpH,EAAE,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE;CAChF,CAAA","sourcesContent":["/*\n * The work this module names, for the seats applications build (ADR-0139 decision 11, ADR-0177 decision 8).\n *\n * `saas.administering` is for every seat: what it opens is only the accounts the signed-in person is named an admin of\n * (the service scopes it). Data only - `server/index.ts` registers it - so an application's tests read it without\n * starting the framework.\n */\n\nimport type { RoleTask } from '@things-factory/auth-base'\n\nexport const ROLE_TASKS: RoleTask[] = [\n { id: 'saas.reading', grants: [{ category: 'saas', axes: ['query'] }, { category: 'saas-self', axes: ['query'] }] },\n { id: 'saas.keeping', grants: [{ category: 'saas', axes: ['query', 'mutation'] }, { category: 'saas-self', axes: ['query', 'mutation'] }] },\n { id: 'saas.administering', grants: [{ category: 'saas-self', axes: ['query', 'mutation'] }] },\n /* Seats and quantities as a vendor's tenant says - for whoever runs the scenario that reads it (개정 2); no money. */\n { id: 'saas.syncing', grants: [{ category: 'saas-sync', axes: ['mutation'] }] }\n]\n"]}
@@ -16,7 +16,10 @@ export declare function saasSeatsOfLeavers(tx: EntityManager, domain: Domain, to
16
16
  }[]>;
17
17
  /** Accounts in use with nobody left to administer them - no admin named, or every admin retired. */
18
18
  export declare function saasAccountsWithoutAdmin(tx: EntityManager, domain: Domain, today: string): Promise<SaasAccount[]>;
19
- /** Seat plans in use whose seats held today are not as many as they are billed for. */
19
+ /**
20
+ * Seat plans in use whose seats held today are not as many as they are billed for. A plan with no price is left out - a
21
+ * free or trial plan a tenant hands out (1,000,000 Power BI Free) costs nothing unused (ADR-0177 개정 2, the user 10-31).
22
+ */
20
23
  export declare function saasSeatCountsDiffer(tx: EntityManager, domain: Domain, today: string): Promise<{
21
24
  subscription: SaasSubscription;
22
25
  account: SaasAccount;
@@ -55,10 +55,13 @@ async function saasAccountsWithoutAdmin(tx, domain, today) {
55
55
  const retired = await retiredOf(tx, domain, [...new Set(accounts.flatMap(one => (one.admins ?? []).map(admin => admin.id)))], today);
56
56
  return accounts.filter(account => !(account.admins ?? []).some(admin => !retired.has(admin.id)));
57
57
  }
58
- /** Seat plans in use whose seats held today are not as many as they are billed for. */
58
+ /**
59
+ * Seat plans in use whose seats held today are not as many as they are billed for. A plan with no price is left out - a
60
+ * free or trial plan a tenant hands out (1,000,000 Power BI Free) costs nothing unused (ADR-0177 개정 2, the user 10-31).
61
+ */
59
62
  async function saasSeatCountsDiffer(tx, domain, today) {
60
63
  const { accounts, subs } = await inUse(tx, domain);
61
- const plans = subs.filter(one => one.billing === saas_rules_1.SaasBilling.SEAT && one.startOn <= today);
64
+ const plans = subs.filter(one => one.billing === saas_rules_1.SaasBilling.SEAT && one.startOn <= today && one.unitPrice !== null && one.unitPrice !== undefined);
62
65
  if (!plans.length)
63
66
  return [];
64
67
  const seats = await tx.getRepository(saas_seat_1.SaasSeat).find({ where: { domain: { id: domain.id }, subscription: { id: (0, typeorm_1.In)(plans.map(one => one.id)) } } });
@@ -1 +1 @@
1
- {"version":3,"file":"checks.js","sourceRoot":"","sources":["../../server/service/checks.ts"],"names":[],"mappings":"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","sourcesContent":["import { Employee } from '@things-factory/organization'\nimport { Domain } from '@things-factory/shell'\nimport { EntityManager, In } from 'typeorm'\n\nimport { SaasAccount } from './saas-account'\nimport { SaasBill } from './saas-bill'\nimport { billedIn, renewalDue, SaasAccountStatus, SaasBilling, SaasSubscriptionStatus, seatHeld, shiftMonth } from './saas-rules'\nimport { SaasSeat } from './saas-seat'\nimport { SaasSubscription } from './saas-subscription'\n\n/*\n * The subscriptions' part of an application's management check (ADR-0177 decisions 6, 7, 9): judged here, counted there.\n * Each takes the day it judges on.\n */\n\n/** The employees who have retired by a day. */\nasync function retiredOf(tx: EntityManager, domain: Domain, ids: string[], today: string): Promise<Set<string>> {\n if (!ids.length) return new Set()\n const employees = await tx.getRepository(Employee).find({ where: { domain: { id: domain.id }, id: In(ids) } as any })\n return new Set(employees.filter(one => one.retiredOn && one.retiredOn <= today).map(one => one.id))\n}\n\nasync function inUse(tx: EntityManager, domain: Domain) {\n const accounts = await tx.getRepository(SaasAccount).find({ where: { domain: { id: domain.id }, status: SaasAccountStatus.ACTIVE } as any, relations: ['admins'] })\n const subs = accounts.length\n ? await tx.getRepository(SaasSubscription).find({ where: { domain: { id: domain.id }, account: { id: In(accounts.map(one => one.id)) }, status: In([SaasSubscriptionStatus.ACTIVE, SaasSubscriptionStatus.CANCELLING]) } as any })\n : []\n return { accounts, subs }\n}\n\n/** Subscriptions in use whose renewal is near - from their notice days before it to the day (decision 7). */\nexport async function saasRenewalsDue(tx: EntityManager, domain: Domain, today: string) {\n const { accounts, subs } = await inUse(tx, domain)\n return subs.filter(sub => renewalDue(sub, today)).map(sub => ({ subscription: sub, account: accounts.find(one => one.id === sub.accountId)! }))\n}\n\n/** Seats still held by people who have retired. */\nexport async function saasSeatsOfLeavers(tx: EntityManager, domain: Domain, today: string) {\n const { accounts, subs } = await inUse(tx, domain)\n if (!subs.length) return []\n const seats = (await tx.getRepository(SaasSeat).find({ where: { domain: { id: domain.id }, subscription: { id: In(subs.map(one => one.id)) } } as any, relations: ['employee'] })).filter(\n seat => seat.employeeId && seatHeld(seat, today)\n )\n const retired = await retiredOf(tx, domain, [...new Set(seats.map(one => one.employeeId!))], today)\n return seats\n .filter(seat => retired.has(seat.employeeId!))\n .map(seat => {\n const subscription = subs.find(one => one.id === seat.subscriptionId)!\n return { seat, subscription, account: accounts.find(one => one.id === subscription.accountId)! }\n })\n}\n\n/** Accounts in use with nobody left to administer them - no admin named, or every admin retired. */\nexport async function saasAccountsWithoutAdmin(tx: EntityManager, domain: Domain, today: string) {\n const { accounts } = await inUse(tx, domain)\n const retired = await retiredOf(tx, domain, [...new Set(accounts.flatMap(one => (one.admins ?? []).map(admin => admin.id)))], today)\n return accounts.filter(account => !(account.admins ?? []).some(admin => !retired.has(admin.id)))\n}\n\n/** Seat plans in use whose seats held today are not as many as they are billed for. */\nexport async function saasSeatCountsDiffer(tx: EntityManager, domain: Domain, today: string) {\n const { accounts, subs } = await inUse(tx, domain)\n const plans = subs.filter(one => one.billing === SaasBilling.SEAT && one.startOn <= today)\n if (!plans.length) return []\n const seats = await tx.getRepository(SaasSeat).find({ where: { domain: { id: domain.id }, subscription: { id: In(plans.map(one => one.id)) } } as any })\n return plans\n .map(sub => ({ subscription: sub, account: accounts.find(one => one.id === sub.accountId)!, held: seats.filter(seat => seat.subscriptionId === sub.id && seatHeld(seat, today)).length }))\n .filter(one => one.held !== Number(one.subscription.quantity ?? 0))\n}\n\n/**\n * Accounts in use that were to be billed last month and have no bill for it (decision 9) - the trend holds only while the\n * bills are written every month.\n */\nexport async function saasBillsMissing(tx: EntityManager, domain: Domain, today: string) {\n const { accounts, subs } = await inUse(tx, domain)\n const month = shiftMonth(today.slice(0, 7), -1)\n const [year, m] = month.split('-').map(Number)\n const due = accounts.filter(account => !account.parentId && subs.some(sub => sub.accountId === account.id && sub.billing !== SaasBilling.OWNED && billedIn(sub, year, m, account.billingDay)))\n if (!due.length) return []\n const billed = new Set(\n (await tx.getRepository(SaasBill).find({ where: { domain: { id: domain.id }, month, account: { id: In(due.map(one => one.id)) } } as any })).map(one => one.accountId)\n )\n return due.filter(one => !billed.has(one.id)).map(account => ({ account, month }))\n}\n"]}
1
+ {"version":3,"file":"checks.js","sourceRoot":"","sources":["../../server/service/checks.ts"],"names":[],"mappings":"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","sourcesContent":["import { Employee } from '@things-factory/organization'\nimport { Domain } from '@things-factory/shell'\nimport { EntityManager, In } from 'typeorm'\n\nimport { SaasAccount } from './saas-account'\nimport { SaasBill } from './saas-bill'\nimport { billedIn, renewalDue, SaasAccountStatus, SaasBilling, SaasSubscriptionStatus, seatHeld, shiftMonth } from './saas-rules'\nimport { SaasSeat } from './saas-seat'\nimport { SaasSubscription } from './saas-subscription'\n\n/*\n * The subscriptions' part of an application's management check (ADR-0177 decisions 6, 7, 9): judged here, counted there.\n * Each takes the day it judges on.\n */\n\n/** The employees who have retired by a day. */\nasync function retiredOf(tx: EntityManager, domain: Domain, ids: string[], today: string): Promise<Set<string>> {\n if (!ids.length) return new Set()\n const employees = await tx.getRepository(Employee).find({ where: { domain: { id: domain.id }, id: In(ids) } as any })\n return new Set(employees.filter(one => one.retiredOn && one.retiredOn <= today).map(one => one.id))\n}\n\nasync function inUse(tx: EntityManager, domain: Domain) {\n const accounts = await tx.getRepository(SaasAccount).find({ where: { domain: { id: domain.id }, status: SaasAccountStatus.ACTIVE } as any, relations: ['admins'] })\n const subs = accounts.length\n ? await tx.getRepository(SaasSubscription).find({ where: { domain: { id: domain.id }, account: { id: In(accounts.map(one => one.id)) }, status: In([SaasSubscriptionStatus.ACTIVE, SaasSubscriptionStatus.CANCELLING]) } as any })\n : []\n return { accounts, subs }\n}\n\n/** Subscriptions in use whose renewal is near - from their notice days before it to the day (decision 7). */\nexport async function saasRenewalsDue(tx: EntityManager, domain: Domain, today: string) {\n const { accounts, subs } = await inUse(tx, domain)\n return subs.filter(sub => renewalDue(sub, today)).map(sub => ({ subscription: sub, account: accounts.find(one => one.id === sub.accountId)! }))\n}\n\n/** Seats still held by people who have retired. */\nexport async function saasSeatsOfLeavers(tx: EntityManager, domain: Domain, today: string) {\n const { accounts, subs } = await inUse(tx, domain)\n if (!subs.length) return []\n const seats = (await tx.getRepository(SaasSeat).find({ where: { domain: { id: domain.id }, subscription: { id: In(subs.map(one => one.id)) } } as any, relations: ['employee'] })).filter(\n seat => seat.employeeId && seatHeld(seat, today)\n )\n const retired = await retiredOf(tx, domain, [...new Set(seats.map(one => one.employeeId!))], today)\n return seats\n .filter(seat => retired.has(seat.employeeId!))\n .map(seat => {\n const subscription = subs.find(one => one.id === seat.subscriptionId)!\n return { seat, subscription, account: accounts.find(one => one.id === subscription.accountId)! }\n })\n}\n\n/** Accounts in use with nobody left to administer them - no admin named, or every admin retired. */\nexport async function saasAccountsWithoutAdmin(tx: EntityManager, domain: Domain, today: string) {\n const { accounts } = await inUse(tx, domain)\n const retired = await retiredOf(tx, domain, [...new Set(accounts.flatMap(one => (one.admins ?? []).map(admin => admin.id)))], today)\n return accounts.filter(account => !(account.admins ?? []).some(admin => !retired.has(admin.id)))\n}\n\n/**\n * Seat plans in use whose seats held today are not as many as they are billed for. A plan with no price is left out - a\n * free or trial plan a tenant hands out (1,000,000 Power BI Free) costs nothing unused (ADR-0177 개정 2, the user 10-31).\n */\nexport async function saasSeatCountsDiffer(tx: EntityManager, domain: Domain, today: string) {\n const { accounts, subs } = await inUse(tx, domain)\n const plans = subs.filter(one => one.billing === SaasBilling.SEAT && one.startOn <= today && one.unitPrice !== null && one.unitPrice !== undefined)\n if (!plans.length) return []\n const seats = await tx.getRepository(SaasSeat).find({ where: { domain: { id: domain.id }, subscription: { id: In(plans.map(one => one.id)) } } as any })\n return plans\n .map(sub => ({ subscription: sub, account: accounts.find(one => one.id === sub.accountId)!, held: seats.filter(seat => seat.subscriptionId === sub.id && seatHeld(seat, today)).length }))\n .filter(one => one.held !== Number(one.subscription.quantity ?? 0))\n}\n\n/**\n * Accounts in use that were to be billed last month and have no bill for it (decision 9) - the trend holds only while the\n * bills are written every month.\n */\nexport async function saasBillsMissing(tx: EntityManager, domain: Domain, today: string) {\n const { accounts, subs } = await inUse(tx, domain)\n const month = shiftMonth(today.slice(0, 7), -1)\n const [year, m] = month.split('-').map(Number)\n const due = accounts.filter(account => !account.parentId && subs.some(sub => sub.accountId === account.id && sub.billing !== SaasBilling.OWNED && billedIn(sub, year, m, account.billingDay)))\n if (!due.length) return []\n const billed = new Set(\n (await tx.getRepository(SaasBill).find({ where: { domain: { id: domain.id }, month, account: { id: In(due.map(one => one.id)) } } as any })).map(one => one.accountId)\n )\n return due.filter(one => !billed.has(one.id)).map(account => ({ account, month }))\n}\n"]}
@@ -3,18 +3,21 @@ export * from './saas-account';
3
3
  export * from './saas-subscription';
4
4
  export * from './saas-seat';
5
5
  export * from './saas-bill';
6
+ export * from './saas-hidden-vendor';
6
7
  export * from './saas-type';
7
8
  export * from './saas-trend-type';
8
9
  export * from './saas-access';
9
10
  export * from './saas-service';
11
+ export * from './saas-sync';
10
12
  export * from './checks';
11
13
  import { SaasAccount } from './saas-account';
12
14
  import { SaasBill, SaasBillLine } from './saas-bill';
15
+ import { SaasHiddenVendor } from './saas-hidden-vendor';
13
16
  import { SaasMutation } from './saas-mutation';
14
17
  import { SaasAccountQuery } from './saas-query';
15
18
  import { SaasSeat } from './saas-seat';
16
19
  import { SaasSubscription } from './saas-subscription';
17
- export declare const entities: (typeof SaasAccount | typeof SaasSubscription | typeof SaasSeat | typeof SaasBill | typeof SaasBillLine)[];
20
+ export declare const entities: (typeof SaasAccount | typeof SaasSubscription | typeof SaasSeat | typeof SaasBill | typeof SaasBillLine | typeof SaasHiddenVendor)[];
18
21
  export declare const schema: {
19
22
  resolverClasses: (typeof SaasMutation | typeof SaasAccountQuery)[];
20
23
  };
@@ -8,14 +8,17 @@ tslib_1.__exportStar(require("./saas-account"), exports);
8
8
  tslib_1.__exportStar(require("./saas-subscription"), exports);
9
9
  tslib_1.__exportStar(require("./saas-seat"), exports);
10
10
  tslib_1.__exportStar(require("./saas-bill"), exports);
11
+ tslib_1.__exportStar(require("./saas-hidden-vendor"), exports);
11
12
  tslib_1.__exportStar(require("./saas-type"), exports);
12
13
  tslib_1.__exportStar(require("./saas-trend-type"), exports);
13
14
  tslib_1.__exportStar(require("./saas-access"), exports);
14
15
  tslib_1.__exportStar(require("./saas-service"), exports);
16
+ tslib_1.__exportStar(require("./saas-sync"), exports);
15
17
  tslib_1.__exportStar(require("./checks"), exports);
16
18
  /* IMPORT ENTITIES AND RESOLVERS */
17
19
  const saas_account_1 = require("./saas-account");
18
20
  const saas_bill_1 = require("./saas-bill");
21
+ const saas_hidden_vendor_1 = require("./saas-hidden-vendor");
19
22
  const saas_mutation_1 = require("./saas-mutation");
20
23
  const saas_query_1 = require("./saas-query");
21
24
  const saas_seat_1 = require("./saas-seat");
@@ -26,7 +29,8 @@ exports.entities = [
26
29
  saas_subscription_1.SaasSubscription,
27
30
  saas_seat_1.SaasSeat,
28
31
  saas_bill_1.SaasBill,
29
- saas_bill_1.SaasBillLine
32
+ saas_bill_1.SaasBillLine,
33
+ saas_hidden_vendor_1.SaasHiddenVendor
30
34
  ];
31
35
  exports.schema = {
32
36
  resolverClasses: [
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/service/index.ts"],"names":[],"mappings":";;;;AAAA,yBAAyB;AACzB,uDAA4B;AAC5B,yDAA8B;AAC9B,8DAAmC;AACnC,sDAA2B;AAC3B,sDAA2B;AAC3B,sDAA2B;AAC3B,4DAAiC;AACjC,wDAA6B;AAC7B,yDAA8B;AAC9B,mDAAwB;AAExB,mCAAmC;AACnC,iDAA4C;AAC5C,2CAAoD;AACpD,mDAA8C;AAC9C,6CAA+C;AAC/C,2CAAsC;AACtC,2DAAsD;AAEzC,QAAA,QAAQ,GAAG;IACtB,cAAc;IACd,0BAAW;IACX,oCAAgB;IAChB,oBAAQ;IACR,oBAAQ;IACR,wBAAY;CACb,CAAA;AAEY,QAAA,MAAM,GAAG;IACpB,eAAe,EAAE;QACf,sBAAsB;QACtB,6BAAgB;QAChB,4BAAY;KACb;CACF,CAAA","sourcesContent":["/* EXPORT ENTITY TYPES */\nexport * from './saas-rules'\nexport * from './saas-account'\nexport * from './saas-subscription'\nexport * from './saas-seat'\nexport * from './saas-bill'\nexport * from './saas-type'\nexport * from './saas-trend-type'\nexport * from './saas-access'\nexport * from './saas-service'\nexport * from './checks'\n\n/* IMPORT ENTITIES AND RESOLVERS */\nimport { SaasAccount } from './saas-account'\nimport { SaasBill, SaasBillLine } from './saas-bill'\nimport { SaasMutation } from './saas-mutation'\nimport { SaasAccountQuery } from './saas-query'\nimport { SaasSeat } from './saas-seat'\nimport { SaasSubscription } from './saas-subscription'\n\nexport const entities = [\n /* ENTITIES */\n SaasAccount,\n SaasSubscription,\n SaasSeat,\n SaasBill,\n SaasBillLine\n]\n\nexport const schema = {\n resolverClasses: [\n /* RESOLVER CLASSES */\n SaasAccountQuery,\n SaasMutation\n ]\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/service/index.ts"],"names":[],"mappings":";;;;AAAA,yBAAyB;AACzB,uDAA4B;AAC5B,yDAA8B;AAC9B,8DAAmC;AACnC,sDAA2B;AAC3B,sDAA2B;AAC3B,+DAAoC;AACpC,sDAA2B;AAC3B,4DAAiC;AACjC,wDAA6B;AAC7B,yDAA8B;AAC9B,sDAA2B;AAC3B,mDAAwB;AAExB,mCAAmC;AACnC,iDAA4C;AAC5C,2CAAoD;AACpD,6DAAuD;AACvD,mDAA8C;AAC9C,6CAA+C;AAC/C,2CAAsC;AACtC,2DAAsD;AAEzC,QAAA,QAAQ,GAAG;IACtB,cAAc;IACd,0BAAW;IACX,oCAAgB;IAChB,oBAAQ;IACR,oBAAQ;IACR,wBAAY;IACZ,qCAAgB;CACjB,CAAA;AAEY,QAAA,MAAM,GAAG;IACpB,eAAe,EAAE;QACf,sBAAsB;QACtB,6BAAgB;QAChB,4BAAY;KACb;CACF,CAAA","sourcesContent":["/* EXPORT ENTITY TYPES */\nexport * from './saas-rules'\nexport * from './saas-account'\nexport * from './saas-subscription'\nexport * from './saas-seat'\nexport * from './saas-bill'\nexport * from './saas-hidden-vendor'\nexport * from './saas-type'\nexport * from './saas-trend-type'\nexport * from './saas-access'\nexport * from './saas-service'\nexport * from './saas-sync'\nexport * from './checks'\n\n/* IMPORT ENTITIES AND RESOLVERS */\nimport { SaasAccount } from './saas-account'\nimport { SaasBill, SaasBillLine } from './saas-bill'\nimport { SaasHiddenVendor } from './saas-hidden-vendor'\nimport { SaasMutation } from './saas-mutation'\nimport { SaasAccountQuery } from './saas-query'\nimport { SaasSeat } from './saas-seat'\nimport { SaasSubscription } from './saas-subscription'\n\nexport const entities = [\n /* ENTITIES */\n SaasAccount,\n SaasSubscription,\n SaasSeat,\n SaasBill,\n SaasBillLine,\n SaasHiddenVendor\n]\n\nexport const schema = {\n resolverClasses: [\n /* RESOLVER CLASSES */\n SaasAccountQuery,\n SaasMutation\n ]\n}\n"]}
@@ -16,6 +16,7 @@ export declare class SaasBill {
16
16
  month: string;
17
17
  billedOn?: string;
18
18
  currency: string;
19
+ synced: boolean;
19
20
  lines?: SaasBillLine[];
20
21
  total?: number;
21
22
  description?: string;
@@ -54,6 +54,11 @@ tslib_1.__decorate([
54
54
  (0, type_graphql_1.Field)({ description: 'The currency it is in - the account’s when it was written' }),
55
55
  tslib_1.__metadata("design:type", String)
56
56
  ], SaasBill.prototype, "currency", void 0);
57
+ tslib_1.__decorate([
58
+ (0, typeorm_1.Column)({ default: false }),
59
+ (0, type_graphql_1.Field)({ description: "Written by a sync from the vendor's cost report - a later sync rewrites it; a bill a person wrote is never rewritten" }),
60
+ tslib_1.__metadata("design:type", Boolean)
61
+ ], SaasBill.prototype, "synced", void 0);
57
62
  tslib_1.__decorate([
58
63
  (0, typeorm_1.OneToMany)(type => SaasBillLine, line => line.bill),
59
64
  (0, type_graphql_1.Field)(type => [SaasBillLine], { nullable: true, description: 'One line a subscription, and lines on none - tax, credits' }),
@@ -1 +1 @@
1
- {"version":3,"file":"saas-bill.js","sourceRoot":"","sources":["../../server/service/saas-bill.ts"],"names":[],"mappings":";;;;AAAA,yDAAgD;AAChD,iDAA2D;AAC3D,+CAA2D;AAC3D,qCAA+J;AAE/J,iDAA4C;AAC5C,2DAAsD;AAEtD;;;;GAIG;AAII,IAAM,QAAQ,GAAd,MAAM,QAAQ;CAmEpB,CAAA;AAnEY,4BAAQ;AAGV;IAFR,IAAA,gCAAsB,EAAC,MAAM,CAAC;IAC9B,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAE,EAAE,EAAE,WAAW,EAAE,+BAA+B,EAAE,CAAC;;oCACjD;AAInB;IAFC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,cAAM,CAAC;IACzB,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,cAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,gCAAgC,EAAE,CAAC;sCAChF,cAAM;wCAAA;AAGf;IADC,IAAA,oBAAU,EAAC,CAAC,IAAc,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC;;0CAC3B;AAIjB;IAFC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,0BAAW,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IACvD,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,0BAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,oBAAoB,EAAE,CAAC;sCACxE,0BAAW;yCAAA;AAGrB;IADC,IAAA,oBAAU,EAAC,CAAC,IAAc,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC;;2CAC3B;AAIlB;IAFC,IAAA,gBAAM,GAAE;IACR,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,8BAA8B,EAAE,CAAC;;uCAC1C;AAIb;IAFC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1B,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,2CAA2C,EAAE,CAAC;;0CACnE;AAIjB;IAFC,IAAA,gBAAM,EAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC1B,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,2DAA2D,EAAE,CAAC;;0CACpE;AAIhB;IAFC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,YAAY,EAAE,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;IAClD,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,YAAY,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,2DAA2D,EAAE,CAAC;;uCACtG;AAGtB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,oBAAK,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,4CAA4C,EAAE,CAAC;;uCACtF;AAId;IAFC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACxC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC;;6CAC5B;AAIpB;IAFC,IAAA,0BAAgB,GAAE;IAClB,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,2BAA2B,EAAE,CAAC;sCACxD,IAAI;2CAAA;AAIhB;IAFC,IAAA,0BAAgB,GAAE;IAClB,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,4BAA4B,EAAE,CAAC;sCACzD,IAAI;2CAAA;AAIhB;IAFC,IAAA,0BAAgB,GAAE;IAClB,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,2BAA2B,EAAE,CAAC;sCACxD,IAAI;2CAAA;AAIhB;IAFC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,gBAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC3C,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,gBAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC;sCAC3D,gBAAI;yCAAA;AAGd;IADC,IAAA,oBAAU,EAAC,CAAC,IAAc,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC;;2CAC3B;AAIlB;IAFC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,gBAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC3C,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,gBAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,qBAAqB,EAAE,CAAC;sCAClE,gBAAI;yCAAA;AAGd;IADC,IAAA,oBAAU,EAAC,CAAC,IAAc,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC;;2CAC3B;mBAlEP,QAAQ;IAHpB,IAAA,gBAAM,GAAE;IACR,IAAA,eAAK,EAAC,gBAAgB,EAAE,CAAC,IAAc,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IACpF,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,8DAA8D,EAAE,CAAC;GAC/E,QAAQ,CAmEpB;AAED,8FAA8F;AAIvF,IAAM,YAAY,GAAlB,MAAM,YAAY;CAiCxB,CAAA;AAjCY,oCAAY;AAGd;IAFR,IAAA,gCAAsB,EAAC,MAAM,CAAC;IAC9B,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAE,EAAE,EAAE,WAAW,EAAE,+BAA+B,EAAE,CAAC;;wCACjD;AAInB;IAFC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,cAAM,CAAC;IACzB,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,cAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,gCAAgC,EAAE,CAAC;sCAChF,cAAM;4CAAA;AAGf;IADC,IAAA,oBAAU,EAAC,CAAC,IAAkB,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC;;8CAC/B;AAIjB;IAFC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IACxE,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,0BAA0B,EAAE,CAAC;sCAC9E,QAAQ;0CAAA;AAGf;IADC,IAAA,oBAAU,EAAC,CAAC,IAAkB,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;;4CAC/B;AAIf;IAFC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,oCAAgB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;IAC7E,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,oCAAgB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,sDAAsD,EAAE,CAAC;sCAC1G,oCAAgB;kDAAA;AAG/B;IADC,IAAA,oBAAU,EAAC,CAAC,IAAkB,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC;;oDAC/B;AAIvB;IAFC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1B,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,uDAAuD,EAAE,CAAC;;2CAClF;AAId;IAFC,IAAA,gBAAM,EAAC,IAAA,mBAAW,GAAE,CAAC;IACrB,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,oBAAK,EAAE,EAAE,WAAW,EAAE,sCAAsC,EAAE,CAAC;;4CAChE;uBAhCH,YAAY;IAHxB,IAAA,gBAAM,GAAE;IACR,IAAA,eAAK,EAAC,qBAAqB,EAAE,CAAC,IAAkB,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9E,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,oFAAoF,EAAE,CAAC;GACrG,YAAY,CAiCxB","sourcesContent":["import { User } from '@things-factory/auth-base'\nimport { Domain, moneyColumn } from '@things-factory/shell'\nimport { Field, Float, ID, ObjectType } from 'type-graphql'\nimport { Column, CreateDateColumn, DeleteDateColumn, Entity, Index, ManyToOne, OneToMany, PrimaryGeneratedColumn, RelationId, UpdateDateColumn } from 'typeorm'\n\nimport { SaasAccount } from './saas-account'\nimport { SaasSubscription } from './saas-subscription'\n\n/**\n * What an account was actually billed for a month (ADR-0177 decisions 5, 9) - one a month, in the account's currency,\n * one line a subscription and lines on none for tax and credits. Its total is the sum of its lines; the cost trend is\n * computed from these.\n */\n@Entity()\n@Index('ix_saas_bill_0', (bill: SaasBill) => [bill.domain, bill.account, bill.month])\n@ObjectType({ description: 'Entity for SaasBill — what an account was billed for a month' })\nexport class SaasBill {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier of the bill' })\n readonly id: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { nullable: true, description: 'The domain the bill belongs to' })\n domain?: Domain\n\n @RelationId((bill: SaasBill) => bill.domain)\n domainId?: string\n\n @ManyToOne(type => SaasAccount, { onDelete: 'CASCADE' })\n @Field(type => SaasAccount, { nullable: true, description: 'The account billed' })\n account?: SaasAccount\n\n @RelationId((bill: SaasBill) => bill.account)\n accountId?: string\n\n @Column()\n @Field({ description: 'The month it bills - YYYY-MM' })\n month: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The day the vendor billed it - YYYY-MM-DD' })\n billedOn?: string\n\n @Column({ default: 'KRW' })\n @Field({ description: 'The currency it is in - the account’s when it was written' })\n currency: string\n\n @OneToMany(type => SaasBillLine, line => line.bill)\n @Field(type => [SaasBillLine], { nullable: true, description: 'One line a subscription, and lines on none - tax, credits' })\n lines?: SaasBillLine[]\n\n @Field(type => Float, { nullable: true, description: 'The sum of its lines - filled by the query' })\n total?: number\n\n @Column({ type: 'text', nullable: true })\n @Field({ nullable: true, description: 'Notes' })\n description?: string\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'When the bill was written' })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true, description: 'When the bill last changed' })\n updatedAt?: Date\n\n @DeleteDateColumn()\n @Field({ nullable: true, description: 'When the bill was deleted' })\n deletedAt?: Date\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'Who wrote it' })\n creator?: User\n\n @RelationId((bill: SaasBill) => bill.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((bill: SaasBill) => bill.updater)\n updaterId?: string\n}\n\n/** One line of a bill - what one subscription cost that month, or tax and credits on none. */\n@Entity()\n@Index('ix_saas_bill_line_0', (line: SaasBillLine) => [line.domain, line.bill])\n@ObjectType({ description: 'Entity for SaasBillLine — what one subscription cost in a bill, or tax and credits' })\nexport class SaasBillLine {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier of the line' })\n readonly id: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { nullable: true, description: 'The domain the line belongs to' })\n domain?: Domain\n\n @RelationId((line: SaasBillLine) => line.domain)\n domainId?: string\n\n @ManyToOne(type => SaasBill, bill => bill.lines, { onDelete: 'CASCADE' })\n @Field(type => SaasBill, { nullable: true, description: 'The bill it is a line of' })\n bill?: SaasBill\n\n @RelationId((line: SaasBillLine) => line.bill)\n billId?: string\n\n @ManyToOne(type => SaasSubscription, { nullable: true, onDelete: 'SET NULL' })\n @Field(type => SaasSubscription, { nullable: true, description: 'The subscription it is for; none for tax and credits' })\n subscription?: SaasSubscription\n\n @RelationId((line: SaasBillLine) => line.subscription)\n subscriptionId?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'What the bill calls it - tax, a credit, a support fee' })\n label?: string\n\n @Column(moneyColumn())\n @Field(type => Float, { description: 'What it cost; a credit is below zero' })\n amount: number\n}\n"]}
1
+ {"version":3,"file":"saas-bill.js","sourceRoot":"","sources":["../../server/service/saas-bill.ts"],"names":[],"mappings":"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","sourcesContent":["import { User } from '@things-factory/auth-base'\nimport { Domain, moneyColumn } from '@things-factory/shell'\nimport { Field, Float, ID, ObjectType } from 'type-graphql'\nimport { Column, CreateDateColumn, DeleteDateColumn, Entity, Index, ManyToOne, OneToMany, PrimaryGeneratedColumn, RelationId, UpdateDateColumn } from 'typeorm'\n\nimport { SaasAccount } from './saas-account'\nimport { SaasSubscription } from './saas-subscription'\n\n/**\n * What an account was actually billed for a month (ADR-0177 decisions 5, 9) - one a month, in the account's currency,\n * one line a subscription and lines on none for tax and credits. Its total is the sum of its lines; the cost trend is\n * computed from these.\n */\n@Entity()\n@Index('ix_saas_bill_0', (bill: SaasBill) => [bill.domain, bill.account, bill.month])\n@ObjectType({ description: 'Entity for SaasBill — what an account was billed for a month' })\nexport class SaasBill {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier of the bill' })\n readonly id: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { nullable: true, description: 'The domain the bill belongs to' })\n domain?: Domain\n\n @RelationId((bill: SaasBill) => bill.domain)\n domainId?: string\n\n @ManyToOne(type => SaasAccount, { onDelete: 'CASCADE' })\n @Field(type => SaasAccount, { nullable: true, description: 'The account billed' })\n account?: SaasAccount\n\n @RelationId((bill: SaasBill) => bill.account)\n accountId?: string\n\n @Column()\n @Field({ description: 'The month it bills - YYYY-MM' })\n month: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The day the vendor billed it - YYYY-MM-DD' })\n billedOn?: string\n\n @Column({ default: 'KRW' })\n @Field({ description: 'The currency it is in - the account’s when it was written' })\n currency: string\n\n @Column({ default: false })\n @Field({ description: \"Written by a sync from the vendor's cost report - a later sync rewrites it; a bill a person wrote is never rewritten\" })\n synced: boolean\n\n @OneToMany(type => SaasBillLine, line => line.bill)\n @Field(type => [SaasBillLine], { nullable: true, description: 'One line a subscription, and lines on none - tax, credits' })\n lines?: SaasBillLine[]\n\n @Field(type => Float, { nullable: true, description: 'The sum of its lines - filled by the query' })\n total?: number\n\n @Column({ type: 'text', nullable: true })\n @Field({ nullable: true, description: 'Notes' })\n description?: string\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'When the bill was written' })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true, description: 'When the bill last changed' })\n updatedAt?: Date\n\n @DeleteDateColumn()\n @Field({ nullable: true, description: 'When the bill was deleted' })\n deletedAt?: Date\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'Who wrote it' })\n creator?: User\n\n @RelationId((bill: SaasBill) => bill.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((bill: SaasBill) => bill.updater)\n updaterId?: string\n}\n\n/** One line of a bill - what one subscription cost that month, or tax and credits on none. */\n@Entity()\n@Index('ix_saas_bill_line_0', (line: SaasBillLine) => [line.domain, line.bill])\n@ObjectType({ description: 'Entity for SaasBillLine — what one subscription cost in a bill, or tax and credits' })\nexport class SaasBillLine {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier of the line' })\n readonly id: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { nullable: true, description: 'The domain the line belongs to' })\n domain?: Domain\n\n @RelationId((line: SaasBillLine) => line.domain)\n domainId?: string\n\n @ManyToOne(type => SaasBill, bill => bill.lines, { onDelete: 'CASCADE' })\n @Field(type => SaasBill, { nullable: true, description: 'The bill it is a line of' })\n bill?: SaasBill\n\n @RelationId((line: SaasBillLine) => line.bill)\n billId?: string\n\n @ManyToOne(type => SaasSubscription, { nullable: true, onDelete: 'SET NULL' })\n @Field(type => SaasSubscription, { nullable: true, description: 'The subscription it is for; none for tax and credits' })\n subscription?: SaasSubscription\n\n @RelationId((line: SaasBillLine) => line.subscription)\n subscriptionId?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'What the bill calls it - tax, a credit, a support fee' })\n label?: string\n\n @Column(moneyColumn())\n @Field(type => Float, { description: 'What it cost; a credit is below zero' })\n amount: number\n}\n"]}
@@ -0,0 +1,19 @@
1
+ import { User } from '@things-factory/auth-base';
2
+ import { Counterparty } from '@things-factory/biz-base';
3
+ import { Domain } from '@things-factory/shell';
4
+ /**
5
+ * Whom a keeper said is no subscription - paid month after month but a cleaner, an accountant, a landlord - so the books
6
+ * stop offering it as one (ADR-0177 개정 1): a counterparty, or the name written on lines no counterparty is linked to.
7
+ * Shown again, the row goes.
8
+ */
9
+ export declare class SaasHiddenVendor {
10
+ readonly id: string;
11
+ domain?: Domain;
12
+ domainId?: string;
13
+ counterparty?: Counterparty;
14
+ counterpartyId?: string;
15
+ /** The written name's key (biz-base `nameKey`), for lines no counterparty is linked to. */
16
+ nameKey?: string;
17
+ createdAt?: Date;
18
+ creator?: User;
19
+ }
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SaasHiddenVendor = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const auth_base_1 = require("@things-factory/auth-base");
6
+ const biz_base_1 = require("@things-factory/biz-base");
7
+ const shell_1 = require("@things-factory/shell");
8
+ const typeorm_1 = require("typeorm");
9
+ /**
10
+ * Whom a keeper said is no subscription - paid month after month but a cleaner, an accountant, a landlord - so the books
11
+ * stop offering it as one (ADR-0177 개정 1): a counterparty, or the name written on lines no counterparty is linked to.
12
+ * Shown again, the row goes.
13
+ */
14
+ let SaasHiddenVendor = class SaasHiddenVendor {
15
+ };
16
+ exports.SaasHiddenVendor = SaasHiddenVendor;
17
+ tslib_1.__decorate([
18
+ (0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
19
+ tslib_1.__metadata("design:type", String)
20
+ ], SaasHiddenVendor.prototype, "id", void 0);
21
+ tslib_1.__decorate([
22
+ (0, typeorm_1.ManyToOne)(type => shell_1.Domain),
23
+ tslib_1.__metadata("design:type", shell_1.Domain)
24
+ ], SaasHiddenVendor.prototype, "domain", void 0);
25
+ tslib_1.__decorate([
26
+ (0, typeorm_1.RelationId)((row) => row.domain),
27
+ tslib_1.__metadata("design:type", String)
28
+ ], SaasHiddenVendor.prototype, "domainId", void 0);
29
+ tslib_1.__decorate([
30
+ (0, typeorm_1.ManyToOne)(type => biz_base_1.Counterparty, { nullable: true, onDelete: 'CASCADE' }),
31
+ tslib_1.__metadata("design:type", biz_base_1.Counterparty)
32
+ ], SaasHiddenVendor.prototype, "counterparty", void 0);
33
+ tslib_1.__decorate([
34
+ (0, typeorm_1.RelationId)((row) => row.counterparty),
35
+ tslib_1.__metadata("design:type", String)
36
+ ], SaasHiddenVendor.prototype, "counterpartyId", void 0);
37
+ tslib_1.__decorate([
38
+ (0, typeorm_1.Column)({ nullable: true }),
39
+ tslib_1.__metadata("design:type", String)
40
+ ], SaasHiddenVendor.prototype, "nameKey", void 0);
41
+ tslib_1.__decorate([
42
+ (0, typeorm_1.CreateDateColumn)(),
43
+ tslib_1.__metadata("design:type", Date)
44
+ ], SaasHiddenVendor.prototype, "createdAt", void 0);
45
+ tslib_1.__decorate([
46
+ (0, typeorm_1.ManyToOne)(type => auth_base_1.User, { nullable: true }),
47
+ tslib_1.__metadata("design:type", auth_base_1.User)
48
+ ], SaasHiddenVendor.prototype, "creator", void 0);
49
+ exports.SaasHiddenVendor = SaasHiddenVendor = tslib_1.__decorate([
50
+ (0, typeorm_1.Entity)(),
51
+ (0, typeorm_1.Index)('ix_saas_hidden_vendor_0', (row) => [row.domain, row.counterparty, row.nameKey])
52
+ ], SaasHiddenVendor);
53
+ //# sourceMappingURL=saas-hidden-vendor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"saas-hidden-vendor.js","sourceRoot":"","sources":["../../server/service/saas-hidden-vendor.ts"],"names":[],"mappings":";;;;AAAA,yDAAgD;AAChD,uDAAuD;AACvD,iDAA8C;AAC9C,qCAAgH;AAEhH;;;;GAIG;AAGI,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;CAyB5B,CAAA;AAzBY,4CAAgB;AAElB;IADR,IAAA,gCAAsB,EAAC,MAAM,CAAC;;4CACZ;AAGnB;IADC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,cAAM,CAAC;sCACjB,cAAM;gDAAA;AAGf;IADC,IAAA,oBAAU,EAAC,CAAC,GAAqB,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC;;kDACjC;AAGjB;IADC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,uBAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;sCAC1D,uBAAY;sDAAA;AAG3B;IADC,IAAA,oBAAU,EAAC,CAAC,GAAqB,EAAE,EAAE,CAAC,GAAG,CAAC,YAAY,CAAC;;wDACjC;AAIvB;IADC,IAAA,gBAAM,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;iDACX;AAGhB;IADC,IAAA,0BAAgB,GAAE;sCACP,IAAI;mDAAA;AAGhB;IADC,IAAA,mBAAS,EAAC,IAAI,CAAC,EAAE,CAAC,gBAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;sCAClC,gBAAI;iDAAA;2BAxBH,gBAAgB;IAF5B,IAAA,gBAAM,GAAE;IACR,IAAA,eAAK,EAAC,yBAAyB,EAAE,CAAC,GAAqB,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,YAAY,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;GAC5F,gBAAgB,CAyB5B","sourcesContent":["import { User } from '@things-factory/auth-base'\nimport { Counterparty } from '@things-factory/biz-base'\nimport { Domain } from '@things-factory/shell'\nimport { Column, CreateDateColumn, Entity, Index, ManyToOne, PrimaryGeneratedColumn, RelationId } from 'typeorm'\n\n/**\n * Whom a keeper said is no subscription - paid month after month but a cleaner, an accountant, a landlord - so the books\n * stop offering it as one (ADR-0177 개정 1): a counterparty, or the name written on lines no counterparty is linked to.\n * Shown again, the row goes.\n */\n@Entity()\n@Index('ix_saas_hidden_vendor_0', (row: SaasHiddenVendor) => [row.domain, row.counterparty, row.nameKey])\nexport class SaasHiddenVendor {\n @PrimaryGeneratedColumn('uuid')\n readonly id: string\n\n @ManyToOne(type => Domain)\n domain?: Domain\n\n @RelationId((row: SaasHiddenVendor) => row.domain)\n domainId?: string\n\n @ManyToOne(type => Counterparty, { nullable: true, onDelete: 'CASCADE' })\n counterparty?: Counterparty\n\n @RelationId((row: SaasHiddenVendor) => row.counterparty)\n counterpartyId?: string\n\n /** The written name's key (biz-base `nameKey`), for lines no counterparty is linked to. */\n @Column({ nullable: true })\n nameKey?: string\n\n @CreateDateColumn()\n createdAt?: Date\n\n @ManyToOne(type => User, { nullable: true })\n creator?: User\n}\n"]}
@@ -2,9 +2,16 @@ import { SaasAccount } from './saas-account';
2
2
  import { SaasBill } from './saas-bill';
3
3
  import { SaasSeat } from './saas-seat';
4
4
  import { SaasSubscription } from './saas-subscription';
5
- import { SaasAccountPatch, SaasBillInput, SaasSeatPatch, SaasSubscriptionPatch } from './saas-type';
5
+ import { SaasAccountPatch, SaasBillInput, SaasCostsInput, SaasLicensesInput, SaasSeatPatch, SaasSubscriptionPatch } from './saas-type';
6
6
  export declare class SaasMutation {
7
+ syncSaasLicenses(licenses: SaasLicensesInput, context: ResolverContext): Promise<import("./saas-sync").LicenseSyncResult>;
8
+ syncSaasCosts(costs: SaasCostsInput[], context: ResolverContext): Promise<{
9
+ results: import("./saas-sync").CostSyncResult[];
10
+ unmatched: string[];
11
+ }>;
7
12
  updateMultipleSaasAccount(patches: SaasAccountPatch[], context: ResolverContext): Promise<SaasAccount[]>;
13
+ createSaasAccountsFromCandidates(keys: string[], context: ResolverContext): Promise<SaasAccount[]>;
14
+ hideSaasCandidates(keys: string[], hide: boolean, context: ResolverContext): Promise<boolean>;
8
15
  updateMultipleSaasSubscription(accountId: string, patches: SaasSubscriptionPatch[], context: ResolverContext): Promise<SaasSubscription[]>;
9
16
  updateMultipleSaasSeat(subscriptionId: string, patches: SaasSeatPatch[], context: ResolverContext): Promise<SaasSeat[]>;
10
17
  saveSaasBill(accountId: string, bill: SaasBillInput, context: ResolverContext): Promise<SaasBill>;
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SaasMutation = void 0;
4
4
  const tslib_1 = require("tslib");
5
+ const auth_base_1 = require("@things-factory/auth-base");
5
6
  const shell_1 = require("@things-factory/shell");
6
7
  const type_graphql_1 = require("type-graphql");
7
8
  const saas_access_1 = require("./saas-access");
@@ -10,16 +11,43 @@ const saas_bill_1 = require("./saas-bill");
10
11
  const saas_service_1 = require("./saas-service");
11
12
  const saas_seat_1 = require("./saas-seat");
12
13
  const saas_subscription_1 = require("./saas-subscription");
14
+ const saas_sync_1 = require("./saas-sync");
13
15
  const saas_type_1 = require("./saas-type");
16
+ /** The bank's fact (ADR-0139) is read only by whoever reads bank lines. */
17
+ async function mustReadBank(state) {
18
+ const { domain, user, unsafeIP, prohibitedPrivileges } = state;
19
+ if (!(await (0, auth_base_1.checkPermission)({ category: 'bank', privilege: 'query', owner: false }, user, domain, unsafeIP, prohibitedPrivileges)))
20
+ throw new shell_1.Refusal('saas-candidates-need-bank', {}, 'Making accounts from the books needs reading the bank lines');
21
+ }
14
22
  /*
15
23
  * The accounts are the keepers'. What is under an account - its subscriptions, their seats, its bills - is also its
16
24
  * admins', whatever their seat (ADR-0177 Q4): those doors ask `saas-self`, and the service keeps an admin to their own.
17
25
  */
18
26
  let SaasMutation = class SaasMutation {
27
+ /* A scenario's step (ADR-0177 개정 2): seats and quantities only, so its own category - the system admin runs it. */
28
+ syncSaasLicenses(licenses, context) {
29
+ const { tx, domain, user } = context.state;
30
+ return (0, saas_sync_1.syncSaasLicenses)(tx, domain, user, licenses, new Date().toISOString().slice(0, 10));
31
+ }
32
+ /* A scenario's step (ADR-0177 개정 3): the bills of the closed months as the vendor's cost report says. */
33
+ syncSaasCosts(costs, context) {
34
+ const { tx, domain, user } = context.state;
35
+ return (0, saas_sync_1.syncSaasCostsOf)(tx, domain, user, costs, new Date().toISOString().slice(0, 10));
36
+ }
19
37
  updateMultipleSaasAccount(patches, context) {
20
38
  const { tx, domain, user } = context.state;
21
39
  return (0, saas_service_1.saveSaasAccounts)(tx, domain, user, patches);
22
40
  }
41
+ /* The candidates are read from the bank and card lines - a keeper who also reads them (checked in the service). */
42
+ async createSaasAccountsFromCandidates(keys, context) {
43
+ const { tx, domain, user } = context.state;
44
+ await mustReadBank(context.state);
45
+ return (0, saas_service_1.createSaasAccountsFromCandidates)(tx, domain, user, keys, new Date().toISOString().slice(0, 10));
46
+ }
47
+ async hideSaasCandidates(keys, hide, context) {
48
+ const { tx, domain, user } = context.state;
49
+ return (0, saas_service_1.hideSaasCandidates)(tx, domain, user, keys, hide);
50
+ }
23
51
  async updateMultipleSaasSubscription(accountId, patches, context) {
24
52
  const { tx, domain, user } = context.state;
25
53
  return (0, saas_service_1.saveSaasSubscriptions)(tx, domain, user, await (0, saas_access_1.scopeOf)(context.state, 'mutation', tx), accountId, patches);
@@ -38,6 +66,26 @@ let SaasMutation = class SaasMutation {
38
66
  }
39
67
  };
40
68
  exports.SaasMutation = SaasMutation;
69
+ tslib_1.__decorate([
70
+ (0, type_graphql_1.Directive)('@transaction'),
71
+ (0, type_graphql_1.Directive)('@privilege(category: "saas-sync", privilege: "mutation", domainOwnerGranted: true)'),
72
+ (0, type_graphql_1.Mutation)(type => saas_type_1.SaasLicenseSync, { description: "To keep an account's seats and quantities as its vendor tenant says - what it bought and who holds each" }),
73
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('licenses', type => saas_type_1.SaasLicensesInput)),
74
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
75
+ tslib_1.__metadata("design:type", Function),
76
+ tslib_1.__metadata("design:paramtypes", [saas_type_1.SaasLicensesInput, Object]),
77
+ tslib_1.__metadata("design:returntype", void 0)
78
+ ], SaasMutation.prototype, "syncSaasLicenses", null);
79
+ tslib_1.__decorate([
80
+ (0, type_graphql_1.Directive)('@transaction'),
81
+ (0, type_graphql_1.Directive)('@privilege(category: "saas-sync", privilege: "mutation", domainOwnerGranted: true)'),
82
+ (0, type_graphql_1.Mutation)(type => saas_type_1.SaasCostSyncs, { description: "To write accounts' bills of the closed months from their vendors' cost reports - an entry an account; never over a bill a person wrote; vendor accounts no account names are passed over" }),
83
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('costs', type => [saas_type_1.SaasCostsInput])),
84
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
85
+ tslib_1.__metadata("design:type", Function),
86
+ tslib_1.__metadata("design:paramtypes", [Array, Object]),
87
+ tslib_1.__metadata("design:returntype", void 0)
88
+ ], SaasMutation.prototype, "syncSaasCosts", null);
41
89
  tslib_1.__decorate([
42
90
  (0, type_graphql_1.Directive)('@transaction'),
43
91
  (0, type_graphql_1.Directive)('@privilege(category: "saas", privilege: "mutation", domainOwnerGranted: true)'),
@@ -49,6 +97,27 @@ tslib_1.__decorate([
49
97
  tslib_1.__metadata("design:paramtypes", [Array, Object]),
50
98
  tslib_1.__metadata("design:returntype", void 0)
51
99
  ], SaasMutation.prototype, "updateMultipleSaasAccount", null);
100
+ tslib_1.__decorate([
101
+ (0, type_graphql_1.Directive)('@transaction'),
102
+ (0, type_graphql_1.Directive)('@privilege(category: "saas", privilege: "mutation", domainOwnerGranted: true)'),
103
+ (0, type_graphql_1.Mutation)(type => [saas_account_1.SaasAccount], { description: 'To make an account, with one usage subscription at the monthly average, of each candidate (by its key)' }),
104
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('keys', type => [String])),
105
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
106
+ tslib_1.__metadata("design:type", Function),
107
+ tslib_1.__metadata("design:paramtypes", [Array, Object]),
108
+ tslib_1.__metadata("design:returntype", Promise)
109
+ ], SaasMutation.prototype, "createSaasAccountsFromCandidates", null);
110
+ tslib_1.__decorate([
111
+ (0, type_graphql_1.Directive)('@transaction'),
112
+ (0, type_graphql_1.Directive)('@privilege(category: "saas", privilege: "mutation", domainOwnerGranted: true)'),
113
+ (0, type_graphql_1.Mutation)(type => Boolean, { description: 'To hide candidates (by their keys), or with hide false to show them again' }),
114
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('keys', type => [String])),
115
+ tslib_1.__param(1, (0, type_graphql_1.Arg)('hide')),
116
+ tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
117
+ tslib_1.__metadata("design:type", Function),
118
+ tslib_1.__metadata("design:paramtypes", [Array, Boolean, Object]),
119
+ tslib_1.__metadata("design:returntype", Promise)
120
+ ], SaasMutation.prototype, "hideSaasCandidates", null);
52
121
  tslib_1.__decorate([
53
122
  (0, type_graphql_1.Directive)('@transaction'),
54
123
  (0, type_graphql_1.Directive)('@privilege(category: "saas-self", privilege: "mutation", domainOwnerGranted: true)'),
@@ -1 +1 @@
1
- {"version":3,"file":"saas-mutation.js","sourceRoot":"","sources":["../../server/service/saas-mutation.ts"],"names":[],"mappings":"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","sourcesContent":["import { SpeakRefusals } from '@things-factory/shell'\nimport { Arg, Ctx, Directive, Mutation, Resolver, UseMiddleware } from 'type-graphql'\n\nimport { scopeOf } from './saas-access'\nimport { SaasAccount } from './saas-account'\nimport { SaasBill } from './saas-bill'\nimport { deleteSaasBill, saveSaasAccounts, saveSaasBill, saveSaasSeats, saveSaasSubscriptions } from './saas-service'\nimport { SaasSeat } from './saas-seat'\nimport { SaasSubscription } from './saas-subscription'\nimport { SaasAccountPatch, SaasBillInput, SaasSeatPatch, SaasSubscriptionPatch } from './saas-type'\n\n/*\n * The accounts are the keepers'. What is under an account - its subscriptions, their seats, its bills - is also its\n * admins', whatever their seat (ADR-0177 Q4): those doors ask `saas-self`, and the service keeps an admin to their own.\n */\n@UseMiddleware(SpeakRefusals)\n@Resolver(SaasAccount)\nexport class SaasMutation {\n @Directive('@transaction')\n @Directive('@privilege(category: \"saas\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@auditTarget(kind: \"SaasAccount\", arg: \"patches\")')\n @Mutation(type => [SaasAccount], { description: 'To save the accounts grid - new, changed and deleted rows together' })\n updateMultipleSaasAccount(@Arg('patches', type => [SaasAccountPatch]) patches: SaasAccountPatch[], @Ctx() context: ResolverContext) {\n const { tx, domain, user } = context.state\n return saveSaasAccounts(tx, domain, user, patches)\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"saas-self\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@auditTarget(kind: \"SaasAccount\", arg: \"accountId\")')\n @Mutation(type => [SaasSubscription], { description: \"To save an account's subscriptions grid\" })\n async updateMultipleSaasSubscription(@Arg('accountId') accountId: string, @Arg('patches', type => [SaasSubscriptionPatch]) patches: SaasSubscriptionPatch[], @Ctx() context: ResolverContext) {\n const { tx, domain, user } = context.state\n return saveSaasSubscriptions(tx, domain, user, await scopeOf(context.state, 'mutation', tx), accountId, patches)\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"saas-self\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@auditTarget(kind: \"SaasSubscription\", arg: \"subscriptionId\")')\n @Mutation(type => [SaasSeat], { description: \"To save a subscription's seats grid\" })\n async updateMultipleSaasSeat(@Arg('subscriptionId') subscriptionId: string, @Arg('patches', type => [SaasSeatPatch]) patches: SaasSeatPatch[], @Ctx() context: ResolverContext) {\n const { tx, domain, user } = context.state\n return saveSaasSeats(tx, domain, user, await scopeOf(context.state, 'mutation', tx), subscriptionId, patches)\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"saas-self\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@auditTarget(kind: \"SaasAccount\", arg: \"accountId\")')\n @Mutation(type => SaasBill, { description: \"To write an account's bill for a month, its lines whole\" })\n async saveSaasBill(@Arg('accountId') accountId: string, @Arg('bill', type => SaasBillInput) bill: SaasBillInput, @Ctx() context: ResolverContext) {\n const { tx, domain, user } = context.state\n return saveSaasBill(tx, domain, user, await scopeOf(context.state, 'mutation', tx), accountId, bill)\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"saas-self\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@auditTarget(kind: \"SaasBill\", arg: \"id\")')\n @Mutation(type => Boolean, { description: 'To delete a bill' })\n async deleteSaasBill(@Arg('id') id: string, @Ctx() context: ResolverContext) {\n const { tx, domain } = context.state\n return deleteSaasBill(tx, domain, await scopeOf(context.state, 'mutation', tx), id)\n }\n}\n"]}
1
+ {"version":3,"file":"saas-mutation.js","sourceRoot":"","sources":["../../server/service/saas-mutation.ts"],"names":[],"mappings":"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","sourcesContent":["import { checkPermission } from '@things-factory/auth-base'\nimport { Refusal, SpeakRefusals } from '@things-factory/shell'\nimport { Arg, Ctx, Directive, Mutation, Resolver, UseMiddleware } from 'type-graphql'\n\nimport { scopeOf } from './saas-access'\nimport { SaasAccount } from './saas-account'\nimport { SaasBill } from './saas-bill'\nimport { createSaasAccountsFromCandidates, deleteSaasBill, hideSaasCandidates, saveSaasAccounts, saveSaasBill, saveSaasSeats, saveSaasSubscriptions } from './saas-service'\nimport { SaasSeat } from './saas-seat'\nimport { SaasSubscription } from './saas-subscription'\nimport { syncSaasCostsOf, syncSaasLicenses } from './saas-sync'\nimport { SaasAccountPatch, SaasBillInput, SaasCostSyncs, SaasCostsInput, SaasLicenseSync, SaasLicensesInput, SaasSeatPatch, SaasSubscriptionPatch } from './saas-type'\n\n/** The bank's fact (ADR-0139) is read only by whoever reads bank lines. */\nasync function mustReadBank(state: any) {\n const { domain, user, unsafeIP, prohibitedPrivileges } = state\n if (!(await checkPermission({ category: 'bank', privilege: 'query', owner: false } as any, user, domain, unsafeIP, prohibitedPrivileges)))\n throw new Refusal('saas-candidates-need-bank', {}, 'Making accounts from the books needs reading the bank lines')\n}\n\n/*\n * The accounts are the keepers'. What is under an account - its subscriptions, their seats, its bills - is also its\n * admins', whatever their seat (ADR-0177 Q4): those doors ask `saas-self`, and the service keeps an admin to their own.\n */\n@UseMiddleware(SpeakRefusals)\n@Resolver(SaasAccount)\nexport class SaasMutation {\n /* A scenario's step (ADR-0177 개정 2): seats and quantities only, so its own category - the system admin runs it. */\n @Directive('@transaction')\n @Directive('@privilege(category: \"saas-sync\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(type => SaasLicenseSync, { description: \"To keep an account's seats and quantities as its vendor tenant says - what it bought and who holds each\" })\n syncSaasLicenses(@Arg('licenses', type => SaasLicensesInput) licenses: SaasLicensesInput, @Ctx() context: ResolverContext) {\n const { tx, domain, user } = context.state\n return syncSaasLicenses(tx, domain, user, licenses, new Date().toISOString().slice(0, 10))\n }\n\n /* A scenario's step (ADR-0177 개정 3): the bills of the closed months as the vendor's cost report says. */\n @Directive('@transaction')\n @Directive('@privilege(category: \"saas-sync\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(type => SaasCostSyncs, { description: \"To write accounts' bills of the closed months from their vendors' cost reports - an entry an account; never over a bill a person wrote; vendor accounts no account names are passed over\" })\n syncSaasCosts(@Arg('costs', type => [SaasCostsInput]) costs: SaasCostsInput[], @Ctx() context: ResolverContext) {\n const { tx, domain, user } = context.state\n return syncSaasCostsOf(tx, domain, user, costs, new Date().toISOString().slice(0, 10))\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"saas\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@auditTarget(kind: \"SaasAccount\", arg: \"patches\")')\n @Mutation(type => [SaasAccount], { description: 'To save the accounts grid - new, changed and deleted rows together' })\n updateMultipleSaasAccount(@Arg('patches', type => [SaasAccountPatch]) patches: SaasAccountPatch[], @Ctx() context: ResolverContext) {\n const { tx, domain, user } = context.state\n return saveSaasAccounts(tx, domain, user, patches)\n }\n\n /* The candidates are read from the bank and card lines - a keeper who also reads them (checked in the service). */\n @Directive('@transaction')\n @Directive('@privilege(category: \"saas\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(type => [SaasAccount], { description: 'To make an account, with one usage subscription at the monthly average, of each candidate (by its key)' })\n async createSaasAccountsFromCandidates(@Arg('keys', type => [String]) keys: string[], @Ctx() context: ResolverContext) {\n const { tx, domain, user } = context.state\n await mustReadBank(context.state)\n return createSaasAccountsFromCandidates(tx, domain, user, keys, new Date().toISOString().slice(0, 10))\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"saas\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(type => Boolean, { description: 'To hide candidates (by their keys), or with hide false to show them again' })\n async hideSaasCandidates(@Arg('keys', type => [String]) keys: string[], @Arg('hide') hide: boolean, @Ctx() context: ResolverContext) {\n const { tx, domain, user } = context.state\n return hideSaasCandidates(tx, domain, user, keys, hide)\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"saas-self\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@auditTarget(kind: \"SaasAccount\", arg: \"accountId\")')\n @Mutation(type => [SaasSubscription], { description: \"To save an account's subscriptions grid\" })\n async updateMultipleSaasSubscription(@Arg('accountId') accountId: string, @Arg('patches', type => [SaasSubscriptionPatch]) patches: SaasSubscriptionPatch[], @Ctx() context: ResolverContext) {\n const { tx, domain, user } = context.state\n return saveSaasSubscriptions(tx, domain, user, await scopeOf(context.state, 'mutation', tx), accountId, patches)\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"saas-self\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@auditTarget(kind: \"SaasSubscription\", arg: \"subscriptionId\")')\n @Mutation(type => [SaasSeat], { description: \"To save a subscription's seats grid\" })\n async updateMultipleSaasSeat(@Arg('subscriptionId') subscriptionId: string, @Arg('patches', type => [SaasSeatPatch]) patches: SaasSeatPatch[], @Ctx() context: ResolverContext) {\n const { tx, domain, user } = context.state\n return saveSaasSeats(tx, domain, user, await scopeOf(context.state, 'mutation', tx), subscriptionId, patches)\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"saas-self\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@auditTarget(kind: \"SaasAccount\", arg: \"accountId\")')\n @Mutation(type => SaasBill, { description: \"To write an account's bill for a month, its lines whole\" })\n async saveSaasBill(@Arg('accountId') accountId: string, @Arg('bill', type => SaasBillInput) bill: SaasBillInput, @Ctx() context: ResolverContext) {\n const { tx, domain, user } = context.state\n return saveSaasBill(tx, domain, user, await scopeOf(context.state, 'mutation', tx), accountId, bill)\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"saas-self\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@auditTarget(kind: \"SaasBill\", arg: \"id\")')\n @Mutation(type => Boolean, { description: 'To delete a bill' })\n async deleteSaasBill(@Arg('id') id: string, @Ctx() context: ResolverContext) {\n const { tx, domain } = context.state\n return deleteSaasBill(tx, domain, await scopeOf(context.state, 'mutation', tx), id)\n }\n}\n"]}
@@ -6,7 +6,7 @@ import { SaasAccount } from './saas-account';
6
6
  import { SaasBill } from './saas-bill';
7
7
  import { SaasSeat } from './saas-seat';
8
8
  import { SaasSubscription } from './saas-subscription';
9
- import { SaasAccountList, SaasChange } from './saas-type';
9
+ import { SaasAccountList, SaasCandidate, SaasChange } from './saas-type';
10
10
  export declare class SaasAccountQuery {
11
11
  saasAccounts(params: ListParam, context: ResolverContext): Promise<SaasAccountList>;
12
12
  mySaasAccounts(context: ResolverContext): Promise<SaasAccount[]>;
@@ -16,6 +16,7 @@ export declare class SaasAccountQuery {
16
16
  saasBills(accountId: string, context: ResolverContext): Promise<SaasBill[]>;
17
17
  saasChanges(accountId: string, context: ResolverContext): Promise<SaasChange[]>;
18
18
  saasPayments(accountId: string, context: ResolverContext): Promise<Transaction[]>;
19
+ saasCandidates(hidden: boolean, context: ResolverContext): Promise<SaasCandidate[]>;
19
20
  saasCostTrend(from: string, to: string, context: ResolverContext): Promise<{
20
21
  months: string[];
21
22
  all: import("./saas-rules").TrendSeries[];
@@ -72,6 +72,13 @@ let SaasAccountQuery = class SaasAccountQuery {
72
72
  const manager = (0, shell_1.getRepository)(saas_account_1.SaasAccount).manager;
73
73
  return (0, saas_service_1.saasPaymentsOf)(manager, context.state.domain, await (0, saas_access_1.scopeOf)(context.state, 'query', manager), accountId);
74
74
  }
75
+ /* Read from the bank and card lines (ADR-0139): the bank's door; the candidates are the keepers' (`saas`) on top. */
76
+ async saasCandidates(hidden, context) {
77
+ const manager = (0, shell_1.getRepository)(saas_account_1.SaasAccount).manager;
78
+ if ((await (0, saas_access_1.scopeOf)(context.state, 'query', manager)) !== 'all')
79
+ return [];
80
+ return (0, saas_service_1.saasCandidatesOf)(manager, context.state.domain, today(), !!hidden);
81
+ }
75
82
  saasCostTrend(from, to, context) {
76
83
  return (0, saas_service_1.saasCostTrend)((0, shell_1.getRepository)(saas_account_1.SaasAccount).manager, context.state.domain, from, to);
77
84
  }
@@ -163,6 +170,15 @@ tslib_1.__decorate([
163
170
  tslib_1.__metadata("design:paramtypes", [String, Object]),
164
171
  tslib_1.__metadata("design:returntype", Promise)
165
172
  ], SaasAccountQuery.prototype, "saasPayments", null);
173
+ tslib_1.__decorate([
174
+ (0, type_graphql_1.Directive)('@privilege(category: "bank", privilege: "query", domainOwnerGranted: false)'),
175
+ (0, type_graphql_1.Query)(type => [saas_type_1.SaasCandidate], { description: 'The vendors the bank and card lines show paid month after month that are no account or recurring item yet; with hidden, the ones hidden' }),
176
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('hidden', { nullable: true })),
177
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
178
+ tslib_1.__metadata("design:type", Function),
179
+ tslib_1.__metadata("design:paramtypes", [Boolean, Object]),
180
+ tslib_1.__metadata("design:returntype", Promise)
181
+ ], SaasAccountQuery.prototype, "saasCandidates", null);
166
182
  tslib_1.__decorate([
167
183
  (0, type_graphql_1.Directive)('@privilege(category: "saas", privilege: "query", domainOwnerGranted: true)'),
168
184
  (0, type_graphql_1.Query)(type => saas_type_1.SaasCostTrend, { description: 'The cost trend from the bills, month by month from one month to another (YYYY-MM)' }),