@things-factory/asset 10.1.243 → 10.1.245

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.
@@ -1,4 +1,5 @@
1
1
  import { User } from '@things-factory/auth-base';
2
+ import { Employee } from '@things-factory/organization';
2
3
  import { Domain, ListParam } from '@things-factory/shell';
3
4
  import { Asset } from './asset';
4
5
  import { AssetList, AssetYear } from './asset-type';
@@ -13,6 +14,7 @@ export declare class AssetQuery {
13
14
  })[];
14
15
  }>;
15
16
  year(asset: Asset, fiscalYear?: number): AssetYear;
17
+ keeper(row: Asset): Employee | Promise<Employee>;
16
18
  domain(row: Asset): Domain | Promise<Domain>;
17
19
  creator(row: Asset): User | Promise<User>;
18
20
  updater(row: Asset): User | Promise<User>;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AssetQuery = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const auth_base_1 = require("@things-factory/auth-base");
6
+ const organization_1 = require("@things-factory/organization");
6
7
  const shell_1 = require("@things-factory/shell");
7
8
  const type_graphql_1 = require("type-graphql");
8
9
  const asset_document_service_1 = require("../asset-document/asset-document-service");
@@ -20,7 +21,7 @@ let AssetQuery = class AssetQuery {
20
21
  domain,
21
22
  params,
22
23
  repository: (0, shell_1.getRepository)(asset_1.Asset),
23
- searchables: ['name', 'location', 'keeper', 'source', 'project', 'description']
24
+ searchables: ['name', 'location', 'source', 'project', 'description']
24
25
  });
25
26
  const [items, total] = await query.getManyAndCount();
26
27
  const counts = await (0, asset_document_service_1.documentCounts)((0, shell_1.getRepository)(asset_1.Asset).manager, domain, 'Asset', items.map(one => one.id));
