tin-spa 20.14.113 → 20.16.0

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 (44) hide show
  1. package/core/index.d.ts +80 -10
  2. package/fesm2022/{tin-spa-accounting.module-Cg4vWaJE.mjs → tin-spa-accounting.module-CamqAeW_.mjs} +71 -83
  3. package/fesm2022/tin-spa-accounting.module-CamqAeW_.mjs.map +1 -0
  4. package/fesm2022/{tin-spa-agent-page.component-DJvMPjCQ.mjs → tin-spa-agent-page.component-DTYn54p0.mjs} +2 -2
  5. package/fesm2022/{tin-spa-agent-page.component-DJvMPjCQ.mjs.map → tin-spa-agent-page.component-DTYn54p0.mjs.map} +1 -1
  6. package/fesm2022/{tin-spa-agent.component-D0CGGnGZ.mjs → tin-spa-agent.component-CZKMWl3r.mjs} +2 -2
  7. package/fesm2022/{tin-spa-agent.component-D0CGGnGZ.mjs.map → tin-spa-agent.component-CZKMWl3r.mjs.map} +1 -1
  8. package/fesm2022/{tin-spa-assets.module-qIWNwJ2E.mjs → tin-spa-assets.module-BcOjlhfm.mjs} +16 -11
  9. package/fesm2022/tin-spa-assets.module-BcOjlhfm.mjs.map +1 -0
  10. package/fesm2022/tin-spa-core.mjs +426 -112
  11. package/fesm2022/tin-spa-core.mjs.map +1 -1
  12. package/fesm2022/{tin-spa-general-erp.module-CoYxceLj.mjs → tin-spa-general-erp.module-b6SjnWUM.mjs} +2 -2
  13. package/fesm2022/{tin-spa-general-erp.module-CoYxceLj.mjs.map → tin-spa-general-erp.module-b6SjnWUM.mjs.map} +1 -1
  14. package/fesm2022/{tin-spa-hr.module-CKPZ9ZOj.mjs → tin-spa-hr.module-DkGVK2lX.mjs} +2 -2
  15. package/fesm2022/{tin-spa-hr.module-CKPZ9ZOj.mjs.map → tin-spa-hr.module-DkGVK2lX.mjs.map} +1 -1
  16. package/fesm2022/tin-spa-http.mjs +32 -1
  17. package/fesm2022/tin-spa-http.mjs.map +1 -1
  18. package/fesm2022/{tin-spa-inventory.module-DRKAcNau.mjs → tin-spa-inventory.module-CYWBqSCd.mjs} +16 -11
  19. package/fesm2022/tin-spa-inventory.module-CYWBqSCd.mjs.map +1 -0
  20. package/fesm2022/{tin-spa-loans.module-BTDmgrWo.mjs → tin-spa-loans.module-BDh-T-Ng.mjs} +2 -2
  21. package/fesm2022/{tin-spa-loans.module-BTDmgrWo.mjs.map → tin-spa-loans.module-BDh-T-Ng.mjs.map} +1 -1
  22. package/fesm2022/{tin-spa-manufacturing.module-CHta6oV_.mjs → tin-spa-manufacturing.module-9Ti-BFb2.mjs} +2 -2
  23. package/fesm2022/{tin-spa-manufacturing.module-CHta6oV_.mjs.map → tin-spa-manufacturing.module-9Ti-BFb2.mjs.map} +1 -1
  24. package/fesm2022/{tin-spa-payroll.module-CZ_GO1jF.mjs → tin-spa-payroll.module-54Efumv_.mjs} +9 -6
  25. package/fesm2022/{tin-spa-payroll.module-CZ_GO1jF.mjs.map → tin-spa-payroll.module-54Efumv_.mjs.map} +1 -1
  26. package/fesm2022/{tin-spa-purchasing.module-NCdwquaF.mjs → tin-spa-purchasing.module-Bq8JnsyM.mjs} +16 -11
  27. package/fesm2022/tin-spa-purchasing.module-Bq8JnsyM.mjs.map +1 -0
  28. package/fesm2022/{tin-spa-sales.module-D0uEGJW7.mjs → tin-spa-sales.module-nyrJulzD.mjs} +40 -17
  29. package/fesm2022/tin-spa-sales.module-nyrJulzD.mjs.map +1 -0
  30. package/fesm2022/{tin-spa-tenancy-erp.module-GwIv8Wbc.mjs → tin-spa-tenancy-erp.module-DGATA-p_.mjs} +2 -2
  31. package/fesm2022/{tin-spa-tenancy-erp.module-GwIv8Wbc.mjs.map → tin-spa-tenancy-erp.module-DGATA-p_.mjs.map} +1 -1
  32. package/fesm2022/{tin-spa-tin-spa-Cqe5hYTr.mjs → tin-spa-tin-spa-BMy59BVn.mjs} +1428 -219
  33. package/fesm2022/tin-spa-tin-spa-BMy59BVn.mjs.map +1 -0
  34. package/fesm2022/tin-spa.mjs +1 -1
  35. package/http/index.d.ts +3 -1
  36. package/index.d.ts +144 -24
  37. package/package.json +1 -1
  38. package/src/tin-styles.css +27 -0
  39. package/fesm2022/tin-spa-accounting.module-Cg4vWaJE.mjs.map +0 -1
  40. package/fesm2022/tin-spa-assets.module-qIWNwJ2E.mjs.map +0 -1
  41. package/fesm2022/tin-spa-inventory.module-DRKAcNau.mjs.map +0 -1
  42. package/fesm2022/tin-spa-purchasing.module-NCdwquaF.mjs.map +0 -1
  43. package/fesm2022/tin-spa-sales.module-D0uEGJW7.mjs.map +0 -1
  44. package/fesm2022/tin-spa-tin-spa-Cqe5hYTr.mjs.map +0 -1
package/core/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import * as rxjs from 'rxjs';
2
2
  import { BehaviorSubject, Observable, Subject } from 'rxjs';
3
3
  import * as tin_spa_core from 'tin-spa/core';
4
4
  import * as i0 from '@angular/core';
5
- import { InjectionToken, EnvironmentProviders, Injector, NgZone, OnInit, EventEmitter, OnChanges, SimpleChanges } from '@angular/core';
5
+ import { InjectionToken, EnvironmentProviders, Injector, NgZone, OnInit, EventEmitter, OnChanges, SimpleChanges, ElementRef } from '@angular/core';
6
6
  import * as i11 from '@angular/material/dialog';
7
7
  import { MatDialog, MatDialogRef } from '@angular/material/dialog';
8
8
  import { HttpClient, HttpContext, HttpResponse, HttpErrorResponse, HttpContextToken } from '@angular/common/http';
@@ -14,7 +14,6 @@ import { SocialUser, SocialAuthService } from '@abacritt/angularx-social-login';
14
14
  import * as signalR from '@microsoft/signalr';
15
15
  import * as i1 from '@angular/common';
16
16
  import { PlatformLocation, LocationStrategy } from '@angular/common';
17
- import { IPublicClientApplication } from '@azure/msal-browser';
18
17
  import * as i2 from '@angular/forms';
19
18
  import { FormControl } from '@angular/forms';
20
19
  import * as i3 from '@angular/material/menu';
@@ -766,6 +765,9 @@ interface Tile {
766
765
  chart?: TileChartConfig;
767
766
  filter?: (row: any) => boolean;
768
767
  data?: any;
768
+ hideWhenEmpty?: boolean;
769
+ emptyText?: string;
770
+ securityConfig?: SecurityConfig;
769
771
  }