@@ -34,6 +35,9 @@ let AssetQuery = class AssetQuery {
34
35
  year(asset, fiscalYear) {
35
36
  return (0, asset_rules_1.depreciationOf)(asset, fiscalYear ?? new Date().getFullYear());
36
37
  }
38
+ keeper(row) {
39
+ return row.keeper ?? (row.keeperId ? (0, shell_1.getRepository)(organization_1.Employee).findOneBy({ id: row.keeperId }) : undefined);
40
+ }
37
41
  domain(row) {
38
42
  return row.domain ?? (row.domainId ? (0, shell_1.getRepository)(shell_1.Domain).findOneBy({ id: row.domainId }) : undefined);
39
43
  }
@@ -80,6 +84,13 @@ tslib_1.__decorate([
80
84
  tslib_1.__metadata("design:paramtypes", [asset_1.Asset, Number]),
81
85
  tslib_1.__metadata("design:returntype", asset_type_1.AssetYear)
82
86
  ], AssetQuery.prototype, "year", null);
87
+ tslib_1.__decorate([
88
+ (0, type_graphql_1.FieldResolver)(type => organization_1.Employee, { nullable: true }),
89
+ tslib_1.__param(0, (0, type_graphql_1.Root)()),
90
+ tslib_1.__metadata("design:type", Function),
91
+ tslib_1.__metadata("design:paramtypes", [asset_1.Asset]),
92
+ tslib_1.__metadata("design:returntype", void 0)
93
+ ], AssetQuery.prototype, "keeper", null);
83
94
  tslib_1.__decorate([
84
95
  (0, type_graphql_1.FieldResolver)(type => shell_1.Domain, { nullable: true }),
85
96
  tslib_1.__param(0, (0, type_graphql_1.Root)()),
@@ -1 +1 @@
1
- {"version":3,"file":"asset-query.js","sourceRoot":"","sources":["../../../server/service/asset/asset-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { User } from '@things-factory/auth-base'\nimport { Domain, getQueryBuilderFromListParams, getRepository, ListParam, SpeakRefusals } from '@things-factory/shell'\nimport { Arg, Args, Ctx, Directive, FieldResolver, Int, Query, Resolver, Root, UseMiddleware } from 'type-graphql'\n\nimport { documentCounts } from '../asset-document/asset-document-service'\nimport { Asset } from './asset'\nimport { depreciationOf } from './asset-rules'\nimport { assetReconciliation } from './asset-service'\nimport { AssetList, AssetReconciliation, AssetYear } from './asset-type'\n\n@UseMiddleware(SpeakRefusals)\n@Resolver(Asset)\nexport class AssetQuery {\n @Directive('@privilege(category: \"asset\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(type => Asset, { nullable: true, description: 'To fetch an asset' })\n asset(@Arg('id') id: string, @Ctx() context: ResolverContext) {\n return getRepository(Asset).findOne({ where: { id, domain: { id: context.state.domain.id } } })\n }\n\n @Directive('@privilege(category: \"asset\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(type => AssetList, { description: 'To fetch a page of the asset register' })\n async assets(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<AssetList> {\n const { domain } = context.state\n const query = getQueryBuilderFromListParams({\n domain,\n params,\n repository: getRepository(Asset),\n searchables: ['name', 'location', 'keeper', 'source', 'project', 'description']\n })\n const [items, total] = await query.getManyAndCount()\n const counts = await documentCounts(getRepository(Asset).manager, domain, 'Asset', items.map(one => one.id))\n for (const one of items) one.documents = counts.get(one.id) ?? 0\n return { items, total }\n }\n\n @Directive('@privilege(category: \"asset\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(type => AssetReconciliation, { description: 'The register beside the filed balance sheet of a fiscal year' })\n assetReconciliation(@Arg('fiscalYear', type => Int) fiscalYear: number, @Ctx() context: ResolverContext) {\n return assetReconciliation(getRepository(Asset).manager, context.state.domain, fiscalYear)\n }\n\n @FieldResolver(type => AssetYear, { description: \"The asset's depreciation for a fiscal year - this year when not given\" })\n year(@Root() asset: Asset, @Arg('fiscalYear', type => Int, { nullable: true }) fiscalYear?: number): AssetYear {\n return depreciationOf(asset, fiscalYear ?? new Date().getFullYear())\n }\n\n @FieldResolver(type => Domain, { nullable: true })\n domain(@Root() row: Asset) {\n return row.domain ?? (row.domainId ? getRepository(Domain).findOneBy({ id: row.domainId }) : undefined)\n }\n\n @FieldResolver(type => User, { nullable: true })\n creator(@Root() row: Asset) {\n return row.creator ?? (row.creatorId ? getRepository(User).findOneBy({ id: row.creatorId }) : undefined)\n }\n\n @FieldResolver(type => User, { nullable: true })\n updater(@Root() row: Asset) {\n return row.updater ?? (row.updaterId ? getRepository(User).findOneBy({ id: row.updaterId }) : undefined)\n }\n}\n"]}
1
+ {"version":3,"file":"asset-query.js","sourceRoot":"","sources":["../../../server/service/asset/asset-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { User } from '@things-factory/auth-base'\nimport { Employee } from '@things-factory/organization'\nimport { Domain, getQueryBuilderFromListParams, getRepository, ListParam, SpeakRefusals } from '@things-factory/shell'\nimport { Arg, Args, Ctx, Directive, FieldResolver, Int, Query, Resolver, Root, UseMiddleware } from 'type-graphql'\n\nimport { documentCounts } from '../asset-document/asset-document-service'\nimport { Asset } from './asset'\nimport { depreciationOf } from './asset-rules'\nimport { assetReconciliation } from './asset-service'\nimport { AssetList, AssetReconciliation, AssetYear } from './asset-type'\n\n@UseMiddleware(SpeakRefusals)\n@Resolver(Asset)\nexport class AssetQuery {\n @Directive('@privilege(category: \"asset\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(type => Asset, { nullable: true, description: 'To fetch an asset' })\n asset(@Arg('id') id: string, @Ctx() context: ResolverContext) {\n return getRepository(Asset).findOne({ where: { id, domain: { id: context.state.domain.id } } })\n }\n\n @Directive('@privilege(category: \"asset\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(type => AssetList, { description: 'To fetch a page of the asset register' })\n async assets(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<AssetList> {\n const { domain } = context.state\n const query = getQueryBuilderFromListParams({\n domain,\n params,\n repository: getRepository(Asset),\n searchables: ['name', 'location', 'source', 'project', 'description']\n })\n const [items, total] = await query.getManyAndCount()\n const counts = await documentCounts(getRepository(Asset).manager, domain, 'Asset', items.map(one => one.id))\n for (const one of items) one.documents = counts.get(one.id) ?? 0\n return { items, total }\n }\n\n @Directive('@privilege(category: \"asset\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(type => AssetReconciliation, { description: 'The register beside the filed balance sheet of a fiscal year' })\n assetReconciliation(@Arg('fiscalYear', type => Int) fiscalYear: number, @Ctx() context: ResolverContext) {\n return assetReconciliation(getRepository(Asset).manager, context.state.domain, fiscalYear)\n }\n\n @FieldResolver(type => AssetYear, { description: \"The asset's depreciation for a fiscal year - this year when not given\" })\n year(@Root() asset: Asset, @Arg('fiscalYear', type => Int, { nullable: true }) fiscalYear?: number): AssetYear {\n return depreciationOf(asset, fiscalYear ?? new Date().getFullYear())\n }\n\n @FieldResolver(type => Employee, { nullable: true })\n keeper(@Root() row: Asset) {\n return row.keeper ?? (row.keeperId ? getRepository(Employee).findOneBy({ id: row.keeperId }) : undefined)\n }\n\n @FieldResolver(type => Domain, { nullable: true })\n domain(@Root() row: Asset) {\n return row.domain ?? (row.domainId ? getRepository(Domain).findOneBy({ id: row.domainId }) : undefined)\n }\n\n @FieldResolver(type => User, { nullable: true })\n creator(@Root() row: Asset) {\n return row.creator ?? (row.creatorId ? getRepository(User).findOneBy({ id: row.creatorId }) : undefined)\n }\n\n @FieldResolver(type => User, { nullable: true })\n updater(@Root() row: Asset) {\n return row.updater ?? (row.updaterId ? getRepository(User).findOneBy({ id: row.updaterId }) : undefined)\n }\n}\n"]}
@@ -30,6 +30,8 @@ export declare const DATE: RegExp;
30
30
  /** What depreciation reads of an asset. */
31
31
  export type Depreciable = {
32
32
  cost: number;
33
+ /** False for an item only looked after - bought as an expense, so nothing to depreciate (ADR-0175 amendment 2). */
34
+ capitalized?: boolean | null;
33
35
  residualValue?: number | null;
34
36
  method: DepreciationMethod | string;
35
37
  usefulLifeYears?: number | null;
@@ -73,6 +73,8 @@ function heldAtYearEnd(asset, fiscalYear) {
73
73
  */
74
74
  function depreciationOf(asset, fiscalYear) {
75
75
  const cost = Number(asset.cost) || 0;
76
+ if (asset.capitalized === false)
77
+ return { fiscalYear, expense: 0, accumulated: 0, bookValue: cost };
76
78
  const residual = Math.min(Number(asset.residualValue) || 0, cost);
77
79
  const base = cost - residual;
78
80
  const accumulatedAt = (year) => {
@@ -117,7 +119,8 @@ function reconcile(assets, lines, fiscalYear) {
117
119
  const ordered = [...(lines ?? [])].sort((a, b) => a.rank - b.rank);
118
120
  const lineOf = (code) => ordered.findIndex(one => one.code === code && !one.contra);
119
121
  const codes = new Set(Object.values(exports.DEFAULT_STATEMENT_CODE).filter((code) => !!code && lineOf(code) >= 0 && !!ordered[lineOf(code)].amount));
120
- const held = assets.filter(one => heldAtYearEnd(one, fiscalYear));
122
+ /* An item only looked after is no asset of the books (ADR-0175 amendment 2). */
123
+ const held = assets.filter(one => one.capitalized !== false && heldAtYearEnd(one, fiscalYear));
121
124
  for (const asset of held) {
122
125
  const code = asset.statementCode || exports.DEFAULT_STATEMENT_CODE[asset.kind];
123
126
  if (code)
@@ -1 +1 @@
1
- {"version":3,"file":"asset-rules.js","sourceRoot":"","sources":["../../../server/service/asset/asset-rules.ts"],"names":[],"mappings":"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","sourcesContent":["import { registerEnumType } from 'type-graphql'\n\n/*\n * The asset register's rules (ADR-0175 decisions 3-5) - apart from the entity, so the screens' words and the tests read\n * them without a type-graphql class. Pure.\n */\n\nexport enum AssetKind {\n LAND = 'LAND',\n BUILDING = 'BUILDING',\n MACHINERY = 'MACHINERY',\n VEHICLE = 'VEHICLE',\n FURNITURE = 'FURNITURE',\n FACILITY = 'FACILITY',\n DEVELOPMENT_COST = 'DEVELOPMENT_COST',\n SOFTWARE = 'SOFTWARE',\n OTHER_INTANGIBLE = 'OTHER_INTANGIBLE'\n}\nregisterEnumType(AssetKind, { name: 'AssetKind', description: 'What an asset is - land, a building, machinery, a vehicle, furniture, a facility, development cost, software or another intangible' })\n\nexport enum AssetStatus {\n IN_USE = 'IN_USE',\n DISPOSED = 'DISPOSED',\n SCRAPPED = 'SCRAPPED'\n}\nregisterEnumType(AssetStatus, { name: 'AssetStatus', description: 'Whether an asset is in use, disposed of (sold) or scrapped' })\n\nexport enum DepreciationMethod {\n STRAIGHT_LINE = 'STRAIGHT_LINE',\n DECLINING_BALANCE = 'DECLINING_BALANCE',\n NONE = 'NONE'\n}\nregisterEnumType(DepreciationMethod, { name: 'DepreciationMethod', description: 'How an asset is depreciated - straight line, declining balance, or not at all (land)' })\n\n/**\n * The line of the standard balance sheet (표준재무제표) each kind is filed under, as accounting reads it\n * (`FinancialStatementLine.code`). An asset may name another; a kind without one names its own.\n */\nexport const DEFAULT_STATEMENT_CODE: Record<AssetKind, string | null> = {\n [AssetKind.LAND]: '111',\n [AssetKind.BUILDING]: '114',\n [AssetKind.MACHINERY]: '122',\n [AssetKind.VEHICLE]: '134',\n [AssetKind.FURNITURE]: '149',\n [AssetKind.FACILITY]: '149',\n [AssetKind.DEVELOPMENT_COST]: '184',\n [AssetKind.SOFTWARE]: '186',\n [AssetKind.OTHER_INTANGIBLE]: null\n}\n\n/** Land is not depreciated; everything else straight line unless written. */\nexport const defaultMethodOf = (kind: AssetKind | string) => (kind === AssetKind.LAND ? DepreciationMethod.NONE : DepreciationMethod.STRAIGHT_LINE)\n\nexport const DATE = /^\\d{4}-\\d{2}-\\d{2}$/\n\nconst monthOf = (date: string) => Number(date.slice(0, 4)) * 12 + Number(date.slice(5, 7)) - 1\n\n/** What depreciation reads of an asset. */\nexport type Depreciable = {\n cost: number\n residualValue?: number | null\n method: DepreciationMethod | string\n usefulLifeYears?: number | null\n declineRate?: number | null\n acquiredOn: string\n depreciationStartOn?: string | null\n status?: AssetStatus | string\n disposedOn?: string | null\n}\n\nexport type YearDepreciation = { fiscalYear: number; expense: number; accumulated: number; bookValue: number }\n\n/** Whether the asset is on the balance sheet at the end of the year: acquired by then, not yet disposed of or scrapped. */\nexport function heldAtYearEnd(asset: Pick<Depreciable, 'acquiredOn' | 'status' | 'disposedOn'>, fiscalYear: number): boolean {\n const end = `${fiscalYear}-12-31`\n if (asset.acquiredOn > end) return false\n return !(asset.status && asset.status !== AssetStatus.IN_USE && asset.disposedOn && asset.disposedOn <= end)\n}\n\n/**\n * The depreciation of an asset for a fiscal year (January to December) - computed, never stored (decision 4).\n *\n * Month by month from the month it starts, through the month it is disposed of. Straight line spreads cost less residual\n * value over the useful life; declining balance takes the rate of the book value each year, the first and the last year\n * in proportion to their months, and never below the residual value. The useful life and the rate are what the books\n * use - this neither looks them up nor checks them against the tax law.\n */\nexport function depreciationOf(asset: Depreciable, fiscalYear: number): YearDepreciation {\n const cost = Number(asset.cost) || 0\n const residual = Math.min(Number(asset.residualValue) || 0, cost)\n const base = cost - residual\n const accumulatedAt = (year: number): number => {\n const start = monthOf(asset.depreciationStartOn || asset.acquiredOn)\n const disposed = asset.status && asset.status !== AssetStatus.IN_USE && asset.disposedOn ? monthOf(asset.disposedOn) : Infinity\n const last = Math.min(year * 12 + 11, disposed)\n if (last < start || base <= 0) return 0\n if (asset.method === DepreciationMethod.STRAIGHT_LINE) {\n const life = Math.round((Number(asset.usefulLifeYears) || 0) * 12)\n if (life <= 0) return 0\n const months = Math.min(last - start + 1, life)\n return months === life ? base : Math.round((base * months) / life)\n }\n if (asset.method === DepreciationMethod.DECLINING_BALANCE) {\n const rate = Number(asset.declineRate) || 0\n if (rate <= 0 || rate >= 1) return 0\n let book = cost\n for (let y = Math.floor(start / 12); y <= year; y++) {\n const months = Math.min(last, y * 12 + 11) - Math.max(start, y * 12) + 1\n if (months <= 0) continue\n book = Math.max(residual, book - Math.round((book * rate * months) / 12))\n }\n return cost - book\n }\n return 0\n }\n const accumulated = accumulatedAt(fiscalYear)\n const before = accumulatedAt(fiscalYear - 1)\n return { fiscalYear, expense: accumulated - before, accumulated, bookValue: cost - accumulated }\n}\n\n/** A line of the filed balance sheet, as accounting keeps it. */\nexport type StatementLine = { code: string; name: string; amount: number; contra?: boolean; rank: number }\n\nexport type ReconciliationRow = {\n code: string\n name: string\n assets: number\n registerCost: number\n registerAccumulated: number\n statementCost: number | null\n statementAccumulated: number | null\n}\n\n/**\n * The register beside the filed balance sheet, line by line (decision 5). A line's accumulated depreciation is the contra\n * line of the next code (122 machinery, 123 its accumulated depreciation) - the filed order can put it elsewhere. The lines are the kinds' own and whatever an asset names; a line the books carry and the register\n * does not is shown too - that is the difference to look at. Nothing is changed: a difference is the accountant's to\n * explain.\n */\nexport function reconcile(\n assets: (Depreciable & { statementCode?: string | null; kind: AssetKind | string })[],\n lines: StatementLine[] | null,\n fiscalYear: number\n): ReconciliationRow[] {\n const ordered = [...(lines ?? [])].sort((a, b) => a.rank - b.rank)\n const lineOf = (code: string) => ordered.findIndex(one => one.code === code && !one.contra)\n const codes = new Set<string>(Object.values(DEFAULT_STATEMENT_CODE).filter((code): code is string => !!code && lineOf(code) >= 0 && !!ordered[lineOf(code)].amount))\n const held = assets.filter(one => heldAtYearEnd(one, fiscalYear))\n for (const asset of held) {\n const code = asset.statementCode || DEFAULT_STATEMENT_CODE[asset.kind as AssetKind]\n if (code) codes.add(code)\n }\n return [...codes]\n .map(code => {\n const at = lineOf(code)\n const line = at >= 0 ? ordered[at] : undefined\n const contraCode = String(Number(code) + 1).padStart(code.length, '0')\n const next = ordered.find(one => one.contra && one.code === contraCode)\n const mine = held.filter(one => (one.statementCode || DEFAULT_STATEMENT_CODE[one.kind as AssetKind]) === code)\n return {\n code,\n name: line?.name ?? '',\n assets: mine.length,\n registerCost: mine.reduce((sum, one) => sum + (Number(one.cost) || 0), 0),\n registerAccumulated: mine.reduce((sum, one) => sum + depreciationOf(one, fiscalYear).accumulated, 0),\n statementCost: lines ? Number(line?.amount ?? 0) : null,\n statementAccumulated: lines ? Number(next?.amount ?? 0) : null\n }\n })\n .sort((a, b) => a.code.localeCompare(b.code))\n}\n\n/** Whether a row of the reconciliation differs - the register and the books do not say the same. */\nexport const differs = (row: ReconciliationRow) =>\n row.statementCost !== null && (Math.round(row.registerCost) !== Math.round(row.statementCost) || Math.round(row.registerAccumulated) !== Math.round(row.statementAccumulated ?? 0))\n"]}
1
+ {"version":3,"file":"asset-rules.js","sourceRoot":"","sources":["../../../server/service/asset/asset-rules.ts"],"names":[],"mappings":"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","sourcesContent":["import { registerEnumType } from 'type-graphql'\n\n/*\n * The asset register's rules (ADR-0175 decisions 3-5) - apart from the entity, so the screens' words and the tests read\n * them without a type-graphql class. Pure.\n */\n\nexport enum AssetKind {\n LAND = 'LAND',\n BUILDING = 'BUILDING',\n MACHINERY = 'MACHINERY',\n VEHICLE = 'VEHICLE',\n FURNITURE = 'FURNITURE',\n FACILITY = 'FACILITY',\n DEVELOPMENT_COST = 'DEVELOPMENT_COST',\n SOFTWARE = 'SOFTWARE',\n OTHER_INTANGIBLE = 'OTHER_INTANGIBLE'\n}\nregisterEnumType(AssetKind, { name: 'AssetKind', description: 'What an asset is - land, a building, machinery, a vehicle, furniture, a facility, development cost, software or another intangible' })\n\nexport enum AssetStatus {\n IN_USE = 'IN_USE',\n DISPOSED = 'DISPOSED',\n SCRAPPED = 'SCRAPPED'\n}\nregisterEnumType(AssetStatus, { name: 'AssetStatus', description: 'Whether an asset is in use, disposed of (sold) or scrapped' })\n\nexport enum DepreciationMethod {\n STRAIGHT_LINE = 'STRAIGHT_LINE',\n DECLINING_BALANCE = 'DECLINING_BALANCE',\n NONE = 'NONE'\n}\nregisterEnumType(DepreciationMethod, { name: 'DepreciationMethod', description: 'How an asset is depreciated - straight line, declining balance, or not at all (land)' })\n\n/**\n * The line of the standard balance sheet (표준재무제표) each kind is filed under, as accounting reads it\n * (`FinancialStatementLine.code`). An asset may name another; a kind without one names its own.\n */\nexport const DEFAULT_STATEMENT_CODE: Record<AssetKind, string | null> = {\n [AssetKind.LAND]: '111',\n [AssetKind.BUILDING]: '114',\n [AssetKind.MACHINERY]: '122',\n [AssetKind.VEHICLE]: '134',\n [AssetKind.FURNITURE]: '149',\n [AssetKind.FACILITY]: '149',\n [AssetKind.DEVELOPMENT_COST]: '184',\n [AssetKind.SOFTWARE]: '186',\n [AssetKind.OTHER_INTANGIBLE]: null\n}\n\n/** Land is not depreciated; everything else straight line unless written. */\nexport const defaultMethodOf = (kind: AssetKind | string) => (kind === AssetKind.LAND ? DepreciationMethod.NONE : DepreciationMethod.STRAIGHT_LINE)\n\nexport const DATE = /^\\d{4}-\\d{2}-\\d{2}$/\n\nconst monthOf = (date: string) => Number(date.slice(0, 4)) * 12 + Number(date.slice(5, 7)) - 1\n\n/** What depreciation reads of an asset. */\nexport type Depreciable = {\n cost: number\n /** False for an item only looked after - bought as an expense, so nothing to depreciate (ADR-0175 amendment 2). */\n capitalized?: boolean | null\n residualValue?: number | null\n method: DepreciationMethod | string\n usefulLifeYears?: number | null\n declineRate?: number | null\n acquiredOn: string\n depreciationStartOn?: string | null\n status?: AssetStatus | string\n disposedOn?: string | null\n}\n\nexport type YearDepreciation = { fiscalYear: number; expense: number; accumulated: number; bookValue: number }\n\n/** Whether the asset is on the balance sheet at the end of the year: acquired by then, not yet disposed of or scrapped. */\nexport function heldAtYearEnd(asset: Pick<Depreciable, 'acquiredOn' | 'status' | 'disposedOn'>, fiscalYear: number): boolean {\n const end = `${fiscalYear}-12-31`\n if (asset.acquiredOn > end) return false\n return !(asset.status && asset.status !== AssetStatus.IN_USE && asset.disposedOn && asset.disposedOn <= end)\n}\n\n/**\n * The depreciation of an asset for a fiscal year (January to December) - computed, never stored (decision 4).\n *\n * Month by month from the month it starts, through the month it is disposed of. Straight line spreads cost less residual\n * value over the useful life; declining balance takes the rate of the book value each year, the first and the last year\n * in proportion to their months, and never below the residual value. The useful life and the rate are what the books\n * use - this neither looks them up nor checks them against the tax law.\n */\nexport function depreciationOf(asset: Depreciable, fiscalYear: number): YearDepreciation {\n const cost = Number(asset.cost) || 0\n if (asset.capitalized === false) return { fiscalYear, expense: 0, accumulated: 0, bookValue: cost }\n const residual = Math.min(Number(asset.residualValue) || 0, cost)\n const base = cost - residual\n const accumulatedAt = (year: number): number => {\n const start = monthOf(asset.depreciationStartOn || asset.acquiredOn)\n const disposed = asset.status && asset.status !== AssetStatus.IN_USE && asset.disposedOn ? monthOf(asset.disposedOn) : Infinity\n const last = Math.min(year * 12 + 11, disposed)\n if (last < start || base <= 0) return 0\n if (asset.method === DepreciationMethod.STRAIGHT_LINE) {\n const life = Math.round((Number(asset.usefulLifeYears) || 0) * 12)\n if (life <= 0) return 0\n const months = Math.min(last - start + 1, life)\n return months === life ? base : Math.round((base * months) / life)\n }\n if (asset.method === DepreciationMethod.DECLINING_BALANCE) {\n const rate = Number(asset.declineRate) || 0\n if (rate <= 0 || rate >= 1) return 0\n let book = cost\n for (let y = Math.floor(start / 12); y <= year; y++) {\n const months = Math.min(last, y * 12 + 11) - Math.max(start, y * 12) + 1\n if (months <= 0) continue\n book = Math.max(residual, book - Math.round((book * rate * months) / 12))\n }\n return cost - book\n }\n return 0\n }\n const accumulated = accumulatedAt(fiscalYear)\n const before = accumulatedAt(fiscalYear - 1)\n return { fiscalYear, expense: accumulated - before, accumulated, bookValue: cost - accumulated }\n}\n\n/** A line of the filed balance sheet, as accounting keeps it. */\nexport type StatementLine = { code: string; name: string; amount: number; contra?: boolean; rank: number }\n\nexport type ReconciliationRow = {\n code: string\n name: string\n assets: number\n registerCost: number\n registerAccumulated: number\n statementCost: number | null\n statementAccumulated: number | null\n}\n\n/**\n * The register beside the filed balance sheet, line by line (decision 5). A line's accumulated depreciation is the contra\n * line of the next code (122 machinery, 123 its accumulated depreciation) - the filed order can put it elsewhere. The lines are the kinds' own and whatever an asset names; a line the books carry and the register\n * does not is shown too - that is the difference to look at. Nothing is changed: a difference is the accountant's to\n * explain.\n */\nexport function reconcile(\n assets: (Depreciable & { statementCode?: string | null; kind: AssetKind | string })[],\n lines: StatementLine[] | null,\n fiscalYear: number\n): ReconciliationRow[] {\n const ordered = [...(lines ?? [])].sort((a, b) => a.rank - b.rank)\n const lineOf = (code: string) => ordered.findIndex(one => one.code === code && !one.contra)\n const codes = new Set<string>(Object.values(DEFAULT_STATEMENT_CODE).filter((code): code is string => !!code && lineOf(code) >= 0 && !!ordered[lineOf(code)].amount))\n /* An item only looked after is no asset of the books (ADR-0175 amendment 2). */\n const held = assets.filter(one => one.capitalized !== false && heldAtYearEnd(one, fiscalYear))\n for (const asset of held) {\n const code = asset.statementCode || DEFAULT_STATEMENT_CODE[asset.kind as AssetKind]\n if (code) codes.add(code)\n }\n return [...codes]\n .map(code => {\n const at = lineOf(code)\n const line = at >= 0 ? ordered[at] : undefined\n const contraCode = String(Number(code) + 1).padStart(code.length, '0')\n const next = ordered.find(one => one.contra && one.code === contraCode)\n const mine = held.filter(one => (one.statementCode || DEFAULT_STATEMENT_CODE[one.kind as AssetKind]) === code)\n return {\n code,\n name: line?.name ?? '',\n assets: mine.length,\n registerCost: mine.reduce((sum, one) => sum + (Number(one.cost) || 0), 0),\n registerAccumulated: mine.reduce((sum, one) => sum + depreciationOf(one, fiscalYear).accumulated, 0),\n statementCost: lines ? Number(line?.amount ?? 0) : null,\n statementAccumulated: lines ? Number(next?.amount ?? 0) : null\n }\n })\n .sort((a, b) => a.code.localeCompare(b.code))\n}\n\n/** Whether a row of the reconciliation differs - the register and the books do not say the same. */\nexport const differs = (row: ReconciliationRow) =>\n row.statementCost !== null && (Math.round(row.registerCost) !== Math.round(row.statementCost) || Math.round(row.registerAccumulated) !== Math.round(row.statementAccumulated ?? 0))\n"]}
@@ -3,7 +3,7 @@ import { EntityManager } from 'typeorm';
3
3
  import { Patch } from '../patches';
4
4
  import { Asset } from './asset';
5
5
  import { ReconciliationRow } from './asset-rules';
6
- /** Apply the register grid's rows. */
6
+ /** Apply the register grid's rows. A serial number is one live asset's (ADR-0175 amendment 2). */
7
7
  export declare function saveAssets(tx: EntityManager, domain: Domain, user: any, patches: Patch[]): Promise<Asset[]>;
8
8
  /** The filed balance sheet's lines of a year - null when none is filed. */
9
9
  export declare function balanceSheetLines(tx: EntityManager, domain: Domain, fiscalYear: number): Promise<{
@@ -4,11 +4,13 @@ exports.saveAssets = saveAssets;
4
4
  exports.balanceSheetLines = balanceSheetLines;
5
5
  exports.assetReconciliation = assetReconciliation;
6
6
  const accounting_1 = require("@things-factory/accounting");
7
+ const organization_1 = require("@things-factory/organization");
7
8
  const shell_1 = require("@things-factory/shell");
9
+ const biz_base_1 = require("@things-factory/biz-base");
8
10
  const patches_1 = require("../patches");
9
11
  const asset_1 = require("./asset");
10
12
  const asset_rules_1 = require("./asset-rules");
11
- const TEXT = ['statementCode', 'location', 'keeper', 'source', 'project', 'description'];
13
+ const TEXT = ['statementCode', 'serialNo', 'location', 'source', 'project', 'description'];
12
14
  /** A patch as the row it writes, refused when the asset would not make sense (decisions 3-4). */
13
15
  function rowOf(patch, old) {
14
16
  const row = {};
@@ -32,9 +34,14 @@ function rowOf(patch, old) {
32
34
  const cost = row.cost ?? old.cost;
33
35
  if ((row.residualValue ?? old?.residualValue ?? 0) > cost)
34
36
  throw new shell_1.Refusal('asset-residual-above-cost', {}, 'The residual value is more than the cost');
35
- /* A changed kind takes its own method only when the method was the old kind's own. */
37
+ if ((0, patches_1.touched)(patch, 'capitalized', old))
38
+ row.capitalized = patch.capitalized !== false;
39
+ const capitalized = row.capitalized ?? old?.capitalized ?? true;
40
+ /* A changed kind takes its own method only when the method was the old kind's own; an item only looked after is not depreciated. */
36
41
  if (patch.method)
37
42
  row.method = patch.method;
43
+ else if (!capitalized && (!old || old.capitalized !== false))
44
+ row.method = asset_rules_1.DepreciationMethod.NONE;
38
45
  else if (!old)
39
46
  row.method = (0, asset_rules_1.defaultMethodOf)(kind);
40
47
  else if (patch.kind !== undefined && old.method === (0, asset_rules_1.defaultMethodOf)(old.kind))
@@ -64,9 +71,25 @@ function rowOf(patch, old) {
64
71
  throw new shell_1.Refusal('asset-disposed-before-acquired', {}, 'It was disposed of before it was acquired');
65
72
  return row;
66
73
  }
67
- /** Apply the register grid's rows. */
68
- function saveAssets(tx, domain, user, patches) {
69
- return (0, patches_1.applyPatches)(tx, asset_1.Asset, domain, user, patches, rowOf, 'asset-not-found');
74
+ /** Who looks after it: an employee of the domain, or no one. */
75
+ async function keeperOf(tx, domain, id) {
76
+ if (!id)
77
+ return null;
78
+ const keeper = await tx.getRepository(organization_1.Employee).findOne({ where: { domain: { id: domain.id }, id } });
79
+ if (!keeper)
80
+ throw new shell_1.Refusal('asset-keeper-not-found', {}, 'The keeper is no employee of this domain');
81
+ return keeper;
82
+ }
83
+ /** Apply the register grid's rows. A serial number is one live asset's (ADR-0175 amendment 2). */
84
+ async function saveAssets(tx, domain, user, patches) {
85
+ const serials = patches.filter(one => one.cuFlag !== '-' && one.serialNo !== undefined);
86
+ if (serials.length) {
87
+ const existing = await tx.getRepository(asset_1.Asset).find({ where: { domain: { id: domain.id } }, select: ['id', 'name', 'serialNo'] });
88
+ const clash = (0, biz_base_1.keyClash)(existing.map(one => ({ id: one.id, label: one.name, key: one.serialNo })), serials.map(one => ({ id: one.cuFlag === '+' ? undefined : one.id ?? undefined, label: one.name, key: (0, patches_1.textOf)(one.serialNo) })), patches.filter(one => one.cuFlag === '-' && one.id).map(one => one.id));
89
+ if (clash)
90
+ throw new shell_1.Refusal('asset-serial-clash', clash, `serial number ${clash.number} is already '${clash.existing}'`);
91
+ }
92
+ return (0, patches_1.applyPatches)(tx, asset_1.Asset, domain, user, patches, async (patch, old) => ({ ...rowOf(patch, old), ...((0, patches_1.touched)(patch, 'keeperId', old) ? { keeper: await keeperOf(tx, domain, patch.keeperId) } : {}) }), 'asset-not-found');
70
93
  }
71
94
  /** The filed balance sheet's lines of a year - null when none is filed. */
72
95
  async function balanceSheetLines(tx, domain, fiscalYear) {
@@ -1 +1 @@
1
- {"version":3,"file":"asset-service.js","sourceRoot":"","sources":["../../../server/service/asset/asset-service.ts"],"names":[],"mappings":"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","sourcesContent":["import { FinancialStatement, FinancialStatementKind, FinancialStatementLine } from '@things-factory/accounting'\nimport { Domain, Refusal } from '@things-factory/shell'\nimport { EntityManager } from 'typeorm'\n\nimport { amountOf, applyPatches, dayOf, Patch, textOf, touched } from '../patches'\nimport { Asset } from './asset'\nimport { AssetKind, AssetStatus, defaultMethodOf, DepreciationMethod, differs, reconcile, ReconciliationRow } from './asset-rules'\n\nconst TEXT = ['statementCode', 'location', 'keeper', 'source', 'project', 'description'] as const\n\n/** A patch as the row it writes, refused when the asset would not make sense (decisions 3-4). */\nfunction rowOf(patch: Patch, old?: Asset): Partial<Asset> {\n const row: Record<string, any> = {}\n const name = touched(patch, 'name', old) ? textOf(patch.name) : old!.name\n if (!name) throw new Refusal('asset-name-required', {}, 'Name the asset')\n row.name = name\n const kind = (patch.kind ?? old?.kind) as AssetKind\n if (!kind || !Object.values(AssetKind).includes(kind)) throw new Refusal('asset-kind-required', {}, 'Say what kind of asset it is')\n row.kind = kind\n for (const field of TEXT) if (touched(patch, field, old)) row[field] = textOf(patch[field])\n const acquiredOn = touched(patch, 'acquiredOn', old) ? dayOf(patch.acquiredOn, 'asset-acquired-on-invalid', true) : old!.acquiredOn\n row.acquiredOn = acquiredOn\n if (touched(patch, 'cost', old)) row.cost = amountOf(patch.cost, 'asset-amount-invalid') ?? 0\n if (touched(patch, 'residualValue', old)) row.residualValue = amountOf(patch.residualValue, 'asset-amount-invalid') ?? 0\n const cost = row.cost ?? old!.cost\n if ((row.residualValue ?? old?.residualValue ?? 0) > cost) throw new Refusal('asset-residual-above-cost', {}, 'The residual value is more than the cost')\n\n /* A changed kind takes its own method only when the method was the old kind's own. */\n if (patch.method) row.method = patch.method\n else if (!old) row.method = defaultMethodOf(kind)\n else if (patch.kind !== undefined && old.method === defaultMethodOf(old.kind)) row.method = defaultMethodOf(kind)\n const method = row.method ?? old!.method\n if (touched(patch, 'usefulLifeYears', old)) row.usefulLifeYears = amountOf(patch.usefulLifeYears, 'asset-useful-life-invalid')\n if (touched(patch, 'declineRate', old)) row.declineRate = amountOf(patch.declineRate, 'asset-decline-rate-invalid')\n const life = row.usefulLifeYears !== undefined ? row.usefulLifeYears : old?.usefulLifeYears\n const rate = row.declineRate !== undefined ? row.declineRate : old?.declineRate\n if (method === DepreciationMethod.STRAIGHT_LINE && !(Number(life) > 0))\n throw new Refusal('asset-useful-life-required', {}, 'Give the useful life in years for straight-line depreciation')\n if (method === DepreciationMethod.DECLINING_BALANCE && !(Number(rate) > 0 && Number(rate) < 1))\n throw new Refusal('asset-decline-rate-required', {}, 'Give the yearly rate (between 0 and 1) for declining-balance depreciation')\n if (touched(patch, 'depreciationStartOn', old)) row.depreciationStartOn = dayOf(patch.depreciationStartOn, 'asset-start-on-invalid')\n\n if (touched(patch, 'status', old)) row.status = patch.status ?? AssetStatus.IN_USE\n if (touched(patch, 'disposedOn', old)) row.disposedOn = dayOf(patch.disposedOn, 'asset-disposed-on-invalid')\n const status = row.status ?? old!.status\n const disposedOn = row.disposedOn !== undefined ? row.disposedOn : old?.disposedOn\n if (status !== AssetStatus.IN_USE && !disposedOn) throw new Refusal('asset-disposed-on-required', {}, 'Give the day it was disposed of or scrapped')\n if (disposedOn && disposedOn < acquiredOn!) throw new Refusal('asset-disposed-before-acquired', {}, 'It was disposed of before it was acquired')\n return row\n}\n\n/** Apply the register grid's rows. */\nexport function saveAssets(tx: EntityManager, domain: Domain, user: any, patches: Patch[]) {\n return applyPatches(tx, Asset, domain, user, patches, rowOf, 'asset-not-found')\n}\n\n/** The filed balance sheet's lines of a year - null when none is filed. */\nexport async function balanceSheetLines(tx: EntityManager, domain: Domain, fiscalYear: number) {\n const statement = await tx.getRepository(FinancialStatement).findOne({ where: { domain: { id: domain.id }, fiscalYear, kind: FinancialStatementKind.BALANCE_SHEET } as any })\n if (!statement) return null\n const lines = await tx.getRepository(FinancialStatementLine).find({ where: { statement: { id: statement.id } } as any })\n return lines.map(line => ({ code: line.code, name: line.name, amount: Number(line.amount), contra: !!line.contra, rank: line.rank }))\n}\n\n/** The register beside the filed balance sheet of a year (decision 5). */\nexport async function assetReconciliation(tx: EntityManager, domain: Domain, fiscalYear: number): Promise<{ fiscalYear: number; filed: boolean; rows: (ReconciliationRow & { differs: boolean })[] }> {\n const [assets, lines] = await Promise.all([tx.getRepository(Asset).find({ where: { domain: { id: domain.id } } as any }), balanceSheetLines(tx, domain, fiscalYear)])\n return { fiscalYear, filed: !!lines, rows: reconcile(assets as any, lines, fiscalYear).map(row => ({ ...row, differs: differs(row) })) }\n}\n"]}
1
+ {"version":3,"file":"asset-service.js","sourceRoot":"","sources":["../../../server/service/asset/asset-service.ts"],"names":[],"mappings":";;AAiEA,gCAoBC;AAGD,8CAKC;AAGD,kDAGC;AAnGD,2DAA+G;AAC/G,+DAAuD;AACvD,iDAAuD;AACvD,uDAAmD;AAGnD,wCAAkF;AAClF,mCAA+B;AAC/B,+CAAkI;AAElI,MAAM,IAAI,GAAG,CAAC,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,aAAa,CAAU,CAAA;AAEnG,iGAAiG;AACjG,SAAS,KAAK,CAAC,KAAY,EAAE,GAAW;IACtC,MAAM,GAAG,GAAwB,EAAE,CAAA;IACnC,MAAM,IAAI,GAAG,IAAA,iBAAO,EAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAA,gBAAM,EAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAI,CAAC,IAAI,CAAA;IACzE,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,eAAO,CAAC,qBAAqB,EAAE,EAAE,EAAE,gBAAgB,CAAC,CAAA;IACzE,GAAG,CAAC,IAAI,GAAG,IAAI,CAAA;IACf,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,GAAG,EAAE,IAAI,CAAc,CAAA;IACnD,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,uBAAS,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,eAAO,CAAC,qBAAqB,EAAE,EAAE,EAAE,8BAA8B,CAAC,CAAA;IACnI,GAAG,CAAC,IAAI,GAAG,IAAI,CAAA;IACf,KAAK,MAAM,KAAK,IAAI,IAAI;QAAE,IAAI,IAAA,iBAAO,EAAC,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC;YAAE,GAAG,CAAC,KAAK,CAAC,GAAG,IAAA,gBAAM,EAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAA;IAC3F,MAAM,UAAU,GAAG,IAAA,iBAAO,EAAC,KAAK,EAAE,YAAY,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAA,eAAK,EAAC,KAAK,CAAC,UAAU,EAAE,2BAA2B,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,GAAI,CAAC,UAAU,CAAA;IACnI,GAAG,CAAC,UAAU,GAAG,UAAU,CAAA;IAC3B,IAAI,IAAA,iBAAO,EAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC;QAAE,GAAG,CAAC,IAAI,GAAG,IAAA,kBAAQ,EAAC,KAAK,CAAC,IAAI,EAAE,sBAAsB,CAAC,IAAI,CAAC,CAAA;IAC7F,IAAI,IAAA,iBAAO,EAAC,KAAK,EAAE,eAAe,EAAE,GAAG,CAAC;QAAE,GAAG,CAAC,aAAa,GAAG,IAAA,kBAAQ,EAAC,KAAK,CAAC,aAAa,EAAE,sBAAsB,CAAC,IAAI,CAAC,CAAA;IACxH,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,IAAI,GAAI,CAAC,IAAI,CAAA;IAClC,IAAI,CAAC,GAAG,CAAC,aAAa,IAAI,GAAG,EAAE,aAAa,IAAI,CAAC,CAAC,GAAG,IAAI;QAAE,MAAM,IAAI,eAAO,CAAC,2BAA2B,EAAE,EAAE,EAAE,0CAA0C,CAAC,CAAA;IAEzJ,IAAI,IAAA,iBAAO,EAAC,KAAK,EAAE,aAAa,EAAE,GAAG,CAAC;QAAE,GAAG,CAAC,WAAW,GAAG,KAAK,CAAC,WAAW,KAAK,KAAK,CAAA;IACrF,MAAM,WAAW,GAAG,GAAG,CAAC,WAAW,IAAI,GAAG,EAAE,WAAW,IAAI,IAAI,CAAA;IAC/D,oIAAoI;IACpI,IAAI,KAAK,CAAC,MAAM;QAAE,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAA;SACtC,IAAI,CAAC,WAAW,IAAI,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,WAAW,KAAK,KAAK,CAAC;QAAE,GAAG,CAAC,MAAM,GAAG,gCAAkB,CAAC,IAAI,CAAA;SAC7F,IAAI,CAAC,GAAG;QAAE,GAAG,CAAC,MAAM,GAAG,IAAA,6BAAe,EAAC,IAAI,CAAC,CAAA;SAC5C,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,GAAG,CAAC,MAAM,KAAK,IAAA,6BAAe,EAAC,GAAG,CAAC,IAAI,CAAC;QAAE,GAAG,CAAC,MAAM,GAAG,IAAA,6BAAe,EAAC,IAAI,CAAC,CAAA;IACjH,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,GAAI,CAAC,MAAM,CAAA;IACxC,IAAI,IAAA,iBAAO,EAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,CAAC;QAAE,GAAG,CAAC,eAAe,GAAG,IAAA,kBAAQ,EAAC,KAAK,CAAC,eAAe,EAAE,2BAA2B,CAAC,CAAA;IAC9H,IAAI,IAAA,iBAAO,EAAC,KAAK,EAAE,aAAa,EAAE,GAAG,CAAC;QAAE,GAAG,CAAC,WAAW,GAAG,IAAA,kBAAQ,EAAC,KAAK,CAAC,WAAW,EAAE,4BAA4B,CAAC,CAAA;IACnH,MAAM,IAAI,GAAG,GAAG,CAAC,eAAe,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,GAAG,EAAE,eAAe,CAAA;IAC3F,MAAM,IAAI,GAAG,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,EAAE,WAAW,CAAA;IAC/E,IAAI,MAAM,KAAK,gCAAkB,CAAC,aAAa,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpE,MAAM,IAAI,eAAO,CAAC,4BAA4B,EAAE,EAAE,EAAE,8DAA8D,CAAC,CAAA;IACrH,IAAI,MAAM,KAAK,gCAAkB,CAAC,iBAAiB,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC5F,MAAM,IAAI,eAAO,CAAC,6BAA6B,EAAE,EAAE,EAAE,2EAA2E,CAAC,CAAA;IACnI,IAAI,IAAA,iBAAO,EAAC,KAAK,EAAE,qBAAqB,EAAE,GAAG,CAAC;QAAE,GAAG,CAAC,mBAAmB,GAAG,IAAA,eAAK,EAAC,KAAK,CAAC,mBAAmB,EAAE,wBAAwB,CAAC,CAAA;IAEpI,IAAI,IAAA,iBAAO,EAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,CAAC;QAAE,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,yBAAW,CAAC,MAAM,CAAA;IAClF,IAAI,IAAA,iBAAO,EAAC,KAAK,EAAE,YAAY,EAAE,GAAG,CAAC;QAAE,GAAG,CAAC,UAAU,GAAG,IAAA,eAAK,EAAC,KAAK,CAAC,UAAU,EAAE,2BAA2B,CAAC,CAAA;IAC5G,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,GAAI,CAAC,MAAM,CAAA;IACxC,MAAM,UAAU,GAAG,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,EAAE,UAAU,CAAA;IAClF,IAAI,MAAM,KAAK,yBAAW,CAAC,MAAM,IAAI,CAAC,UAAU;QAAE,MAAM,IAAI,eAAO,CAAC,4BAA4B,EAAE,EAAE,EAAE,6CAA6C,CAAC,CAAA;IACpJ,IAAI,UAAU,IAAI,UAAU,GAAG,UAAW;QAAE,MAAM,IAAI,eAAO,CAAC,gCAAgC,EAAE,EAAE,EAAE,2CAA2C,CAAC,CAAA;IAChJ,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,gEAAgE;AAChE,KAAK,UAAU,QAAQ,CAAC,EAAiB,EAAE,MAAc,EAAE,EAA6B;IACtF,IAAI,CAAC,EAAE;QAAE,OAAO,IAAI,CAAA;IACpB,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,uBAAQ,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAS,EAAE,CAAC,CAAA;IAC5G,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,eAAO,CAAC,wBAAwB,EAAE,EAAE,EAAE,0CAA0C,CAAC,CAAA;IACxG,OAAO,MAAM,CAAA;AACf,CAAC;AAED,kGAAkG;AAC3F,KAAK,UAAU,UAAU,CAAC,EAAiB,EAAE,MAAc,EAAE,IAAS,EAAE,OAAgB;IAC7F,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAA;IACvF,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,aAAK,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAS,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAQ,EAAE,CAAC,CAAA;QAC/I,MAAM,KAAK,GAAG,IAAA,mBAAQ,EACpB,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,EACzE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,SAAS,EAAE,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,IAAA,gBAAM,EAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,EAC9H,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAG,CAAC,CACxE,CAAA;QACD,IAAI,KAAK;YAAE,MAAM,IAAI,eAAO,CAAC,oBAAoB,EAAE,KAAK,EAAE,iBAAiB,KAAK,CAAC,MAAM,gBAAgB,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAA;IAC3H,CAAC;IACD,OAAO,IAAA,sBAAY,EACjB,EAAE,EACF,aAAK,EACL,MAAM,EACN,IAAI,EACJ,OAAO,EACP,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,IAAA,iBAAO,EAAC,KAAK,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EACpJ,iBAAiB,CAClB,CAAA;AACH,CAAC;AAED,2EAA2E;AACpE,KAAK,UAAU,iBAAiB,CAAC,EAAiB,EAAE,MAAc,EAAE,UAAkB;IAC3F,MAAM,SAAS,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,+BAAkB,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,mCAAsB,CAAC,aAAa,EAAS,EAAE,CAAC,CAAA;IAC7K,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAA;IAC3B,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,mCAAsB,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,EAAE,SAAS,CAAC,EAAE,EAAE,EAAS,EAAE,CAAC,CAAA;IACxH,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;AACvI,CAAC;AAED,0EAA0E;AACnE,KAAK,UAAU,mBAAmB,CAAC,EAAiB,EAAE,MAAc,EAAE,UAAkB;IAC7F,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,aAAK,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAS,EAAE,CAAC,EAAE,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,CAAA;IACrK,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,IAAA,uBAAS,EAAC,MAAa,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,OAAO,EAAE,IAAA,qBAAO,EAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAA;AAC1I,CAAC","sourcesContent":["import { FinancialStatement, FinancialStatementKind, FinancialStatementLine } from '@things-factory/accounting'\nimport { Employee } from '@things-factory/organization'\nimport { Domain, Refusal } from '@things-factory/shell'\nimport { keyClash } from '@things-factory/biz-base'\nimport { EntityManager } from 'typeorm'\n\nimport { amountOf, applyPatches, dayOf, Patch, textOf, touched } from '../patches'\nimport { Asset } from './asset'\nimport { AssetKind, AssetStatus, defaultMethodOf, DepreciationMethod, differs, reconcile, ReconciliationRow } from './asset-rules'\n\nconst TEXT = ['statementCode', 'serialNo', 'location', 'source', 'project', 'description'] as const\n\n/** A patch as the row it writes, refused when the asset would not make sense (decisions 3-4). */\nfunction rowOf(patch: Patch, old?: Asset): Partial<Asset> {\n const row: Record<string, any> = {}\n const name = touched(patch, 'name', old) ? textOf(patch.name) : old!.name\n if (!name) throw new Refusal('asset-name-required', {}, 'Name the asset')\n row.name = name\n const kind = (patch.kind ?? old?.kind) as AssetKind\n if (!kind || !Object.values(AssetKind).includes(kind)) throw new Refusal('asset-kind-required', {}, 'Say what kind of asset it is')\n row.kind = kind\n for (const field of TEXT) if (touched(patch, field, old)) row[field] = textOf(patch[field])\n const acquiredOn = touched(patch, 'acquiredOn', old) ? dayOf(patch.acquiredOn, 'asset-acquired-on-invalid', true) : old!.acquiredOn\n row.acquiredOn = acquiredOn\n if (touched(patch, 'cost', old)) row.cost = amountOf(patch.cost, 'asset-amount-invalid') ?? 0\n if (touched(patch, 'residualValue', old)) row.residualValue = amountOf(patch.residualValue, 'asset-amount-invalid') ?? 0\n const cost = row.cost ?? old!.cost\n if ((row.residualValue ?? old?.residualValue ?? 0) > cost) throw new Refusal('asset-residual-above-cost', {}, 'The residual value is more than the cost')\n\n if (touched(patch, 'capitalized', old)) row.capitalized = patch.capitalized !== false\n const capitalized = row.capitalized ?? old?.capitalized ?? true\n /* A changed kind takes its own method only when the method was the old kind's own; an item only looked after is not depreciated. */\n if (patch.method) row.method = patch.method\n else if (!capitalized && (!old || old.capitalized !== false)) row.method = DepreciationMethod.NONE\n else if (!old) row.method = defaultMethodOf(kind)\n else if (patch.kind !== undefined && old.method === defaultMethodOf(old.kind)) row.method = defaultMethodOf(kind)\n const method = row.method ?? old!.method\n if (touched(patch, 'usefulLifeYears', old)) row.usefulLifeYears = amountOf(patch.usefulLifeYears, 'asset-useful-life-invalid')\n if (touched(patch, 'declineRate', old)) row.declineRate = amountOf(patch.declineRate, 'asset-decline-rate-invalid')\n const life = row.usefulLifeYears !== undefined ? row.usefulLifeYears : old?.usefulLifeYears\n const rate = row.declineRate !== undefined ? row.declineRate : old?.declineRate\n if (method === DepreciationMethod.STRAIGHT_LINE && !(Number(life) > 0))\n throw new Refusal('asset-useful-life-required', {}, 'Give the useful life in years for straight-line depreciation')\n if (method === DepreciationMethod.DECLINING_BALANCE && !(Number(rate) > 0 && Number(rate) < 1))\n throw new Refusal('asset-decline-rate-required', {}, 'Give the yearly rate (between 0 and 1) for declining-balance depreciation')\n if (touched(patch, 'depreciationStartOn', old)) row.depreciationStartOn = dayOf(patch.depreciationStartOn, 'asset-start-on-invalid')\n\n if (touched(patch, 'status', old)) row.status = patch.status ?? AssetStatus.IN_USE\n if (touched(patch, 'disposedOn', old)) row.disposedOn = dayOf(patch.disposedOn, 'asset-disposed-on-invalid')\n const status = row.status ?? old!.status\n const disposedOn = row.disposedOn !== undefined ? row.disposedOn : old?.disposedOn\n if (status !== AssetStatus.IN_USE && !disposedOn) throw new Refusal('asset-disposed-on-required', {}, 'Give the day it was disposed of or scrapped')\n if (disposedOn && disposedOn < acquiredOn!) throw new Refusal('asset-disposed-before-acquired', {}, 'It was disposed of before it was acquired')\n return row\n}\n\n/** Who looks after it: an employee of the domain, or no one. */\nasync function keeperOf(tx: EntityManager, domain: Domain, id: string | null | undefined): Promise<Employee | null> {\n if (!id) return null\n const keeper = await tx.getRepository(Employee).findOne({ where: { domain: { id: domain.id }, id } as any })\n if (!keeper) throw new Refusal('asset-keeper-not-found', {}, 'The keeper is no employee of this domain')\n return keeper\n}\n\n/** Apply the register grid's rows. A serial number is one live asset's (ADR-0175 amendment 2). */\nexport async function saveAssets(tx: EntityManager, domain: Domain, user: any, patches: Patch[]) {\n const serials = patches.filter(one => one.cuFlag !== '-' && one.serialNo !== undefined)\n if (serials.length) {\n const existing = await tx.getRepository(Asset).find({ where: { domain: { id: domain.id } } as any, select: ['id', 'name', 'serialNo'] as any })\n const clash = keyClash(\n existing.map(one => ({ id: one.id, label: one.name, key: one.serialNo })),\n serials.map(one => ({ id: one.cuFlag === '+' ? undefined : one.id ?? undefined, label: one.name, key: textOf(one.serialNo) })),\n patches.filter(one => one.cuFlag === '-' && one.id).map(one => one.id!)\n )\n if (clash) throw new Refusal('asset-serial-clash', clash, `serial number ${clash.number} is already '${clash.existing}'`)\n }\n return applyPatches(\n tx,\n Asset,\n domain,\n user,\n patches,\n async (patch, old) => ({ ...rowOf(patch, old), ...(touched(patch, 'keeperId', old) ? { keeper: await keeperOf(tx, domain, patch.keeperId) } : {}) }),\n 'asset-not-found'\n )\n}\n\n/** The filed balance sheet's lines of a year - null when none is filed. */\nexport async function balanceSheetLines(tx: EntityManager, domain: Domain, fiscalYear: number) {\n const statement = await tx.getRepository(FinancialStatement).findOne({ where: { domain: { id: domain.id }, fiscalYear, kind: FinancialStatementKind.BALANCE_SHEET } as any })\n if (!statement) return null\n const lines = await tx.getRepository(FinancialStatementLine).find({ where: { statement: { id: statement.id } } as any })\n return lines.map(line => ({ code: line.code, name: line.name, amount: Number(line.amount), contra: !!line.contra, rank: line.rank }))\n}\n\n/** The register beside the filed balance sheet of a year (decision 5). */\nexport async function assetReconciliation(tx: EntityManager, domain: Domain, fiscalYear: number): Promise<{ fiscalYear: number; filed: boolean; rows: (ReconciliationRow & { differs: boolean })[] }> {\n const [assets, lines] = await Promise.all([tx.getRepository(Asset).find({ where: { domain: { id: domain.id } } as any }), balanceSheetLines(tx, domain, fiscalYear)])\n return { fiscalYear, filed: !!lines, rows: reconcile(assets as any, lines, fiscalYear).map(row => ({ ...row, differs: differs(row) })) }\n}\n"]}
@@ -7,6 +7,8 @@ export declare class AssetPatch {
7
7
  kind?: AssetKind;
8
8
  statementCode?: string;
9
9
  acquiredOn?: string;
10
+ serialNo?: string;
11
+ capitalized?: boolean;
10
12
  cost?: number;
11
13
  residualValue?: number;
12
14
  method?: DepreciationMethod;
@@ -16,7 +18,7 @@ export declare class AssetPatch {
16
18
  status?: AssetStatus;
17
19
  disposedOn?: string;
18
20
  location?: string;
19
- keeper?: string;
21
+ keeperId?: string;
20
22
  source?: string;
21
23
  project?: string;
22
24
  description?: string;
@@ -32,6 +32,14 @@ tslib_1.__decorate([
32
32
  (0, type_graphql_1.Field)({ nullable: true, description: 'The day it was acquired - YYYY-MM-DD' }),
33
33
  tslib_1.__metadata("design:type", String)
34
34
  ], AssetPatch.prototype, "acquiredOn", void 0);
35
+ tslib_1.__decorate([
36
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Its serial or control number' }),
37
+ tslib_1.__metadata("design:type", String)
38
+ ], AssetPatch.prototype, "serialNo", void 0);
39
+ tslib_1.__decorate([
40
+ (0, type_graphql_1.Field)({ nullable: true, description: 'An asset of the books; false for an item only looked after' }),
41
+ tslib_1.__metadata("design:type", Boolean)
42
+ ], AssetPatch.prototype, "capitalized", void 0);
35
43
  tslib_1.__decorate([
36
44
  (0, type_graphql_1.Field)(type => type_graphql_1.Float, { nullable: true, description: 'What it cost, in won' }),
37
45
  tslib_1.__metadata("design:type", Number)
@@ -69,9 +77,9 @@ tslib_1.__decorate([
69
77
  tslib_1.__metadata("design:type", String)
70
78
  ], AssetPatch.prototype, "location", void 0);
71
79
  tslib_1.__decorate([
72
- (0, type_graphql_1.Field)({ nullable: true, description: 'Who looks after it' }),
80
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Who looks after it - an employee id; empty for no one' }),
73
81
  tslib_1.__metadata("design:type", String)
74
- ], AssetPatch.prototype, "keeper", void 0);
82
+ ], AssetPatch.prototype, "keeperId", void 0);
75
83
  tslib_1.__decorate([
76
84
  (0, type_graphql_1.Field)({ nullable: true, description: 'What it was acquired by, in words' }),
77
85
  tslib_1.__metadata("design:type", String)
@@ -1 +1 @@
1
- {"version":3,"file":"asset-type.js","sourceRoot":"","sources":["../../../server/service/asset/asset-type.ts"],"names":[],"mappings":"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","sourcesContent":["import { Field, Float, ID, InputType, Int, ObjectType } from 'type-graphql'\n\nimport { Asset } from './asset'\nimport { AssetKind, AssetStatus, DepreciationMethod } from './asset-rules'\n\n@InputType({ description: 'A row of the asset register grid (cuFlag + for new, M for changed, - for deleted)' })\nexport class AssetPatch {\n @Field(type => ID, { nullable: true, description: 'The asset; empty for a new one' }) id?: string\n @Field({ nullable: true, description: 'Grid flag: + new, M changed, - deleted' }) cuFlag?: string\n @Field({ nullable: true, description: 'What the asset is called' }) name?: string\n @Field(type => AssetKind, { nullable: true, description: 'What kind of asset it is' }) kind?: AssetKind\n @Field({ nullable: true, description: 'The line of the filed balance sheet; the kind gives it when empty' }) statementCode?: string\n @Field({ nullable: true, description: 'The day it was acquired - YYYY-MM-DD' }) acquiredOn?: string\n @Field(type => Float, { nullable: true, description: 'What it cost, in won' }) cost?: number\n @Field(type => Float, { nullable: true, description: 'The value left at the end of its useful life, in won' }) residualValue?: number\n @Field(type => DepreciationMethod, { nullable: true, description: 'How it is depreciated; the kind gives it when empty' }) method?: DepreciationMethod\n @Field(type => Float, { nullable: true, description: 'Useful life in years' }) usefulLifeYears?: number\n @Field(type => Float, { nullable: true, description: 'Yearly rate of declining-balance depreciation' }) declineRate?: number\n @Field({ nullable: true, description: 'The day depreciation starts - YYYY-MM-DD' }) depreciationStartOn?: string\n @Field(type => AssetStatus, { nullable: true, description: 'In use, disposed of or scrapped' }) status?: AssetStatus\n @Field({ nullable: true, description: 'The day it was disposed of or scrapped - YYYY-MM-DD' }) disposedOn?: string\n @Field({ nullable: true, description: 'Where it is' }) location?: string\n @Field({ nullable: true, description: 'Who looks after it' }) keeper?: string\n @Field({ nullable: true, description: 'What it was acquired by, in words' }) source?: string\n @Field({ nullable: true, description: 'The development project it came from' }) project?: string\n @Field({ nullable: true, description: 'Notes' }) description?: string\n}\n\n@ObjectType({ description: 'A page of assets' })\nexport class AssetList {\n @Field(type => [Asset], { description: 'Assets on the page' }) items: Asset[]\n @Field(type => Int, { description: 'Number of assets matching the list parameters' }) total: number\n}\n\n@ObjectType({ description: \"An asset's depreciation for a fiscal year, computed from the register\" })\nexport class AssetYear {\n @Field(type => Int, { description: 'The fiscal year, January to December' }) fiscalYear: number\n @Field(type => Float, { description: 'Depreciation of the year' }) expense: number\n @Field(type => Float, { description: 'Accumulated depreciation at the end of the year' }) accumulated: number\n @Field(type => Float, { description: 'Cost less accumulated depreciation at the end of the year' }) bookValue: number\n}\n\n@ObjectType({ description: 'A line of the filed balance sheet beside the register' })\nexport class AssetReconciliationRow {\n @Field({ description: 'The line code of the standard balance sheet' }) code: string\n @Field({ description: 'The name the filed statement gives the line' }) name: string\n @Field(type => Int, { description: 'How many assets of the register are on the line at the end of the year' }) assets: number\n @Field(type => Float, { description: 'Their cost' }) registerCost: number\n @Field(type => Float, { description: 'Their accumulated depreciation, computed' }) registerAccumulated: number\n @Field(type => Float, { nullable: true, description: 'The amount the filed statement carries' }) statementCost?: number\n @Field(type => Float, { nullable: true, description: 'The accumulated depreciation the filed statement carries' }) statementAccumulated?: number\n @Field({ description: 'Whether the register and the filed statement differ' }) differs: boolean\n}\n\n@ObjectType({ description: 'The register beside the filed balance sheet of a fiscal year' })\nexport class AssetReconciliation {\n @Field(type => Int, { description: 'The fiscal year' }) fiscalYear: number\n @Field({ description: 'Whether a balance sheet is filed for the year' }) filed: boolean\n @Field(type => [AssetReconciliationRow], { description: 'Line by line' }) rows: AssetReconciliationRow[]\n}\n"]}
1
+ {"version":3,"file":"asset-type.js","sourceRoot":"","sources":["../../../server/service/asset/asset-type.ts"],"names":[],"mappings":"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","sourcesContent":["import { Field, Float, ID, InputType, Int, ObjectType } from 'type-graphql'\n\nimport { Asset } from './asset'\nimport { AssetKind, AssetStatus, DepreciationMethod } from './asset-rules'\n\n@InputType({ description: 'A row of the asset register grid (cuFlag + for new, M for changed, - for deleted)' })\nexport class AssetPatch {\n @Field(type => ID, { nullable: true, description: 'The asset; empty for a new one' }) id?: string\n @Field({ nullable: true, description: 'Grid flag: + new, M changed, - deleted' }) cuFlag?: string\n @Field({ nullable: true, description: 'What the asset is called' }) name?: string\n @Field(type => AssetKind, { nullable: true, description: 'What kind of asset it is' }) kind?: AssetKind\n @Field({ nullable: true, description: 'The line of the filed balance sheet; the kind gives it when empty' }) statementCode?: string\n @Field({ nullable: true, description: 'The day it was acquired - YYYY-MM-DD' }) acquiredOn?: string\n @Field({ nullable: true, description: 'Its serial or control number' }) serialNo?: string\n @Field({ nullable: true, description: 'An asset of the books; false for an item only looked after' }) capitalized?: boolean\n @Field(type => Float, { nullable: true, description: 'What it cost, in won' }) cost?: number\n @Field(type => Float, { nullable: true, description: 'The value left at the end of its useful life, in won' }) residualValue?: number\n @Field(type => DepreciationMethod, { nullable: true, description: 'How it is depreciated; the kind gives it when empty' }) method?: DepreciationMethod\n @Field(type => Float, { nullable: true, description: 'Useful life in years' }) usefulLifeYears?: number\n @Field(type => Float, { nullable: true, description: 'Yearly rate of declining-balance depreciation' }) declineRate?: number\n @Field({ nullable: true, description: 'The day depreciation starts - YYYY-MM-DD' }) depreciationStartOn?: string\n @Field(type => AssetStatus, { nullable: true, description: 'In use, disposed of or scrapped' }) status?: AssetStatus\n @Field({ nullable: true, description: 'The day it was disposed of or scrapped - YYYY-MM-DD' }) disposedOn?: string\n @Field({ nullable: true, description: 'Where it is' }) location?: string\n @Field({ nullable: true, description: 'Who looks after it - an employee id; empty for no one' }) keeperId?: string\n @Field({ nullable: true, description: 'What it was acquired by, in words' }) source?: string\n @Field({ nullable: true, description: 'The development project it came from' }) project?: string\n @Field({ nullable: true, description: 'Notes' }) description?: string\n}\n\n@ObjectType({ description: 'A page of assets' })\nexport class AssetList {\n @Field(type => [Asset], { description: 'Assets on the page' }) items: Asset[]\n @Field(type => Int, { description: 'Number of assets matching the list parameters' }) total: number\n}\n\n@ObjectType({ description: \"An asset's depreciation for a fiscal year, computed from the register\" })\nexport class AssetYear {\n @Field(type => Int, { description: 'The fiscal year, January to December' }) fiscalYear: number\n @Field(type => Float, { description: 'Depreciation of the year' }) expense: number\n @Field(type => Float, { description: 'Accumulated depreciation at the end of the year' }) accumulated: number\n @Field(type => Float, { description: 'Cost less accumulated depreciation at the end of the year' }) bookValue: number\n}\n\n@ObjectType({ description: 'A line of the filed balance sheet beside the register' })\nexport class AssetReconciliationRow {\n @Field({ description: 'The line code of the standard balance sheet' }) code: string\n @Field({ description: 'The name the filed statement gives the line' }) name: string\n @Field(type => Int, { description: 'How many assets of the register are on the line at the end of the year' }) assets: number\n @Field(type => Float, { description: 'Their cost' }) registerCost: number\n @Field(type => Float, { description: 'Their accumulated depreciation, computed' }) registerAccumulated: number\n @Field(type => Float, { nullable: true, description: 'The amount the filed statement carries' }) statementCost?: number\n @Field(type => Float, { nullable: true, description: 'The accumulated depreciation the filed statement carries' }) statementAccumulated?: number\n @Field({ description: 'Whether the register and the filed statement differ' }) differs: boolean\n}\n\n@ObjectType({ description: 'The register beside the filed balance sheet of a fiscal year' })\nexport class AssetReconciliation {\n @Field(type => Int, { description: 'The fiscal year' }) fiscalYear: number\n @Field({ description: 'Whether a balance sheet is filed for the year' }) filed: boolean\n @Field(type => [AssetReconciliationRow], { description: 'Line by line' }) rows: AssetReconciliationRow[]\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import { User } from '@things-factory/auth-base';
2
+ import { Employee } from '@things-factory/organization';
2
3
  import { Domain } from '@things-factory/shell';
3
4
  import { AssetKind, AssetStatus, DepreciationMethod } from './asset-rules';
4
5
  /**
@@ -14,6 +15,8 @@ export declare class Asset {
14
15
  kind: AssetKind;
15
16
  statementCode?: string;
16
17
  acquiredOn: string;
18
+ serialNo?: string;
19
+ capitalized: boolean;
17
20
  cost: number;
18
21
  residualValue: number;
19
22
  method: DepreciationMethod;
@@ -23,7 +26,8 @@ export declare class Asset {
23
26
  status: AssetStatus;
24
27
  disposedOn?: string;
25
28
  location?: string;
26
- keeper?: string;
29
+ keeper?: Employee;
30
+ keeperId?: string;
27
31
  source?: string;
28
32
  project?: string;
29
33
  description?: string;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Asset = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const auth_base_1 = require("@things-factory/auth-base");
6
+ const organization_1 = require("@things-factory/organization");
6
7
  const shell_1 = require("@things-factory/shell");
7
8
  const type_graphql_1 = require("type-graphql");
8
9
  const typeorm_1 = require("typeorm");
@@ -49,6 +50,16 @@ tslib_1.__decorate([
49
50
  (0, type_graphql_1.Field)({ description: 'The day it was acquired - YYYY-MM-DD' }),
50
51
  tslib_1.__metadata("design:type", String)
51
52
  ], Asset.prototype, "acquiredOn", void 0);
53
+ tslib_1.__decorate([
54
+ (0, typeorm_1.Column)({ nullable: true }),
55
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Its serial or control number - one asset\'s in the domain' }),
56
+ tslib_1.__metadata("design:type", String)
57
+ ], Asset.prototype, "serialNo", void 0);
58
+ tslib_1.__decorate([
59
+ (0, typeorm_1.Column)({ default: true }),
60
+ (0, type_graphql_1.Field)({ description: 'An asset of the books (depreciated, set beside the filed statements); off for an item only looked after - bought as an expense' }),
61
+ tslib_1.__metadata("design:type", Boolean)
62
+ ], Asset.prototype, "capitalized", void 0);
52
63
  tslib_1.__decorate([
53
64
  (0, typeorm_1.Column)({ ...(0, shell_1.moneyColumn)(), default: 0 }),
54
65
  (0, type_graphql_1.Field)(type => type_graphql_1.Float, { description: 'What it cost to acquire, in won' }),
@@ -95,10 +106,14 @@ tslib_1.__decorate([
95
106
  tslib_1.__metadata("design:type", String)
96
107
  ], Asset.prototype, "location", void 0);
97
108
  tslib_1.__decorate([
98
- (0, typeorm_1.Column)({ nullable: true }),
99
- (0, type_graphql_1.Field)({ nullable: true, description: 'Who looks after it' }),
100
- tslib_1.__metadata("design:type", String)
109
+ (0, typeorm_1.ManyToOne)(type => organization_1.Employee, { nullable: true }),
110
+ (0, type_graphql_1.Field)(type => organization_1.Employee, { nullable: true, description: 'Who looks after it - an employee of the domain' }),
111
+ tslib_1.__metadata("design:type", organization_1.Employee)
101
112
  ], Asset.prototype, "keeper", void 0);
113
+ tslib_1.__decorate([
114
+ (0, typeorm_1.RelationId)((asset) => asset.keeper),
115
+ tslib_1.__metadata("design:type", String)
116
+ ], Asset.prototype, "keeperId", void 0);
102
117
  tslib_1.__decorate([
103
118
  (0, typeorm_1.Column)({ nullable: true }),
104
119
  (0, type_graphql_1.Field)({ nullable: true, description: 'What it was acquired by - the contract, the invoice, the payment - in words' }),
@@ -1 +1 @@
1
- {"version":3,"file":"asset.js","sourceRoot":"","sources":["../../../server/service/asset/asset.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, Int, ObjectType } from 'type-graphql'\nimport { Column, CreateDateColumn, DeleteDateColumn, Entity, Index, ManyToOne, PrimaryGeneratedColumn, RelationId, UpdateDateColumn } from 'typeorm'\n\nimport { AssetKind, AssetStatus, DepreciationMethod } from './asset-rules'\n\n/**\n * A tangible or intangible asset of the domain - what it is, when and for how much it was acquired, how it is\n * depreciated and whether it is still in use (ADR-0175 decisions 3-4). The depreciation of a year is computed from these,\n * never stored. The books are the accountant's; the register is set beside them, not written into them.\n */\n@Entity()\n@Index('ix_asset_0', (asset: Asset) => [asset.domain, asset.kind])\n@ObjectType({ description: 'Entity for Asset — a tangible or intangible asset of the domain and how it is depreciated' })\nexport class Asset {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier of the asset' })\n readonly id: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { nullable: true, description: 'The domain the asset belongs to' })\n domain?: Domain\n\n @RelationId((asset: Asset) => asset.domain)\n domainId?: string\n\n @Column()\n @Field({ description: 'What the asset is called' })\n name: string\n\n @Column()\n @Field(type => AssetKind, { description: 'What kind of asset it is' })\n kind: AssetKind\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The line of the filed balance sheet it belongs to; the kind gives it when empty' })\n statementCode?: string\n\n @Column()\n @Field({ description: 'The day it was acquired - YYYY-MM-DD' })\n acquiredOn: string\n\n @Column({ ...moneyColumn(), default: 0 })\n @Field(type => Float, { description: 'What it cost to acquire, in won' })\n cost: number\n\n @Column({ ...moneyColumn(), default: 0 })\n @Field(type => Float, { description: 'The value left at the end of its useful life, in won' })\n residualValue: number\n\n @Column({ default: DepreciationMethod.STRAIGHT_LINE })\n @Field(type => DepreciationMethod, { description: 'How it is depreciated' })\n method: DepreciationMethod\n\n @Column({ type: 'float', nullable: true })\n @Field(type => Float, { nullable: true, description: 'Useful life in years, as the books use it' })\n usefulLifeYears?: number\n\n @Column({ type: 'float', nullable: true })\n @Field(type => Float, { nullable: true, description: 'The yearly rate of declining-balance depreciation, as the books use it (0.451 for 45.1%)' })\n declineRate?: number\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The day depreciation starts - YYYY-MM-DD; the day it was acquired when empty' })\n depreciationStartOn?: string\n\n @Column({ default: AssetStatus.IN_USE })\n @Field(type => AssetStatus, { description: 'In use, disposed of or scrapped' })\n status: AssetStatus\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The day it was disposed of or scrapped - YYYY-MM-DD' })\n disposedOn?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Where it is' })\n location?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Who looks after it' })\n keeper?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'What it was acquired by - the contract, the invoice, the payment - in words' })\n source?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'For development cost: the development project it came from' })\n project?: 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 documents are attached - filled by the list query' })\n documents?: number\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'When the asset was registered' })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true, description: 'When the asset last changed' })\n updatedAt?: Date\n\n @DeleteDateColumn()\n @Field({ nullable: true, description: 'When the asset 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((asset: Asset) => asset.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((asset: Asset) => asset.updater)\n updaterId?: string\n}\n"]}
1
+ {"version":3,"file":"asset.js","sourceRoot":"","sources":["../../../server/service/asset/asset.ts"],"names":[],"mappings":"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","sourcesContent":["import { User } from '@things-factory/auth-base'\nimport { Employee } 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 { AssetKind, AssetStatus, DepreciationMethod } from './asset-rules'\n\n/**\n * A tangible or intangible asset of the domain - what it is, when and for how much it was acquired, how it is\n * depreciated and whether it is still in use (ADR-0175 decisions 3-4). The depreciation of a year is computed from these,\n * never stored. The books are the accountant's; the register is set beside them, not written into them.\n */\n@Entity()\n@Index('ix_asset_0', (asset: Asset) => [asset.domain, asset.kind])\n@ObjectType({ description: 'Entity for Asset — a tangible or intangible asset of the domain and how it is depreciated' })\nexport class Asset {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier of the asset' })\n readonly id: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { nullable: true, description: 'The domain the asset belongs to' })\n domain?: Domain\n\n @RelationId((asset: Asset) => asset.domain)\n domainId?: string\n\n @Column()\n @Field({ description: 'What the asset is called' })\n name: string\n\n @Column()\n @Field(type => AssetKind, { description: 'What kind of asset it is' })\n kind: AssetKind\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The line of the filed balance sheet it belongs to; the kind gives it when empty' })\n statementCode?: string\n\n @Column()\n @Field({ description: 'The day it was acquired - YYYY-MM-DD' })\n acquiredOn: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Its serial or control number - one asset\\'s in the domain' })\n serialNo?: string\n\n @Column({ default: true })\n @Field({ description: 'An asset of the books (depreciated, set beside the filed statements); off for an item only looked after - bought as an expense' })\n capitalized: boolean\n\n @Column({ ...moneyColumn(), default: 0 })\n @Field(type => Float, { description: 'What it cost to acquire, in won' })\n cost: number\n\n @Column({ ...moneyColumn(), default: 0 })\n @Field(type => Float, { description: 'The value left at the end of its useful life, in won' })\n residualValue: number\n\n @Column({ default: DepreciationMethod.STRAIGHT_LINE })\n @Field(type => DepreciationMethod, { description: 'How it is depreciated' })\n method: DepreciationMethod\n\n @Column({ type: 'float', nullable: true })\n @Field(type => Float, { nullable: true, description: 'Useful life in years, as the books use it' })\n usefulLifeYears?: number\n\n @Column({ type: 'float', nullable: true })\n @Field(type => Float, { nullable: true, description: 'The yearly rate of declining-balance depreciation, as the books use it (0.451 for 45.1%)' })\n declineRate?: number\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The day depreciation starts - YYYY-MM-DD; the day it was acquired when empty' })\n depreciationStartOn?: string\n\n @Column({ default: AssetStatus.IN_USE })\n @Field(type => AssetStatus, { description: 'In use, disposed of or scrapped' })\n status: AssetStatus\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The day it was disposed of or scrapped - YYYY-MM-DD' })\n disposedOn?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Where it is' })\n location?: string\n\n @ManyToOne(type => Employee, { nullable: true })\n @Field(type => Employee, { nullable: true, description: 'Who looks after it - an employee of the domain' })\n keeper?: Employee\n\n @RelationId((asset: Asset) => asset.keeper)\n keeperId?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'What it was acquired by - the contract, the invoice, the payment - in words' })\n source?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'For development cost: the development project it came from' })\n project?: 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 documents are attached - filled by the list query' })\n documents?: number\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'When the asset was registered' })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true, description: 'When the asset last changed' })\n updatedAt?: Date\n\n @DeleteDateColumn()\n @Field({ nullable: true, description: 'When the asset 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((asset: Asset) => asset.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((asset: Asset) => asset.updater)\n updaterId?: string\n}\n"]}