770
772
  interface FilterChip {
771
773
  key: string;
@@ -805,6 +807,9 @@ declare class TileConfig {
805
807
  minTileWidth?: number;
806
808
  maxPerRow?: number;
807
809
  hideValueOnMobile?: boolean;
810
+ hideWhenEmpty?: boolean;
811
+ emptyText?: string;
812
+ security?: SecurityConfig;
808
813
  }
809
814
  type SpaChartType = 'line' | 'bar' | 'pie' | 'doughnut';
810
815
  interface ChartItem {
@@ -826,12 +831,38 @@ interface ChartItem {
826
831
  hidden?: VisibilityValue;
827
832
  visible?: VisibilityValue;
828
833
  options?: any;
834
+ hideWhenEmpty?: boolean;
835
+ emptyText?: string;
836
+ securityConfig?: SecurityConfig;
829
837
  }
830
838
  declare class ChartConfig {
831
839
  charts: ChartItem[];
832
840
  loadAction?: Action;
833
841
  loadInit?: boolean;
834
842
  columns?: number;
843
+ hideWhenEmpty?: boolean;
844
+ emptyText?: string;
845
+ security?: SecurityConfig;
846
+ }
847
+ interface DashboardSection {
848
+ key: string;
849
+ title: string;
850
+ icon?: string;
851
+ security?: SecurityConfig;
852
+ moduleKey?: string;
853
+ link?: string;
854
+ tileConfigs?: TileConfig[];
855
+ chartConfig?: ChartConfig;
856
+ tableConfigs?: TableConfig[];
857
+ hidden?: VisibilityValue;
858
+ visible?: VisibilityValue;
859
+ }
860
+ declare class DashboardConfig {
861
+ sections: DashboardSection[];
862
+ title?: string;
863
+ icon?: string;
864
+ quietLoading?: boolean;
865
+ emptyText?: string;
835
866
  }
836
867
  declare class Step {
837
868
  name: string;
@@ -876,6 +907,11 @@ interface GroupConfig {
876
907
  orderField?: string;
877
908
  itemsField?: string;
878
909
  itemTextField: string;
910
+ itemChipField?: string;
911
+ itemTimeField?: string;
912
+ itemSubField?: string;
913
+ itemTimeFormat?: string;
914
+ itemClassField?: string;
879
915
  itemIcon?: Icon;
880
916
  itemIcons?: Icon[];
881
917
  itemAdditionalIcons?: Icon[];
@@ -885,10 +921,12 @@ interface GroupConfig {
885
921
  showEmptyGroups?: boolean;
886
922
  headerButtons?: Button[];
887
923
  contextMenuEnabled?: boolean;
924
+ itemClickButton?: string;
888
925
  filterEnabled?: boolean;
889
926
  dragEnabled?: boolean;
890
927
  dropAction?: Action;
891
928
  groupOrderable?: OrderableConfig | boolean;
929
+ groupOrderOrientation?: 'vertical' | 'horizontal' | 'mixed';
892
930
  }
893
931
  interface Column {
894
932
  name: string;
@@ -958,6 +996,7 @@ declare class TableConfig {
958
996
  causeFormRefresh?: boolean;
959
997
  logResponse?: boolean;
960
998
  flatButtons?: boolean;
999
+ outlinedHeaderButtons?: boolean;
961
1000
  greyOut?: (value: any) => boolean;
962
1001
  heroField?: any;
963
1002
  heroValue?: any;
@@ -982,6 +1021,9 @@ declare class TableConfig {
982
1021
  import?: ImportConfig;
983
1022
  realTime?: boolean;
984
1023
  realTimeFallbackMs?: number;
1024
+ realTimeRefresh?: boolean;
1025
+ realTimeRefreshMs?: number;
1026
+ realTimeRefreshEntities?: string[];
985
1027
  entityName?: string;
986
1028
  offline?: OfflineConfig | boolean;
987
1029
  pagination?: PaginationConfig;
@@ -1106,7 +1148,7 @@ declare class AppConfig {
1106
1148
  get navigation(): 'top' | 'side-modern' | 'top-modern';
1107
1149
  docsBaseUrl?: string;
1108
1150
  loginStyle: string;
1109
- dialogStyle: string;
1151
+ dialogStyle: 'default' | 'modern';
1110
1152
  loginTitle: string;
1111
1153
  loginMessage: string;
1112
1154
  termsUrl: string;
@@ -1266,6 +1308,7 @@ interface DayBookSection {
1266
1308
  key: string;
1267
1309
  lane?: string;
1268
1310
  listField: string;
1311
+ refreshOn?: string[];
1269
1312
  collapsed?: boolean;
1270
1313
  tableConfig?: TableConfig;
1271
1314
  columns?: (string | DayBookColumnView)[];
@@ -1303,6 +1346,7 @@ interface DayBookConfig {
1303
1346
  pageSize?: number;
1304
1347
  groupLanes?: boolean;
1305
1348
  expandedGroups?: number;
1349
+ refreshDebounceMs?: number;
1306
1350
  }
1307
1351
  interface AppConfigSection {
1308
1352
  key: string;
@@ -1380,9 +1424,22 @@ declare class Core {
1380
1424
  visible?: VisibilityValue;
1381
1425
  hidden?: VisibilityValue;
1382
1426
  }, data: any): boolean;
1427
+ static isChartDataEmpty(chartData: any): boolean;
1428
+ private static chartPointValue;
1429
+ static isChartEmpty(chart: ChartItem, data: any): boolean;
1430
+ static isChartRendered(chart: ChartItem, config: ChartConfig, data: any): boolean;
1431
+ static isTileChartEmpty(tile: Tile, data: any): boolean;
1432
+ static isTileRendered(tile: Tile, config: TileConfig, data: any): boolean;
1433
+ static gatedItems<T extends {
1434
+ securityConfig?: SecurityConfig;
1435
+ }>(items: T[], security: SecurityConfig, role: any): {
1436
+ items: T[];
1437
+ denied: boolean;
1438
+ };
1383
1439
  static testVisible(config: FormConfig, data: any, field: Field, currentRole: any): boolean;
1384
1440
  static isPredicateHidden(config: FormConfig, data: any, field: Field): boolean;
1385
1441
  static buildSubmitPayload(config: FormConfig, data: any): any;
1442
+ static stripServerOwned(config: FormConfig, data: any): any;
1386
1443
  static testReadOnly(config: FormConfig, data: any, field: Field): boolean;
1387
1444
  static buttonDisplay(button: {
1388
1445
  display?: string | ((data: any) => string);
@@ -1390,6 +1447,7 @@ declare class Core {
1390
1447
  static testVisibleHeaderButton(data: any, btn: any): boolean;
1391
1448
  static getVisibleSubfields(config: FormConfig, data: any, field: Field, currentRole: any): Field[];
1392
1449
  static validateObject(fields: Field[], data: any, onInvalid?: (field: Field) => void): string;
1450
+ private static describeDateBound;
1393
1451
  private static validateField;
1394
1452
  static testRequired(config: FormConfig, data: any, field: Field): boolean;
1395
1453
  static getInitialValue(field: Field): any;
@@ -1470,8 +1528,8 @@ declare class MessageService {
1470
1528
  infoWithSubject(subject: string, details: string): void;
1471
1529
  error(details: string): void;
1472
1530
  errorWithSubject(subject: string, details: string, reference?: string): void;
1473
- warning(details: string, subject?: string): void;
1474
- success(details: string, subject?: string): void;
1531
+ warning(subject: string, details: string): void;
1532
+ success(subject: string, details: string): void;
1475
1533
  confirm(msg: string, confirmLabel?: string, cancelLabel?: string, destructive?: boolean, requirePhrase?: string): Observable<any>;
1476
1534
  static ɵfac: i0.ɵɵFactoryDeclaration<MessageService, never>;
1477
1535
  static ɵprov: i0.ɵɵInjectableDeclaration<MessageService>;
@@ -1548,9 +1606,9 @@ declare const TIN_SPA_RUNTIME_CONFIG: InjectionToken<TinSpaRuntimeConfig>;
1548
1606
  declare function tinSpaLocationStrategyFactory(platformLocation: PlatformLocation, baseHref: string, config: TinSpaRuntimeConfig): LocationStrategy;
1549
1607
  /** Overlays assets/appsettings.json values (when the app loaded one) onto the code-declared config. */
1550
1608
  declare function tinSpaRuntimeConfigFactory(codeConfig: TinSpaRuntimeConfig): TinSpaRuntimeConfig;
1551
- declare function tinSpaMsalInstanceFactory(config: TinSpaRuntimeConfig): IPublicClientApplication;
1552
1609
  /**
1553
- * Wires up tin-spa runtime behaviours (routing strategy, real-time, MSAL) from a single config.
1610
+ * Wires up tin-spa runtime behaviours (routing strategy, real-time) from a single config.
1611
+ * Changed (20.14.114): no longer provides MSAL - an app that wants Microsoft SSO registers it itself.
1554
1612
  * Add the result to your AppModule (or bootstrap) providers.
1555
1613
  */
1556
1614
  declare function provideTinSpaRuntime(config: Partial<TinSpaRuntimeConfig>): EnvironmentProviders;
@@ -1564,6 +1622,10 @@ interface EntityChangeEvent {
1564
1622
  entityName: string;
1565
1623
  data: any;
1566
1624
  }
1625
+ interface EntityInvalidatedEvent {
1626
+ entityName: string;
1627
+ id?: number | null;
1628
+ }
1567
1629
  interface NotificationEvent {
1568
1630
  message: string;
1569
1631
  category: string;
@@ -1589,6 +1651,8 @@ declare class SignalRService {
1589
1651
  entityCreated$: rxjs.Observable<EntityChangeEvent>;
1590
1652
  entityUpdated$: rxjs.Observable<EntityChangeEvent>;
1591
1653
  entityDeleted$: rxjs.Observable<EntityChangeEvent>;
1654
+ private entityInvalidated;
1655
+ entityInvalidated$: rxjs.Observable<EntityInvalidatedEvent>;
1592
1656
  private vehiclePosition;
1593
1657
  vehiclePosition$: rxjs.Observable<VehiclePositionFrame>;
1594
1658
  private notificationReceived;
@@ -1797,6 +1861,7 @@ declare class OfflineService {
1797
1861
  private opening;
1798
1862
  private entries;
1799
1863
  private readUrls;
1864
+ private lookupUrls;
1800
1865
  private readPrefixes;
1801
1866
  registered$: BehaviorSubject<boolean>;
1802
1867
  private connectivityStarted;
@@ -2180,7 +2245,9 @@ declare class SuffixComponent implements OnInit {
2180
2245
  isHovered: boolean;
2181
2246
  clearContent: boolean;
2182
2247
  readonly: boolean;
2248
+ alwaysShow: boolean;
2183
2249
  value: any;
2250
+ get hasValue(): boolean;
2184
2251
  infoClick: EventEmitter<void>;
2185
2252
  copyClick: EventEmitter<string>;
2186
2253
  clearClick: EventEmitter<void>;
@@ -2189,7 +2256,7 @@ declare class SuffixComponent implements OnInit {
2189
2256
  onCopyClick(event: MouseEvent): void;
2190
2257
  onClearClick(event: MouseEvent): void;
2191
2258
  static ɵfac: i0.ɵɵFactoryDeclaration<SuffixComponent, never>;
2192
- static ɵcmp: i0.ɵɵComponentDeclaration<SuffixComponent, "spa-suffix", never, { "label": { "alias": "label"; "required": false; }; "infoMessage": { "alias": "infoMessage"; "required": false; }; "copyContent": { "alias": "copyContent"; "required": false; }; "isHovered": { "alias": "isHovered"; "required": false; }; "clearContent": { "alias": "clearContent"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; "value": { "alias": "value"; "required": false; }; }, { "infoClick": "infoClick"; "copyClick": "copyClick"; "clearClick": "clearClick"; "valueChange": "valueChange"; }, never, never, false, never>;
2259
+ static ɵcmp: i0.ɵɵComponentDeclaration<SuffixComponent, "spa-suffix", never, { "label": { "alias": "label"; "required": false; }; "infoMessage": { "alias": "infoMessage"; "required": false; }; "copyContent": { "alias": "copyContent"; "required": false; }; "isHovered": { "alias": "isHovered"; "required": false; }; "clearContent": { "alias": "clearContent"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; "alwaysShow": { "alias": "alwaysShow"; "required": false; }; "value": { "alias": "value"; "required": false; }; }, { "infoClick": "infoClick"; "copyClick": "copyClick"; "clearClick": "clearClick"; "valueChange": "valueChange"; }, never, never, false, never>;
2193
2260
  }
2194
2261
 
2195
2262
  declare class TermsDialogComponent {
@@ -2269,7 +2336,9 @@ declare class TextComponent implements OnInit, OnChanges {
2269
2336
  onMouseLeave(): void;
2270
2337
  initControl(): void;
2271
2338
  leaved(): void;
2339
+ inputEl: ElementRef<HTMLInputElement>;
2272
2340
  clear(): void;
2341
+ private focusInput;
2273
2342
  enterPressed(): void;
2274
2343
  control: FormControl<string>;
2275
2344
  private getValidators;
@@ -2822,6 +2891,7 @@ declare class MenuSourceService {
2822
2891
  private static readonly roleMetadata;
2823
2892
  private hasAnyCapability;
2824
2893
  isVisible(cap: CapItem): boolean;
2894
+ hasVisibleEntry(capItem: CapItem): boolean;
2825
2895
  sections(): MenuSection[];
2826
2896
  visibleItems(): CapItem[];
2827
2897
  matchLink(route: string, items: CapItem[]): CapItem | null;
@@ -3029,5 +3099,5 @@ declare class SpaCoreModule {
3029
3099
  static ɵinj: i0.ɵɵInjectorDeclaration<SpaCoreModule>;
3030
3100
  }
3031
3101
 
3032
- export { Account, AccountingService, Action, AlertConfig, AlertMessage, ApiErrorService, ApiResponse, AppConfig, AssetStatus, AuthService, BottomTab, CacheConfig, CapItem, ChangeUserPassword, ChartConfig, ConfigService, Constants, Core, CreditNoteStatus, DataServiceLib, DateBounds, DetailsDialogConfig, DetailsDialogProcessor, DetailsSource, FilterChipConfig, FiscalPeriodStatus, FormConfig, GRID_MENU_ROUTE, GRID_MENU_TAB, GeneralService, HttpService, InventoryService, InvoiceItemType, InvoiceStatus, LastRouteService, ListDialogConfig, LoansService, LogLevel, LogService, MenuSourceService, MessageService, MovementType, NotesConfig, NotificationsService, OfflineService, PageConfig, PaginationConfig, PayrollService, PreferencesService, PrivacyDialogComponent, ProductionService, Profile, PurchaseStatus, PurchasingService, QuoteStatus, REDACTED, ReceiptDialogComponent, ReceiptStatus, RedactingSignalRLogger, Register, Role, RoleAccess, SalesService, SearchConfig, SecurityConfig, SetupService, SignalRService, SignupData, SpaCoreModule, SpaMatModule, Step, StepConfig, StorageService, SubscriptionService, SuffixComponent, TIN_INLINE_ERRORS, TIN_LOGIN_TIER_HTTP_PROVIDERS, TIN_SILENT_REQUEST, TIN_SPA_RUNTIME_CONFIG, TableConfig, TermsDialogComponent, TextComponent, TextMaskComponent, TileConfig, TransactionTiming, UnitOfMeasure, User, derivePlaceholder, describeError, describeShape, dialogOptions, getTinSpaAppSettings, isInlineErrorRequest, isSilentRequest, loadTinSpaAppSettings, loginConfig, messageDialog, phraseSatisfied, provideTinSpaRuntime, redactSecrets, silentContext, tinRequestContext, tinSpaLocationStrategyFactory, tinSpaMsalInstanceFactory, tinSpaRuntimeConfigFactory };
3033
- export type { ApiErrorInfo, ApiErrorKind, AppConfigSection, AppConfigurationConfig, AppFailureClass, AppFailureContext, AutoRefreshConfig, BitwiseOption, Button, CacheRule, CapsuleConfig, CardConfig, ChartItem, ChecklistAction, ChecklistConfig, ChecklistItem, ChildField, CloseOptions, Color, Column, Confirm, CreateTabConfig, DayBookButtonView, DayBookColumnPresentation, DayBookColumnView, DayBookConfig, DayBookLane, DayBookPresentation, DayBookSection, DayBookStage, DayBookStageTiles, DayBookTableView, DocumentError, DocumentKind, DocumentSource, DocumentViewerData, EntityChangeEvent, Field, FilterChip, GroupConfig, GroupData, Icon, ImportConfig, InlineEditConfig, InlineLoadError, LoadedDocument, MenuSection, NoAccessInfo, NotificationEvent, OfflineConfig, OfflineEntry, OfflineOpStatus, OrderableConfig, OutboxOp, PlaceholderKind, RefreshResult, SearchField, SetupApprovalPreset, SetupConfig, SetupModule, SetupNotificationPreset, SetupPreset, SetupPresetCatalog, SetupPresetRole, SetupPresetSelection, SetupRoleTemplate, SetupSeedOffer, SetupStatus, SetupStep, SetupStepAction, SpaChartType, StatusConfig, StatusItem, StatusState, TableDialogConfig, TableSectionChip, TableSectionConfig, TableViewType, Tile, TileChartConfig, TileChartType, TileStyle, TinSpaAppSettings, TinSpaMsalConfig, TinSpaMsalSettings, TinSpaRuntimeConfig, TinSpaTableDefaults, UserPreferences, VehiclePositionFrame, VisibilityValue };
3102
+ export { Account, AccountingService, Action, AlertConfig, AlertMessage, ApiErrorService, ApiResponse, AppConfig, AssetStatus, AuthService, BottomTab, CacheConfig, CapItem, ChangeUserPassword, ChartConfig, ConfigService, Constants, Core, CreditNoteStatus, DashboardConfig, DataServiceLib, DateBounds, DetailsDialogConfig, DetailsDialogProcessor, DetailsSource, FilterChipConfig, FiscalPeriodStatus, FormConfig, GRID_MENU_ROUTE, GRID_MENU_TAB, GeneralService, HttpService, InventoryService, InvoiceItemType, InvoiceStatus, LastRouteService, ListDialogConfig, LoansService, LogLevel, LogService, MenuSourceService, MessageService, MovementType, NotesConfig, NotificationsService, OfflineService, PageConfig, PaginationConfig, PayrollService, PreferencesService, PrivacyDialogComponent, ProductionService, Profile, PurchaseStatus, PurchasingService, QuoteStatus, REDACTED, ReceiptDialogComponent, ReceiptStatus, RedactingSignalRLogger, Register, Role, RoleAccess, SalesService, SearchConfig, SecurityConfig, SetupService, SignalRService, SignupData, SpaCoreModule, SpaMatModule, Step, StepConfig, StorageService, SubscriptionService, SuffixComponent, TIN_INLINE_ERRORS, TIN_LOGIN_TIER_HTTP_PROVIDERS, TIN_SILENT_REQUEST, TIN_SPA_RUNTIME_CONFIG, TableConfig, TermsDialogComponent, TextComponent, TextMaskComponent, TileConfig, TransactionTiming, UnitOfMeasure, User, derivePlaceholder, describeError, describeShape, dialogOptions, getTinSpaAppSettings, isInlineErrorRequest, isSilentRequest, loadTinSpaAppSettings, loginConfig, messageDialog, phraseSatisfied, provideTinSpaRuntime, redactSecrets, silentContext, tinRequestContext, tinSpaLocationStrategyFactory, tinSpaRuntimeConfigFactory };
3103
+ export type { ApiErrorInfo, ApiErrorKind, AppConfigSection, AppConfigurationConfig, AppFailureClass, AppFailureContext, AutoRefreshConfig, BitwiseOption, Button, CacheRule, CapsuleConfig, CardConfig, ChartItem, ChecklistAction, ChecklistConfig, ChecklistItem, ChildField, CloseOptions, Color, Column, Confirm, CreateTabConfig, DashboardSection, DayBookButtonView, DayBookColumnPresentation, DayBookColumnView, DayBookConfig, DayBookLane, DayBookPresentation, DayBookSection, DayBookStage, DayBookStageTiles, DayBookTableView, DocumentError, DocumentKind, DocumentSource, DocumentViewerData, EntityChangeEvent, EntityInvalidatedEvent, Field, FilterChip, GroupConfig, GroupData, Icon, ImportConfig, InlineEditConfig, InlineLoadError, LoadedDocument, MenuSection, NoAccessInfo, NotificationEvent, OfflineConfig, OfflineEntry, OfflineOpStatus, OrderableConfig, OutboxOp, PlaceholderKind, RefreshResult, SearchField, SetupApprovalPreset, SetupConfig, SetupModule, SetupNotificationPreset, SetupPreset, SetupPresetCatalog, SetupPresetRole, SetupPresetSelection, SetupRoleTemplate, SetupSeedOffer, SetupStatus, SetupStep, SetupStepAction, SpaChartType, StatusConfig, StatusItem, StatusState, TableDialogConfig, TableSectionChip, TableSectionConfig, TableViewType, Tile, TileChartConfig, TileChartType, TileStyle, TinSpaAppSettings, TinSpaMsalConfig, TinSpaMsalSettings, TinSpaRuntimeConfig, TinSpaTableDefaults, UserPreferences, VehiclePositionFrame, VisibilityValue };
@@ -4,7 +4,7 @@ import * as i1$2 from '@angular/router';
4
4
  import { RouterModule } from '@angular/router';
5
5
  import * as i1 from 'tin-spa/core';
6
6
  import { AccountingService, MessageService, ApiErrorService, PurchasingService, HttpService, DataServiceLib, ReceiptDialogComponent } from 'tin-spa/core';
7
- import { T as TilesComponent, a as TabsComponent, P as PageComponent, D as DateComponent, b as TableComponent, S as SelectLiteComponent, c as TinSpaModule, C as ChartsComponent, d as TenantTransferService, e as SpaAdminModule } from './tin-spa-tin-spa-Cqe5hYTr.mjs';
7
+ import { T as TilesComponent, a as TabsComponent, P as PageComponent, D as DateComponent, b as TableComponent, S as SelectLiteComponent, c as TinSpaModule, C as ChartsComponent, d as TenantTransferService, e as SpaAdminModule } from './tin-spa-tin-spa-BMy59BVn.mjs';
8
8
  import * as i1$1 from '@angular/common';
9
9
  import { CommonModule } from '@angular/common';
10
10
  import * as i3 from '@angular/material/button';
@@ -80,7 +80,7 @@ class AccountsComponent {
80
80
  <spa-tiles [config]="accountTileConfig"></spa-tiles>
81
81
 
82
82
  <spa-tabs [tableConfigs]="accountTabConfigs"></spa-tabs>
83
- `, isInline: true, dependencies: [{ kind: "component", type: TilesComponent, selector: "spa-tiles", inputs: ["config", "lastSearch", "data", "reload"], outputs: ["tileActionSelected", "tileClick", "tileUnClick"] }, { kind: "component", type: TabsComponent, selector: "spa-tabs", inputs: ["tableConfigs", "reload", "reloadTab", "parentDetails", "localMode", "nestingLevel"], outputs: ["formRefresh", "actionSuccess"] }] }); }
83
+ `, isInline: true, dependencies: [{ kind: "component", type: TilesComponent, selector: "spa-tiles", inputs: ["config", "lastSearch", "data", "reload"], outputs: ["tileActionSelected", "contentResolved", "tileClick", "tileUnClick"] }, { kind: "component", type: TabsComponent, selector: "spa-tabs", inputs: ["tableConfigs", "reload", "reloadTab", "parentDetails", "localMode", "nestingLevel"], outputs: ["formRefresh", "actionSuccess"] }] }); }
84
84
  }
85
85
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: AccountsComponent, decorators: [{
86
86
  type: Component,
@@ -238,7 +238,7 @@ class AgingComponent {
238
238
  </div>
239
239
 
240
240
  <spa-tabs [tableConfigs]="agingTableConfigs"></spa-tabs>
241
- `, isInline: true, dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: TilesComponent, selector: "spa-tiles", inputs: ["config", "lastSearch", "data", "reload"], outputs: ["tileActionSelected", "tileClick", "tileUnClick"] }, { kind: "component", type: TabsComponent, selector: "spa-tabs", inputs: ["tableConfigs", "reload", "reloadTab", "parentDetails", "localMode", "nestingLevel"], outputs: ["formRefresh", "actionSuccess"] }] }); }
241
+ `, isInline: true, dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: TilesComponent, selector: "spa-tiles", inputs: ["config", "lastSearch", "data", "reload"], outputs: ["tileActionSelected", "contentResolved", "tileClick", "tileUnClick"] }, { kind: "component", type: TabsComponent, selector: "spa-tabs", inputs: ["tableConfigs", "reload", "reloadTab", "parentDetails", "localMode", "nestingLevel"], outputs: ["formRefresh", "actionSuccess"] }] }); }
242
242
  }
243
243
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: AgingComponent, decorators: [{
244
244
  type: Component,
@@ -324,7 +324,7 @@ class SupplierAgingComponent {
324
324
  </div>
325
325
 
326
326
  <spa-tabs [tableConfigs]="agingTableConfigs"></spa-tabs>
327
- `, isInline: true, dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: TilesComponent, selector: "spa-tiles", inputs: ["config", "lastSearch", "data", "reload"], outputs: ["tileActionSelected", "tileClick", "tileUnClick"] }, { kind: "component", type: TabsComponent, selector: "spa-tabs", inputs: ["tableConfigs", "reload", "reloadTab", "parentDetails", "localMode", "nestingLevel"], outputs: ["formRefresh", "actionSuccess"] }] }); }
327
+ `, isInline: true, dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: TilesComponent, selector: "spa-tiles", inputs: ["config", "lastSearch", "data", "reload"], outputs: ["tileActionSelected", "contentResolved", "tileClick", "tileUnClick"] }, { kind: "component", type: TabsComponent, selector: "spa-tabs", inputs: ["tableConfigs", "reload", "reloadTab", "parentDetails", "localMode", "nestingLevel"], outputs: ["formRefresh", "actionSuccess"] }] }); }
328
328
  }
329
329
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: SupplierAgingComponent, decorators: [{
330
330
  type: Component,
@@ -569,7 +569,7 @@ class StatementComponent {
569
569
 
570
570
  </div>
571
571
  </ng-template>
572
- `, isInline: true, dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i3$2.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i3$2.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "component", type: TilesComponent, selector: "spa-tiles", inputs: ["config", "lastSearch", "data", "reload"], outputs: ["tileActionSelected", "tileClick", "tileUnClick"] }, { kind: "component", type: DateComponent, selector: "spa-date", inputs: ["required", "min", "max", "boundContext", "readonly", "hint", "value", "display", "placeholder", "width", "suffix", "infoMessage", "copyContent", "clearContent"], outputs: ["valueChange"] }, { kind: "component", type: TableComponent, selector: "spa-table", inputs: ["data", "tileData", "config", "localMode", "parentDetails", "reload", "activeTab", "inTab", "nestingLevel"], outputs: ["dataLoad", "totalChange", "actionSuccess", "refreshClick", "searchClick", "createClick", "actionClick", "inputChange", "actionResponse"] }, { kind: "component", type: PageComponent, selector: "spa-page", inputs: ["config"], outputs: ["searchModeActivated", "searchModeDeactivated", "refreshClick", "actionClick", "actionResponse", "inputChange", "createClick", "searchClick", "dataLoad", "titleActionChange"] }, { kind: "component", type: SelectLiteComponent, selector: "spa-select-lite" }] }); }
572
+ `, isInline: true, dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i3$2.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i3$2.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "component", type: TilesComponent, selector: "spa-tiles", inputs: ["config", "lastSearch", "data", "reload"], outputs: ["tileActionSelected", "contentResolved", "tileClick", "tileUnClick"] }, { kind: "component", type: DateComponent, selector: "spa-date", inputs: ["required", "min", "max", "boundContext", "readonly", "hint", "value", "display", "placeholder", "width", "suffix", "infoMessage", "copyContent", "clearContent"], outputs: ["valueChange"] }, { kind: "component", type: TableComponent, selector: "spa-table", inputs: ["data", "tileData", "config", "localMode", "parentDetails", "reload", "activeTab", "inTab", "nestingLevel"], outputs: ["dataLoad", "totalChange", "actionSuccess", "refreshClick", "searchClick", "createClick", "actionClick", "inputChange", "actionResponse", "contentResolved"] }, { kind: "component", type: PageComponent, selector: "spa-page", inputs: ["config"], outputs: ["searchModeActivated", "searchModeDeactivated", "refreshClick", "actionClick", "actionResponse", "inputChange", "createClick", "searchClick", "dataLoad", "titleActionChange"] }, { kind: "component", type: SelectLiteComponent, selector: "spa-select-lite" }] }); }
573
573
  }
574
574
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: StatementComponent, decorators: [{
575
575
  type: Component,
@@ -902,7 +902,7 @@ class BudgetVsActualComponent {
902
902
  <spa-tiles *ngIf="summaryTileConfig.loadAction" [config]="summaryTileConfig"></spa-tiles>
903
903
 
904
904
  <spa-tabs *ngIf="reportTabConfigs.length > 0" [tableConfigs]="reportTabConfigs"></spa-tabs>
905
- `, isInline: true, dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: TilesComponent, selector: "spa-tiles", inputs: ["config", "lastSearch", "data", "reload"], outputs: ["tileActionSelected", "tileClick", "tileUnClick"] }, { kind: "component", type: TabsComponent, selector: "spa-tabs", inputs: ["tableConfigs", "reload", "reloadTab", "parentDetails", "localMode", "nestingLevel"], outputs: ["formRefresh", "actionSuccess"] }, { kind: "component", type: SelectLiteComponent, selector: "spa-select-lite" }] }); }
905
+ `, isInline: true, dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: TilesComponent, selector: "spa-tiles", inputs: ["config", "lastSearch", "data", "reload"], outputs: ["tileActionSelected", "contentResolved", "tileClick", "tileUnClick"] }, { kind: "component", type: TabsComponent, selector: "spa-tabs", inputs: ["tableConfigs", "reload", "reloadTab", "parentDetails", "localMode", "nestingLevel"], outputs: ["formRefresh", "actionSuccess"] }, { kind: "component", type: SelectLiteComponent, selector: "spa-select-lite" }] }); }
906
906
  }
907
907
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: BudgetVsActualComponent, decorators: [{
908
908
  type: Component,
@@ -926,7 +926,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImpo
926
926
 
927
927
  // Accounting module dashboard — pure financial/account performance (invoice-specific moved to invoicing)
928
928
  class AccountingDashboardComponent {
929
- constructor() {
929
+ constructor(dataService) {
930
+ this.dataService = dataService;
930
931
  this.summaryTiles = {
931
932
  tiles: [
932
933
  { name: 'inflows', alias: 'Inflows (MTD)', color: '#4caf50', icon: 'arrow_downward', style: 'icon', info: 'MTD cash inflows' }, // Changed: Cash inflows tile
@@ -937,7 +938,8 @@ class AccountingDashboardComponent {
937
938
  { name: 'cashBalance', alias: 'Cash & Bank', color: '#ff9800', icon: 'account_balance_wallet', style: 'icon', info: 'Cash + bank total' },
938
939
  ],
939
940
  loadAction: { url: 'accounts/dashboard-summary/x' },
940
- loadInit: true
941
+ loadInit: true,
942
+ security: { allow: [this.dataService.capAccountingDashboard] } // Added (dashboard-alignment 1-D.3): cap27 (datalib.service.ts:349) — a single-module dashboard, so the gate sits on the whole config
941
943
  };
942
944
  // Changed: Replaced collectionRate/invoiceStatusSplit with profitMargin/expenseBreakdown
943
945
  this.chartTiles = {
@@ -948,7 +950,8 @@ class AccountingDashboardComponent {
948
950
  { name: 'expenseTrendSpark', alias: 'Expense Trend', color: '#f44336', chart: { type: 'bar', colors: ['#f44336', '#ef5350', '#e57373', '#ef9a9a', '#ffcdd2', '#f44336'], height: 100, dataField: 'expenseTrendSpark' }, footer: 'Last 6 months', footerIcon: 'trending_down' },
949
951
  ],
950
952
  loadAction: { url: 'accounts/dashboard-chart-tiles/x' },
951
- loadInit: true
953
+ loadInit: true,
954
+ security: { allow: [this.dataService.capAccountingDashboard] } // Added (dashboard-alignment 1-D.3): cap27
952
955
  };
953
956
  // Changed: Replaced arAging/invoiceStatus with cashFlow/transactionVolume
954
957
  this.chartConfig = {
@@ -960,7 +963,8 @@ class AccountingDashboardComponent {
960
963
  ],
961
964
  loadAction: { url: 'accounts/dashboard-charts/x' },
962
965
  loadInit: true,
963
- columns: 2
966
+ columns: 2,
967
+ security: { allow: [this.dataService.capAccountingDashboard] } // Added (dashboard-alignment 1-D.3): cap27
964
968
  };
965
969
  // Changed: New cash/bank running balance line chart with separate data source
966
970
  this.cashBankChartConfig = {
@@ -970,10 +974,35 @@ class AccountingDashboardComponent {
970
974
  ],
971
975
  loadAction: { url: 'accounts/dashboard-cash-balances/x' },
972
976
  loadInit: true,
973
- columns: 1
977
+ columns: 1,
978
+ security: { allow: [this.dataService.capAccountingDashboard] } // Added (dashboard-alignment 1-D.3): cap27
979
+ };
980
+ // Added (dashboard-alignment 1-D.2): netProfit MOVED here from the main overview dashboard, which was the
981
+ // only page showing it. It keeps its own load endpoint because `accounts/dashboard-summary` does not carry
982
+ // the key; that endpoint's netProfit is gated on cap27 server-side (TinErp DashboardController, 4b4290b) —
983
+ // the same cap declared here, so the client and the server retract it together.
984
+ this.overviewTiles = {
985
+ tiles: [
986
+ { name: 'netProfit', alias: 'Net Profit (MTD)', color: '#2196f3', icon: 'account_balance', style: 'icon', info: 'MTD profit' },
987
+ ],
988
+ loadAction: { url: 'dashboard/overview/summary' },
989
+ loadInit: true,
990
+ security: { allow: [this.dataService.capAccountingDashboard] }
991
+ };
992
+ // Added (dashboard-alignment 1-D.2): healthIndicators MOVED here from the main overview dashboard. It blends
993
+ // AR and AP and has no cap of its own, so per A15 / A-0902-26 it inherits the nearest module's — cap27, which
994
+ // is exactly what the TinErp gate keys it on.
995
+ this.overviewChartConfig = {
996
+ charts: [
997
+ { name: 'healthIndicators', title: 'Business Health Indicators', type: 'doughnut', height: '300px', colors: ['#4caf50', '#e0e0e0', '#2196f3', '#e0e0e0', '#ff9800', '#e0e0e0'] },
998
+ ],
999
+ loadAction: { url: 'dashboard/overview/charts' },
1000
+ loadInit: true,
1001
+ columns: 1,
1002
+ security: { allow: [this.dataService.capAccountingDashboard] }
974
1003
  };
975
1004
  }
976
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: AccountingDashboardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1005
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: AccountingDashboardComponent, deps: [{ token: i1.DataServiceLib }], target: i0.ɵɵFactoryTarget.Component }); }
977
1006
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.14", type: AccountingDashboardComponent, isStandalone: false, selector: "spa-accounting-dashboard", ngImport: i0, template: `
978
1007
  <div class="dashboard-container">
979
1008
  <h4 class="dashboard-title"><mat-icon>account_balance</mat-icon> Accounting Dashboard</h4>
@@ -983,8 +1012,12 @@ class AccountingDashboardComponent {
983
1012
  <spa-charts [config]="chartConfig"></spa-charts>
984
1013
  <!-- Changed: Separate cash/bank balance chart with own data source -->
985
1014
  <spa-charts [config]="cashBankChartConfig"></spa-charts>
1015
+ <!-- Added (dashboard-alignment 1-D.2): MOVED DOWN from the main overview dashboard, which was the only
1016
+ page showing these two. The module dashboard is the deeper page, so they belong here. -->
1017
+ <spa-tiles [config]="overviewTiles"></spa-tiles>
1018
+ <spa-charts [config]="overviewChartConfig"></spa-charts>
986
1019
  </div>
987
- `, isInline: true, styles: [".dashboard-container{padding:16px}.dashboard-title{display:flex;align-items:center;gap:8px;margin-bottom:16px;color:#333;font-weight:500}\n"], dependencies: [{ kind: "component", type: i3$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: TilesComponent, selector: "spa-tiles", inputs: ["config", "lastSearch", "data", "reload"], outputs: ["tileActionSelected", "tileClick", "tileUnClick"] }, { kind: "component", type: ChartsComponent, selector: "spa-charts", inputs: ["config", "data", "reload"] }] }); }
1020
+ `, isInline: true, styles: [".dashboard-container{padding:16px}.dashboard-title{display:flex;align-items:center;gap:8px;margin-bottom:16px;color:#333;font-weight:500}\n"], dependencies: [{ kind: "component", type: i3$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: TilesComponent, selector: "spa-tiles", inputs: ["config", "lastSearch", "data", "reload"], outputs: ["tileActionSelected", "contentResolved", "tileClick", "tileUnClick"] }, { kind: "component", type: ChartsComponent, selector: "spa-charts", inputs: ["config", "data", "reload"], outputs: ["contentResolved"] }] }); }
988
1021
  }
989
1022
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: AccountingDashboardComponent, decorators: [{
990
1023
  type: Component,
@@ -997,15 +1030,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImpo
997
1030
  <spa-charts [config]="chartConfig"></spa-charts>
998
1031
  <!-- Changed: Separate cash/bank balance chart with own data source -->
999
1032
  <spa-charts [config]="cashBankChartConfig"></spa-charts>
1033
+ <!-- Added (dashboard-alignment 1-D.2): MOVED DOWN from the main overview dashboard, which was the only
1034
+ page showing these two. The module dashboard is the deeper page, so they belong here. -->
1035
+ <spa-tiles [config]="overviewTiles"></spa-tiles>
1036
+ <spa-charts [config]="overviewChartConfig"></spa-charts>
1000
1037
  </div>
1001
1038
  `, standalone: false, styles: [".dashboard-container{padding:16px}.dashboard-title{display:flex;align-items:center;gap:8px;margin-bottom:16px;color:#333;font-weight:500}\n"] }]
1002
- }] });
1039
+ }], ctorParameters: () => [{ type: i1.DataServiceLib }] });
1003
1040
 
1004
1041
  // Invoice module dashboard with pipeline visibility, aging, and collection KPIs
1005
1042
  class InvoiceDashboardComponent {
1006
1043
  constructor(dataService) {
1007
1044
  this.dataService = dataService;
1008
- this.attentionItems = [];
1009
1045
  // Changed: Summary tiles — invoice pipeline KPIs
1010
1046
  this.summaryTiles = {
1011
1047
  tiles: [
@@ -1017,7 +1053,8 @@ class InvoiceDashboardComponent {
1017
1053
  { name: 'avgDaysToPay', alias: 'Avg Days to Pay', color: '#7b1fa2', icon: 'schedule', style: 'icon', suffix: ' days', info: 'Average payment turnaround' },
1018
1054
  ],
1019
1055
  loadAction: { url: 'invoices/dashboard-summary/x' },
1020
- loadInit: true
1056
+ loadInit: true,
1057
+ security: { allow: [this.dataService.capInvoiceDashboard] } // Added (dashboard-alignment 1-D.3): cap53 (datalib.service.ts:470) — a single-module dashboard, so the gate sits on the whole config
1021
1058
  };
1022
1059
  // Changed: Chart tiles — collection gauge, trend sparkline, status pie, aging bar
1023
1060
  this.chartTiles = {
@@ -1028,7 +1065,8 @@ class InvoiceDashboardComponent {
1028
1065
  { name: 'agingSnapshot', alias: 'Aging Snapshot', color: '#f44336', chart: { type: 'bar', colors: ['#4caf50', '#ff9800', '#ff5722', '#f44336', '#b71c1c'], height: 100, dataField: 'agingSnapshot' }, footer: 'Outstanding by age', footerIcon: 'bar_chart' },
1029
1066
  ],
1030
1067
  loadAction: { url: 'invoices/dashboard-chart-tiles/x' },
1031
- loadInit: true
1068
+ loadInit: true,
1069
+ security: { allow: [this.dataService.capInvoiceDashboard] } // Added (dashboard-alignment 1-D.3): cap53
1032
1070
  };
1033
1071
  // Changed: Full charts — revenue pipeline, aging breakdown, top customers, payment trend
1034
1072
  this.chartConfig = {
@@ -1041,16 +1079,10 @@ class InvoiceDashboardComponent {
1041
1079
  ],
1042
1080
  loadAction: { url: 'invoices/dashboard-charts/x' },
1043
1081
  loadInit: true,
1044
- columns: 2
1082
+ columns: 2,
1083
+ security: { allow: [this.dataService.capInvoiceDashboard] } // Added (dashboard-alignment 1-D.3): cap53
1045
1084
  };
1046
1085
  }
1047
- ngOnInit() {
1048
- // Load attention items — top overdue invoices needing action
1049
- this.dataService.CallApi({ url: 'invoices/dashboard-attention/x' }).subscribe((res) => {
1050
- if (res.success)
1051
- this.attentionItems = res.data || [];
1052
- });
1053
- }
1054
1086
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: InvoiceDashboardComponent, deps: [{ token: i1.DataServiceLib }], target: i0.ɵɵFactoryTarget.Component }); }
1055
1087
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.14", type: InvoiceDashboardComponent, isStandalone: false, selector: "spa-invoice-dashboard", ngImport: i0, template: `
1056
1088
  <div class="dashboard-container">
@@ -1059,37 +1091,15 @@ class InvoiceDashboardComponent {
1059
1091
  <div style="margin-top: 16px;"></div>
1060
1092
  <spa-tiles [config]="chartTiles"></spa-tiles>
1061
1093
 
1062
- <!-- Attention Required sub-table -->
1063
- <div *ngIf="attentionItems.length > 0" class="attention-section">
1064
- <h5 class="section-title">
1065
- <mat-icon style="vertical-align: middle; margin-right: 4px; color: #f44336;">warning</mat-icon>
1066
- Needs Attention
1067
- </h5>
1068
- <table class="kpi-table">
1069
- <thead>
1070
- <tr>
1071
- <th>Invoice</th>
1072
- <th>Customer</th>
1073
- <th>Due Date</th>
1074
- <th>Days Overdue</th>
1075
- <th>Outstanding</th>
1076
- </tr>
1077
- </thead>
1078
- <tbody>
1079
- <tr *ngFor="let item of attentionItems">
1080
- <td>{{ item.invoiceNumber }}</td>
1081
- <td>{{ item.customerName }}</td>
1082
- <td>{{ item.dueDate | date:'mediumDate' }}</td>
1083
- <td style="color: #f44336; font-weight: 500;">{{ item.daysOverdue }}</td>
1084
- <td>{{ item.outstandingAmount | currency }}</td>
1085
- </tr>
1086
- </tbody>
1087
- </table>
1088
- </div>
1094
+ <!-- Removed (dashboard-alignment 1-D.4): the "Needs Attention" list of overdue invoices. A dashboard
1095
+ shows the shape of the business; the things a person has to act on live in the Day Book, which
1096
+ already carries this exact list as the overdueInvoices rule
1097
+ (TinErp Services/DayBook/DefaultDayBookProvider.cs:118, gated .Requires(cap53)) with the same five
1098
+ columns off the same DayBookMoneyRow (:405-425). Nothing was lost, only relocated. -->
1089
1099
 
1090
1100
  <spa-charts [config]="chartConfig"></spa-charts>
1091
1101
  </div>
1092
- `, isInline: true, styles: [".dashboard-container{padding:16px}.dashboard-title{display:flex;align-items:center;gap:8px;margin-bottom:16px;color:#333;font-weight:500}.attention-section{margin-top:16px}.section-title{display:flex;align-items:center;margin-bottom:8px;color:#333;font-weight:500}.kpi-table{width:100%;border-collapse:collapse;font-size:13px}.kpi-table th{text-align:left;padding:8px 12px;background:#f5f5f5;border-bottom:2px solid #e0e0e0;font-weight:500}.kpi-table td{padding:8px 12px;border-bottom:1px solid #eee}.kpi-table tr:hover{background:#fafafa}\n"], dependencies: [{ kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: TilesComponent, selector: "spa-tiles", inputs: ["config", "lastSearch", "data", "reload"], outputs: ["tileActionSelected", "tileClick", "tileUnClick"] }, { kind: "component", type: ChartsComponent, selector: "spa-charts", inputs: ["config", "data", "reload"] }, { kind: "pipe", type: i1$1.CurrencyPipe, name: "currency" }, { kind: "pipe", type: i1$1.DatePipe, name: "date" }] }); }
1102
+ `, isInline: true, styles: [".dashboard-container{padding:16px}.dashboard-title{display:flex;align-items:center;gap:8px;margin-bottom:16px;color:#333;font-weight:500}\n"], dependencies: [{ kind: "component", type: i3$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: TilesComponent, selector: "spa-tiles", inputs: ["config", "lastSearch", "data", "reload"], outputs: ["tileActionSelected", "contentResolved", "tileClick", "tileUnClick"] }, { kind: "component", type: ChartsComponent, selector: "spa-charts", inputs: ["config", "data", "reload"], outputs: ["contentResolved"] }] }); }
1093
1103
  }
1094
1104
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: InvoiceDashboardComponent, decorators: [{
1095
1105
  type: Component,
@@ -1100,37 +1110,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImpo
1100
1110
  <div style="margin-top: 16px;"></div>
1101
1111
  <spa-tiles [config]="chartTiles"></spa-tiles>
1102
1112
 
1103
- <!-- Attention Required sub-table -->
1104
- <div *ngIf="attentionItems.length > 0" class="attention-section">
1105
- <h5 class="section-title">
1106
- <mat-icon style="vertical-align: middle; margin-right: 4px; color: #f44336;">warning</mat-icon>
1107
- Needs Attention
1108
- </h5>
1109
- <table class="kpi-table">
1110
- <thead>
1111
- <tr>
1112
- <th>Invoice</th>
1113
- <th>Customer</th>
1114
- <th>Due Date</th>
1115
- <th>Days Overdue</th>
1116
- <th>Outstanding</th>
1117
- </tr>
1118
- </thead>
1119
- <tbody>
1120
- <tr *ngFor="let item of attentionItems">
1121
- <td>{{ item.invoiceNumber }}</td>
1122
- <td>{{ item.customerName }}</td>
1123
- <td>{{ item.dueDate | date:'mediumDate' }}</td>
1124
- <td style="color: #f44336; font-weight: 500;">{{ item.daysOverdue }}</td>
1125
- <td>{{ item.outstandingAmount | currency }}</td>
1126
- </tr>
1127
- </tbody>
1128
- </table>
1129
- </div>
1113
+ <!-- Removed (dashboard-alignment 1-D.4): the "Needs Attention" list of overdue invoices. A dashboard
1114
+ shows the shape of the business; the things a person has to act on live in the Day Book, which
1115
+ already carries this exact list as the overdueInvoices rule
1116
+ (TinErp Services/DayBook/DefaultDayBookProvider.cs:118, gated .Requires(cap53)) with the same five
1117
+ columns off the same DayBookMoneyRow (:405-425). Nothing was lost, only relocated. -->
1130
1118
 
1131
1119
  <spa-charts [config]="chartConfig"></spa-charts>
1132
1120
  </div>
1133
- `, standalone: false, styles: [".dashboard-container{padding:16px}.dashboard-title{display:flex;align-items:center;gap:8px;margin-bottom:16px;color:#333;font-weight:500}.attention-section{margin-top:16px}.section-title{display:flex;align-items:center;margin-bottom:8px;color:#333;font-weight:500}.kpi-table{width:100%;border-collapse:collapse;font-size:13px}.kpi-table th{text-align:left;padding:8px 12px;background:#f5f5f5;border-bottom:2px solid #e0e0e0;font-weight:500}.kpi-table td{padding:8px 12px;border-bottom:1px solid #eee}.kpi-table tr:hover{background:#fafafa}\n"] }]
1121
+ `, standalone: false, styles: [".dashboard-container{padding:16px}.dashboard-title{display:flex;align-items:center;gap:8px;margin-bottom:16px;color:#333;font-weight:500}\n"] }]
1134
1122
  }], ctorParameters: () => [{ type: i1.DataServiceLib }] });
1135
1123
 
1136
1124
  // Credit Notes page (B6) — invoice corrections/returns with GL reversal posting
@@ -1883,7 +1871,7 @@ class TenantTransfersComponent {
1883
1871
  this.tenantTransferService.transfersReload.next(true);
1884
1872
  }
1885
1873
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: TenantTransfersComponent, deps: [{ token: TenantTransferService }], target: i0.ɵɵFactoryTarget.Component }); }
1886
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.14", type: TenantTransfersComponent, isStandalone: false, selector: "spa-tenant-transfers", ngImport: i0, template: "<!-- Organisation Transfers \u2014 the handshake and the money that flows over it. Two sections in one page\n deliberately: an arrangement is meaningless without the transfers it permits, and a transfer is\n unreadable without the arrangement that authorised it. -->\n<h4>Organisation Transfers</h4>\n<hr>\n\n<div class=\"mt-3 tenant-transfers\" style=\"font-size: 14px;\">\n\n <p class=\"tt-lead\">\n Money can only move between two organisations that have <strong>agreed an arrangement</strong> first.\n One side proposes it, the other accepts it, and only then can the proposing side send.\n </p>\n\n <!-- (actionSuccess) \u2014 Send Money is a button on THIS table, so without this wire the Transfers list below\n still shows the previous rows after money has already moved. -->\n <spa-table [config]=\"tenantTransferService.linksTableConfig\" (actionSuccess)=\"arrangementActioned()\"></spa-table>\n\n <div class=\"tt-gap\"></div>\n\n <spa-table [config]=\"tenantTransferService.transfersTableConfig\" [reload]=\"tenantTransferService.transfersReload\"></spa-table>\n\n</div>\n", styles: [".tenant-transfers{max-width:100%;min-width:0}.tenant-transfers .tt-lead{max-width:74ch;margin:0 0 20px;line-height:1.55;opacity:.85;overflow-wrap:break-word}.tenant-transfers spa-table{display:block;max-width:100%;min-width:0;overflow-x:auto}.tenant-transfers .tt-gap{height:28px}\n"], dependencies: [{ kind: "component", type: TableComponent, selector: "spa-table", inputs: ["data", "tileData", "config", "localMode", "parentDetails", "reload", "activeTab", "inTab", "nestingLevel"], outputs: ["dataLoad", "totalChange", "actionSuccess", "refreshClick", "searchClick", "createClick", "actionClick", "inputChange", "actionResponse"] }] }); }
1874
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.14", type: TenantTransfersComponent, isStandalone: false, selector: "spa-tenant-transfers", ngImport: i0, template: "<!-- Organisation Transfers \u2014 the handshake and the money that flows over it. Two sections in one page\n deliberately: an arrangement is meaningless without the transfers it permits, and a transfer is\n unreadable without the arrangement that authorised it. -->\n<h4>Organisation Transfers</h4>\n<hr>\n\n<div class=\"mt-3 tenant-transfers\" style=\"font-size: 14px;\">\n\n <p class=\"tt-lead\">\n Money can only move between two organisations that have <strong>agreed an arrangement</strong> first.\n One side proposes it, the other accepts it, and only then can the proposing side send.\n </p>\n\n <!-- (actionSuccess) \u2014 Send Money is a button on THIS table, so without this wire the Transfers list below\n still shows the previous rows after money has already moved. -->\n <spa-table [config]=\"tenantTransferService.linksTableConfig\" (actionSuccess)=\"arrangementActioned()\"></spa-table>\n\n <div class=\"tt-gap\"></div>\n\n <spa-table [config]=\"tenantTransferService.transfersTableConfig\" [reload]=\"tenantTransferService.transfersReload\"></spa-table>\n\n</div>\n", styles: [".tenant-transfers{max-width:100%;min-width:0}.tenant-transfers .tt-lead{max-width:74ch;margin:0 0 20px;line-height:1.55;opacity:.85;overflow-wrap:break-word}.tenant-transfers spa-table{display:block;max-width:100%;min-width:0;overflow-x:auto}.tenant-transfers .tt-gap{height:28px}\n"], dependencies: [{ kind: "component", type: TableComponent, selector: "spa-table", inputs: ["data", "tileData", "config", "localMode", "parentDetails", "reload", "activeTab", "inTab", "nestingLevel"], outputs: ["dataLoad", "totalChange", "actionSuccess", "refreshClick", "searchClick", "createClick", "actionClick", "inputChange", "actionResponse", "contentResolved"] }] }); }
1887
1875
  }
1888
1876
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImport: i0, type: TenantTransfersComponent, decorators: [{
1889
1877
  type: Component,
@@ -2228,4 +2216,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.14", ngImpo
2228
2216
  }] });
2229
2217
 
2230
2218
  export { AccountingModule };
2231
- //# sourceMappingURL=tin-spa-accounting.module-Cg4vWaJE.mjs.map
2219
+ //# sourceMappingURL=tin-spa-accounting.module-CamqAeW_.mjs.map