- {{#if this.loadData.isRunning}}
-
+
+
+ {{#if this.error}}
+
{{this.error}}
+ {{else if this.loadData.isRunning}}
+
{{else if this.totals.length}}
- {{#each this.totals as |row|}}
-
-
-
{{row.currency}}
-
({{row.count}} wallet{{if (gt row.count 1) "s"}})
+
+ {{#each this.totals as |row|}}
+
+
+
{{row.currency}}
+
{{row.count}} wallet{{if (gt row.count 1) "s"}}
+
+
{{format-currency row.total (or row.currency this.companyCurrency)}}
+
+ {{/each}}
+
+ {{#if this.topWallets.length}}
+
+
Top Wallets
+
+ {{#each this.topWallets as |wallet index|}}
+
+ {{add index 1}}
+ {{n-a (or wallet.subject.name wallet.name wallet.wallet_public_id)}}
+ {{format-currency wallet.balance (or wallet.currency this.companyCurrency)}}
+
+ {{/each}}
-
{{format-currency row.total (or row.currency this.companyCurrency)}}
- {{/each}}
+ {{/if}}
{{else}}
-
No wallet data.
+
No wallet data.
{{/if}}
-
\ No newline at end of file
+
diff --git a/addon/components/widget/wallet-balances.js b/addon/components/widget/wallet-balances.js
index 7bdbd5f..00ba60b 100644
--- a/addon/components/widget/wallet-balances.js
+++ b/addon/components/widget/wallet-balances.js
@@ -6,7 +6,10 @@ import { task } from 'ember-concurrency';
export default class WidgetWalletBalancesComponent extends Component {
@service fetch;
@service currentUser;
+ @service ledgerDashboard;
@tracked totals = null;
+ @tracked topWallets = [];
+ @tracked error = null;
get companyCurrency() {
return this.currentUser.company?.currency ?? this.currentUser.whoisData?.currency?.code ?? 'USD';
@@ -14,15 +17,26 @@ export default class WidgetWalletBalancesComponent extends Component {
constructor() {
super(...arguments);
+ this.unsubscribeDashboard = this.ledgerDashboard.subscribe(() => this.loadData.perform());
this.loadData.perform();
}
@task *loadData() {
try {
- const response = yield this.fetch.get('reports/dashboard', {}, { namespace: 'ledger/int/v1' });
- this.totals = response?.data?.kpis?.wallet_totals ?? null;
- } catch {
+ const response = yield this.fetch.get('reports/dashboard/wallet-balances', this.ledgerDashboard.walletPeriodParams, { namespace: 'ledger/int/v1' });
+ const data = response?.data ?? response;
+ this.totals = data?.totals ?? [];
+ this.topWallets = data?.top_wallets ?? [];
+ this.error = null;
+ } catch (error) {
this.totals = null;
+ this.topWallets = [];
+ this.error = error?.message ?? 'Unable to load wallet balances';
}
}
+
+ willDestroy() {
+ super.willDestroy(...arguments);
+ this.unsubscribeDashboard?.();
+ }
}
diff --git a/addon/controllers/billing/invoices/index.js b/addon/controllers/billing/invoices/index.js
index 0f5c2eb..b4344a4 100644
--- a/addon/controllers/billing/invoices/index.js
+++ b/addon/controllers/billing/invoices/index.js
@@ -1,10 +1,12 @@
import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
+import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
export default class BillingInvoicesIndexController extends Controller {
@service invoiceActions;
@service tableContext;
+ @service hostRouter;
@service intl;
@tracked queryParams = ['page', 'limit', 'sort', 'query', 'status', 'customer_uuid'];
@@ -63,6 +65,14 @@ export default class BillingInvoicesIndexController extends Controller {
resizable: true,
sortable: false,
},
+ {
+ label: 'Order',
+ valuePath: 'orderTrackingLabel',
+ cellComponent: 'table/cell/anchor',
+ action: this.viewOrder,
+ resizable: true,
+ sortable: false,
+ },
{
label: this.intl.t('column.status'),
valuePath: 'status',
@@ -174,4 +184,13 @@ export default class BillingInvoicesIndexController extends Controller {
},
];
}
+
+ @action viewOrder(invoice) {
+ const orderId = invoice?.orderRouteIdentifier;
+ if (!orderId) {
+ return;
+ }
+
+ return this.hostRouter.transitionTo('console.fleet-ops.operations.orders.index.details', orderId);
+ }
}
diff --git a/addon/extension.js b/addon/extension.js
index 1b00b28..9e93eb7 100644
--- a/addon/extension.js
+++ b/addon/extension.js
@@ -100,6 +100,20 @@ export default {
})
);
+ // ── Storefront order details tab: Invoice ────────────────────────────
+ // Reuses the same order-invoice component inside the Storefront order
+ // details panel so commerce orders expose their generated invoice.
+ menuService.registerMenuItem(
+ 'storefront:component:order:details',
+ new MenuItem({
+ title: 'Invoice',
+ route: 'orders.index.view.virtual',
+ component: new ExtensionComponent('@fleetbase/ledger-engine', 'order-invoice'),
+ icon: 'file-invoice-dollar',
+ slug: 'invoice',
+ })
+ );
+
// Register dashboard and widgets
this.registerWidgets(widgetService);
},
@@ -107,86 +121,211 @@ export default {
registerWidgets(widgetService) {
const widgets = [
new Widget({
- id: 'ledger-overview',
- name: 'Financial Overview',
- description: 'Key financial KPIs: revenue, expenses, net income, and outstanding AR for the current period.',
- icon: 'gauge-high',
- component: new ExtensionComponent('@fleetbase/ledger-engine', 'widget/overview'),
- grid_options: { w: 12, h: 4, minW: 8, minH: 4 },
- options: { title: 'Financial Overview' },
+ id: 'ledger-kpi-revenue',
+ name: 'Revenue',
+ description: 'Total revenue for the current period with comparison.',
+ icon: 'sack-dollar',
+ component: new ExtensionComponent('@fleetbase/ledger-engine', 'widget/kpi-revenue'),
+ grid_options: { w: 3, h: 4, minW: 3, minH: 4 },
+ category: 'KPI Tiles',
default: true,
}),
-
new Widget({
- id: 'ledger-revenue-chart',
- name: 'Revenue Chart',
- description: 'Daily revenue trend chart for the current period.',
+ id: 'ledger-kpi-expenses',
+ name: 'Expenses',
+ description: 'Total expenses for the current period with comparison.',
+ icon: 'receipt',
+ component: new ExtensionComponent('@fleetbase/ledger-engine', 'widget/kpi-expenses'),
+ grid_options: { w: 3, h: 4, minW: 3, minH: 4 },
+ category: 'KPI Tiles',
+ default: true,
+ }),
+ new Widget({
+ id: 'ledger-kpi-net-income',
+ name: 'Net Income',
+ description: 'Revenue less expenses for the current period.',
icon: 'chart-line',
- component: new ExtensionComponent('@fleetbase/ledger-engine', 'widget/revenue-chart'),
- grid_options: { w: 8, h: 7, minW: 6, minH: 6 },
- options: { title: 'Revenue Chart' },
+ component: new ExtensionComponent('@fleetbase/ledger-engine', 'widget/kpi-net-income'),
+ grid_options: { w: 3, h: 4, minW: 3, minH: 4 },
+ category: 'KPI Tiles',
default: true,
}),
-
new Widget({
- id: 'ledger-invoice-summary',
- name: 'Invoice Summary',
- description: 'Breakdown of invoices by status: draft, sent, paid, overdue, and cancelled.',
+ id: 'ledger-kpi-outstanding-ar',
+ name: 'Outstanding AR',
+ description: 'Unpaid receivables balance across open invoices.',
icon: 'file-invoice-dollar',
- component: new ExtensionComponent('@fleetbase/ledger-engine', 'widget/invoice-summary'),
- grid_options: { w: 4, h: 6, minW: 3, minH: 5 },
- options: { title: 'Invoice Summary' },
+ component: new ExtensionComponent('@fleetbase/ledger-engine', 'widget/kpi-outstanding-ar'),
+ grid_options: { w: 3, h: 4, minW: 3, minH: 4 },
+ category: 'KPI Tiles',
+ default: true,
+ }),
+ new Widget({
+ id: 'ledger-kpi-overdue-ar',
+ name: 'Overdue AR',
+ description: 'Overdue receivables requiring collection attention.',
+ icon: 'clock',
+ component: new ExtensionComponent('@fleetbase/ledger-engine', 'widget/kpi-overdue-ar'),
+ grid_options: { w: 3, h: 4, minW: 3, minH: 4 },
+ category: 'KPI Tiles',
+ default: true,
+ }),
+ new Widget({
+ id: 'ledger-kpi-open-invoices',
+ name: 'Open Invoices',
+ description: 'Draft, sent, and overdue invoices still requiring action.',
+ icon: 'file-circle-exclamation',
+ component: new ExtensionComponent('@fleetbase/ledger-engine', 'widget/kpi-open-invoices'),
+ grid_options: { w: 3, h: 4, minW: 3, minH: 4 },
+ category: 'KPI Tiles',
+ default: true,
+ }),
+ new Widget({
+ id: 'ledger-kpi-wallet-balance',
+ name: 'Wallet Balance',
+ description: 'Active wallet balances, grouped by currency when needed.',
+ icon: 'wallet',
+ component: new ExtensionComponent('@fleetbase/ledger-engine', 'widget/kpi-wallet-balance'),
+ grid_options: { w: 3, h: 4, minW: 3, minH: 4 },
+ category: 'KPI Tiles',
+ default: true,
+ }),
+ new Widget({
+ id: 'ledger-kpi-active-wallets',
+ name: 'Active Wallets',
+ description: 'Count of active wallets with current balances.',
+ icon: 'wallet',
+ component: new ExtensionComponent('@fleetbase/ledger-engine', 'widget/kpi-active-wallets'),
+ grid_options: { w: 3, h: 4, minW: 3, minH: 4 },
+ category: 'KPI Tiles',
default: true,
}),
+ new Widget({
+ id: 'ledger-revenue-trend',
+ name: 'Revenue Trend',
+ description: 'Revenue and expense trend over selectable periods.',
+ icon: 'chart-line',
+ component: new ExtensionComponent('@fleetbase/ledger-engine', 'widget/revenue-trend'),
+ grid_options: { w: 6, h: 9, minW: 5, minH: 8 },
+ category: 'Analytics',
+ default: true,
+ }),
+ new Widget({
+ id: 'ledger-cash-flow-summary',
+ name: 'Cash Flow Summary',
+ description: 'Operating, financing, and investing cash movement.',
+ icon: 'money-bill-transfer',
+ component: new ExtensionComponent('@fleetbase/ledger-engine', 'widget/cash-flow-summary'),
+ grid_options: { w: 6, h: 9, minW: 5, minH: 8 },
+ category: 'Analytics',
+ default: true,
+ }),
+ new Widget({
+ id: 'ledger-invoice-status',
+ name: 'Invoice Pipeline',
+ description: 'Counts and balances by invoice status.',
+ icon: 'file-invoice-dollar',
+ component: new ExtensionComponent('@fleetbase/ledger-engine', 'widget/invoice-status'),
+ grid_options: { w: 4, h: 8, minW: 4, minH: 7 },
+ category: 'Operations',
+ default: true,
+ }),
+ new Widget({
+ id: 'ledger-ar-aging-summary',
+ name: 'AR Aging Risk',
+ description: 'Condensed accounts receivable aging buckets.',
+ icon: 'clock',
+ component: new ExtensionComponent('@fleetbase/ledger-engine', 'widget/ar-aging-summary'),
+ grid_options: { w: 4, h: 8, minW: 4, minH: 7 },
+ category: 'Operations',
+ default: true,
+ }),
new Widget({
id: 'ledger-wallet-balances',
name: 'Wallet Balances',
description: 'Total wallet balances grouped by currency across all driver and customer wallets.',
icon: 'wallet',
component: new ExtensionComponent('@fleetbase/ledger-engine', 'widget/wallet-balances'),
- grid_options: { w: 4, h: 5, minW: 3, minH: 4 },
- options: { title: 'Wallet Balances' },
+ grid_options: { w: 4, h: 8, minW: 4, minH: 7 },
+ category: 'Operations',
default: true,
}),
-
new Widget({
id: 'ledger-activity-feed',
- name: 'Recent Journal Entries',
+ name: 'Recent Financial Activity',
description: 'Live feed of the most recent double-entry journal entries in the ledger.',
icon: 'book',
component: new ExtensionComponent('@fleetbase/ledger-engine', 'widget/activity-feed'),
- grid_options: { w: 8, h: 11, minW: 6, minH: 8 },
- options: { title: 'Recent Journal Entries' },
+ grid_options: { w: 8, h: 10, minW: 6, minH: 8 },
+ category: 'Operations',
default: true,
}),
-
new Widget({
- id: 'ledger-ar-aging',
- name: 'AR Aging Summary',
- description: 'Accounts receivable aging buckets: current, 1–30, 31–60, 61–90, and 90+ days overdue.',
- icon: 'clock',
- component: new ExtensionComponent('@fleetbase/ledger-engine', 'widget/ar-aging'),
- grid_options: { w: 6, h: 5, minW: 5, minH: 4 },
- options: { title: 'AR Aging Summary' },
+ id: 'ledger-report-shortcuts',
+ name: 'Financial Reports',
+ description: 'Shortcuts into Ledger financial reports.',
+ icon: 'file-lines',
+ component: new ExtensionComponent('@fleetbase/ledger-engine', 'widget/report-shortcuts'),
+ grid_options: { w: 4, h: 10, minW: 4, minH: 7 },
+ category: 'Reports',
+ default: true,
}),
new Widget({
- id: 'ledger-top-wallets',
- name: 'Top Driver Wallets',
- description: 'Leaderboard of the top 10 driver wallets by current balance.',
- icon: 'ranking-star',
- component: new ExtensionComponent('@fleetbase/ledger-engine', 'widget/top-wallets'),
- grid_options: { w: 6, h: 6, minW: 4, minH: 5 },
- options: { title: 'Top Driver Wallets' },
+ id: 'ledger-overview',
+ name: 'Financial Overview (Legacy)',
+ description: 'Legacy grouped KPI widget. Replaced by individual Ledger KPI tiles.',
+ icon: 'gauge-high',
+ component: new ExtensionComponent('@fleetbase/ledger-engine', 'widget/overview'),
+ grid_options: { w: 12, h: 4, minW: 8, minH: 4 },
+ options: { title: 'Financial Overview' },
+ category: 'Legacy',
+ default: false,
+ }),
+ new Widget({
+ id: 'ledger-revenue-chart',
+ name: 'Revenue Chart (Legacy)',
+ description: 'Legacy daily revenue bar widget. Replaced by Revenue Trend.',
+ icon: 'chart-line',
+ component: new ExtensionComponent('@fleetbase/ledger-engine', 'widget/revenue-chart'),
+ grid_options: { w: 8, h: 6, minW: 6, minH: 6 },
+ options: { title: 'Revenue Chart' },
+ category: 'Legacy',
+ default: false,
+ }),
+ new Widget({
+ id: 'ledger-invoice-summary',
+ name: 'Invoice Summary (Legacy)',
+ description: 'Legacy invoice counts widget. Replaced by Invoice Pipeline.',
+ icon: 'file-invoice-dollar',
+ component: new ExtensionComponent('@fleetbase/ledger-engine', 'widget/invoice-summary'),
+ grid_options: { w: 4, h: 6, minW: 3, minH: 5 },
+ options: { title: 'Invoice Summary' },
+ category: 'Legacy',
+ default: false,
}),
];
+ const getWidgetById = (id = null, mutate = null) => {
+ if (!id) return null;
+ const widget = widgets.find((w) => w.id === id);
+ if (typeof mutate === 'function') {
+ mutate(widget);
+ }
+ return widget;
+ };
+
widgetService.registerDashboard('ledger');
widgetService.registerWidgets('ledger', widgets);
- widgetService.registerWidgets(
- 'dashboard',
- widgets.filter((w) => ['ledger-overview', 'ledger-revenue-chart', 'ledger-invoice-summary'].includes(w.id))
- );
+ widgetService.registerWidgets('dashboard', [
+ getWidgetById('ledger-activity-feed', (widget) => {
+ widget.withGridOptions({ w: 6, minW: 6, h: 8, minH: 8 });
+ }),
+ getWidgetById('ledger-kpi-revenue'),
+ getWidgetById('ledger-kpi-net-income'),
+ getWidgetById('ledger-kpi-outstanding-ar'),
+ getWidgetById('ledger-kpi-expenses'),
+ ]);
},
};
diff --git a/addon/models/ledger-invoice.js b/addon/models/ledger-invoice.js
index a7b417d..f89c23f 100644
--- a/addon/models/ledger-invoice.js
+++ b/addon/models/ledger-invoice.js
@@ -16,6 +16,8 @@ export default class LedgerInvoiceModel extends Model {
@attr('string') customer_uuid;
@attr('string') customer_type;
@attr('string') order_uuid;
+ @attr('string') order_public_id;
+ @attr('string') order_tracking_number;
@attr('string') transaction_uuid;
@attr('string') template_uuid;
@@ -64,6 +66,14 @@ export default class LedgerInvoiceModel extends Model {
return this.total_amount;
}
+ @computed('order_tracking_number', 'order_public_id', 'order_uuid') get orderTrackingLabel() {
+ return this.order_tracking_number ?? this.order_public_id ?? this.order_uuid;
+ }
+
+ @computed('order_public_id', 'order_uuid') get orderRouteIdentifier() {
+ return this.order_public_id ?? this.order_uuid;
+ }
+
// -------------------------------------------------------------------------
// Customer convenience accessors
// -------------------------------------------------------------------------
diff --git a/addon/services/ledger-dashboard.js b/addon/services/ledger-dashboard.js
new file mode 100644
index 0000000..6c525f0
--- /dev/null
+++ b/addon/services/ledger-dashboard.js
@@ -0,0 +1,94 @@
+import Service from '@ember/service';
+import { tracked } from '@glimmer/tracking';
+
+function formatDate(date) {
+ const year = date.getFullYear();
+ const month = `${date.getMonth() + 1}`.padStart(2, '0');
+ const day = `${date.getDate()}`.padStart(2, '0');
+
+ return `${year}-${month}-${day}`;
+}
+
+export default class LedgerDashboardService extends Service {
+ @tracked startDate = null;
+ @tracked endDate = null;
+ @tracked dateRange = null;
+ @tracked version = 0;
+
+ subscribers = new Set();
+
+ constructor() {
+ super(...arguments);
+ this.resetPeriod({ notify: false });
+ }
+
+ get periodParams() {
+ return {
+ start_date: this.startDate,
+ end_date: this.endDate,
+ };
+ }
+
+ get walletPeriodParams() {
+ return {
+ date_from: this.startDate,
+ date_to: this.endDate,
+ };
+ }
+
+ get asOfParams() {
+ return {
+ as_of_date: this.endDate,
+ };
+ }
+
+ get periodLabel() {
+ return this.startDate && this.endDate ? `${this.startDate} - ${this.endDate}` : 'Month to date';
+ }
+
+ get dateRangeValue() {
+ return this.startDate && this.endDate ? `${this.startDate},${this.endDate}` : null;
+ }
+
+ setDateRange({ formattedDate } = {}) {
+ if (Array.isArray(formattedDate) && formattedDate.length === 2) {
+ this.setPeriod(formattedDate[0], formattedDate[1]);
+ return;
+ }
+
+ this.resetPeriod();
+ }
+
+ setPeriod(startDate, endDate) {
+ this.startDate = startDate;
+ this.endDate = endDate;
+ this.dateRange = [startDate, endDate];
+ this.notify();
+ }
+
+ resetPeriod({ notify = true } = {}) {
+ const today = new Date();
+ const start = new Date(today.getFullYear(), today.getMonth(), 1);
+
+ this.startDate = formatDate(start);
+ this.endDate = formatDate(today);
+ this.dateRange = [this.startDate, this.endDate];
+
+ if (notify) {
+ this.notify();
+ }
+ }
+
+ subscribe(callback) {
+ this.subscribers.add(callback);
+
+ return () => {
+ this.subscribers.delete(callback);
+ };
+ }
+
+ notify() {
+ this.version++;
+ this.subscribers.forEach((callback) => callback(this));
+ }
+}
diff --git a/addon/styles/ledger-engine.css b/addon/styles/ledger-engine.css
index dcfb8d4..33f6ee9 100644
--- a/addon/styles/ledger-engine.css
+++ b/addon/styles/ledger-engine.css
@@ -46,3 +46,581 @@
.ledger-template-builder-outlet:empty {
display: none;
}
+
+.ledger-dashboard-widget {
+ animation: ledger-widget-fade-up 360ms cubic-bezier(0.16, 1, 0.3, 1) both;
+ border-color: #e5e7eb;
+ background-color: #fff;
+ transition:
+ border-color 180ms ease,
+ box-shadow 180ms ease,
+ transform 180ms ease;
+}
+
+.ledger-dashboard-widget:hover {
+ border-color: #cbd5e1;
+ box-shadow: 0 10px 28px -22px rgb(15 23 42 / 45%);
+}
+
+@keyframes ledger-widget-fade-up {
+ from {
+ opacity: 0;
+ transform: translateY(10px);
+ }
+
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+.ledger-dashboard-page {
+ display: flex;
+ width: 100%;
+ align-items: center;
+ justify-content: space-between;
+ gap: 1rem;
+ border-bottom: 1px solid #e5e7eb;
+ background-color: #fff;
+ padding: 1rem;
+ box-shadow: 0 1px 2px rgb(15 23 42 / 6%);
+}
+
+body[data-theme='dark'] .ledger-dashboard-page {
+ border-bottom-color: #1f2937;
+ background-color: #111827;
+ box-shadow: 0 1px 2px rgb(2 6 23 / 30%);
+}
+
+.ledger-dashboard-title h1 {
+ color: #111827;
+ font-size: 1.05rem;
+ font-weight: 800;
+ line-height: 1.2;
+}
+
+body[data-theme='dark'] .ledger-dashboard-title h1 {
+ color: #f9fafb;
+}
+
+.ledger-dashboard-actions {
+ justify-content: flex-end;
+}
+
+.ledger-dashboard-period-control {
+ display: flex;
+ min-width: 0;
+}
+
+.ledger-dashboard-period-control .fleetbase-date-picker,
+.ledger-dashboard-period-control .form-input,
+.ledger-dashboard-period-control button.btn {
+ min-height: 30px !important;
+ height: 30px !important;
+}
+
+.ledger-dashboard-create-wrapper {
+ padding: 1rem;
+}
+
+body[data-theme='dark'] .ledger-dashboard-widget {
+ border-color: #374151;
+ background-color: #1f2937;
+}
+
+.ledger-widget-header {
+ display: flex;
+ min-height: 3.25rem;
+ align-items: center;
+ justify-content: space-between;
+ gap: 0.75rem;
+ border-bottom: 1px solid #e5e7eb;
+ padding: 0.75rem;
+}
+
+body[data-theme='dark'] .ledger-widget-header {
+ border-bottom-color: #374151;
+}
+
+.ledger-widget-title {
+ overflow: hidden;
+ color: #111827;
+ font-size: 0.82rem;
+ font-weight: 800;
+ line-height: 1.2;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+body[data-theme='dark'] .ledger-widget-title {
+ color: #f9fafb;
+}
+
+.ledger-widget-subtitle {
+ margin-top: 0.15rem;
+ overflow: hidden;
+ color: #6b7280;
+ font-size: 0.69rem;
+ line-height: 1.25;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+body[data-theme='dark'] .ledger-widget-subtitle {
+ color: #9ca3af;
+}
+
+.ledger-widget-body {
+ min-height: 0;
+ flex: 1 1 auto;
+ overflow: auto;
+ padding: 0.9rem;
+}
+
+.ledger-widget-empty {
+ display: flex;
+ min-height: 7rem;
+ flex: 1 1 auto;
+ align-items: center;
+ justify-content: center;
+ padding: 1rem;
+ text-align: center;
+ color: #9ca3af;
+ font-size: 0.8rem;
+}
+
+.ledger-icon-button {
+ display: inline-flex;
+ height: 1.75rem;
+ width: 1.75rem;
+ align-items: center;
+ justify-content: center;
+ border-radius: 0.375rem;
+ color: #64748b;
+}
+
+.ledger-icon-button:hover {
+ background-color: #f1f5f9;
+ color: #334155;
+}
+
+body[data-theme='dark'] .ledger-icon-button:hover {
+ background-color: #374151;
+ color: #e5e7eb;
+}
+
+.ledger-kpi-tile {
+ transition:
+ transform 160ms ease-out,
+ box-shadow 160ms ease-out,
+ border-color 160ms ease-out;
+}
+
+.ledger-kpi-tile:hover {
+ transform: translateY(-1px);
+ box-shadow: 0 8px 24px -12px rgb(15 23 42 / 35%);
+}
+
+.ledger-kpi-value-loaded {
+ animation: ledger-kpi-pop 380ms cubic-bezier(0.16, 1, 0.3, 1) both;
+}
+
+.ledger-kpi-footer {
+ animation: ledger-row-fade-in 320ms ease-out 80ms both;
+}
+
+@keyframes ledger-kpi-pop {
+ 0% {
+ opacity: 0;
+ transform: translateY(4px) scale(0.98);
+ }
+
+ 70% {
+ transform: translateY(0) scale(1.012);
+ }
+
+ 100% {
+ opacity: 1;
+ transform: translateY(0) scale(1);
+ }
+}
+
+.ledger-kpi-value {
+ color: #111827;
+ font-size: 1.55rem;
+ font-weight: 800;
+ line-height: 1.05;
+}
+
+body[data-theme='dark'] .ledger-kpi-value {
+ color: #f9fafb;
+}
+
+.ledger-kpi-icon {
+ width: 2rem;
+ height: 2rem;
+ color: #64748b;
+ background-color: rgb(100 116 139 / 12%);
+}
+
+.ledger-kpi-delta {
+ color: #475569;
+ background-color: rgb(100 116 139 / 12%);
+}
+
+.ledger-kpi-trend-good .ledger-kpi-delta {
+ color: #047857;
+ background-color: rgb(16 185 129 / 12%);
+}
+
+.ledger-kpi-trend-bad .ledger-kpi-delta {
+ color: #be123c;
+ background-color: rgb(244 63 94 / 12%);
+}
+
+.ledger-kpi-accent-green {
+ border-color: rgb(16 185 129 / 28%);
+ background-image: linear-gradient(135deg, rgb(16 185 129 / 10%) 0%, rgb(16 185 129 / 0%) 62%);
+}
+
+.ledger-kpi-accent-blue {
+ border-color: rgb(59 130 246 / 28%);
+ background-image: linear-gradient(135deg, rgb(59 130 246 / 10%) 0%, rgb(59 130 246 / 0%) 62%);
+}
+
+.ledger-kpi-accent-amber {
+ border-color: rgb(245 158 11 / 32%);
+ background-image: linear-gradient(135deg, rgb(245 158 11 / 12%) 0%, rgb(245 158 11 / 0%) 62%);
+}
+
+.ledger-kpi-accent-rose {
+ border-color: rgb(244 63 94 / 28%);
+ background-image: linear-gradient(135deg, rgb(244 63 94 / 10%) 0%, rgb(244 63 94 / 0%) 62%);
+}
+
+.ledger-kpi-accent-violet {
+ border-color: rgb(139 92 246 / 26%);
+ background-image: linear-gradient(135deg, rgb(139 92 246 / 10%) 0%, rgb(139 92 246 / 0%) 62%);
+}
+
+.ledger-chart-widget {
+ overflow: hidden;
+}
+
+.ledger-dashboard-widget .ui-chart {
+ position: relative;
+ width: 100%;
+ height: 100%;
+ min-height: 0;
+}
+
+.ledger-chart-body {
+ display: flex;
+ min-height: 0;
+ min-width: 0;
+ flex: 1 1 auto;
+ align-items: stretch;
+ justify-content: stretch;
+ padding: 0.75rem;
+}
+
+.ledger-chart-frame {
+ position: relative;
+ min-height: 0;
+ width: 100%;
+ flex: 1 1 auto;
+ animation: ledger-chart-reveal 420ms cubic-bezier(0.16, 1, 0.3, 1) both;
+}
+
+@keyframes ledger-chart-reveal {
+ from {
+ opacity: 0;
+ transform: scale(0.985);
+ }
+
+ to {
+ opacity: 1;
+ transform: scale(1);
+ }
+}
+
+.ledger-dashboard-widget .ui-chart > canvas {
+ position: absolute;
+ inset: 0;
+ width: 100% !important;
+ height: 100% !important;
+}
+
+.ledger-period-switcher {
+ display: inline-flex;
+ gap: 0.15rem;
+ border-radius: 0.45rem;
+ background-color: #f1f5f9;
+ padding: 0.15rem;
+}
+
+body[data-theme='dark'] .ledger-period-switcher {
+ background-color: #111827;
+}
+
+.ledger-period-switcher button {
+ border-radius: 0.35rem;
+ padding: 0.2rem 0.45rem;
+ color: #64748b;
+ font-size: 0.62rem;
+ font-weight: 800;
+}
+
+.ledger-period-switcher button.active {
+ background-color: #2563eb;
+ color: #fff;
+}
+
+.ledger-progress-track {
+ height: 0.45rem;
+ overflow: hidden;
+ border-radius: 999px;
+ background-color: #eef2f7;
+}
+
+body[data-theme='dark'] .ledger-progress-track {
+ background-color: #111827;
+}
+
+.ledger-progress-bar {
+ animation: ledger-progress-fill 520ms cubic-bezier(0.16, 1, 0.3, 1) both;
+ height: 100%;
+ min-width: 0.35rem;
+ border-radius: inherit;
+ background-color: #2563eb;
+ transform-origin: left center;
+}
+
+@keyframes ledger-progress-fill {
+ from {
+ transform: scaleX(0);
+ }
+
+ to {
+ transform: scaleX(1);
+ }
+}
+
+.ledger-status-paid,
+.ledger-aging-current {
+ background-color: #059669;
+}
+
+.ledger-status-overdue,
+.ledger-aging-61-90,
+.ledger-aging-over-90 {
+ background-color: #dc2626;
+}
+
+.ledger-status-sent,
+.ledger-aging-1-30 {
+ background-color: #2563eb;
+}
+
+.ledger-status-draft,
+.ledger-status-cancelled,
+.ledger-status-void {
+ background-color: #94a3b8;
+}
+
+.ledger-aging-31-60 {
+ background-color: #d97706;
+}
+
+.ledger-balance-row {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 0.75rem;
+ border-radius: 0.5rem;
+ border: 1px solid #e5e7eb;
+ padding: 0.65rem;
+ transition:
+ border-color 160ms ease,
+ background-color 160ms ease,
+ transform 160ms ease;
+}
+
+.ledger-balance-row:hover {
+ border-color: #bfdbfe;
+ background-color: #f8fafc;
+ transform: translateX(2px);
+}
+
+body[data-theme='dark'] .ledger-balance-row {
+ border-color: #374151;
+}
+
+body[data-theme='dark'] .ledger-balance-row:hover {
+ border-color: #1d4ed8;
+ background-color: rgb(17 24 39 / 58%);
+}
+
+.ledger-activity-icon {
+ display: flex;
+ height: 1.65rem;
+ width: 1.65rem;
+ flex-shrink: 0;
+ align-items: center;
+ justify-content: center;
+ border-radius: 0.45rem;
+ color: #2563eb;
+ background-color: rgb(37 99 235 / 10%);
+}
+
+.ledger-report-grid {
+ display: grid;
+ grid-template-columns: repeat(1, minmax(0, 1fr));
+ gap: 0.5rem;
+}
+
+.ledger-report-body {
+ overflow-x: hidden;
+}
+
+.ledger-report-link {
+ display: flex;
+ min-width: 0;
+ align-items: center;
+ gap: 0.65rem;
+ border-radius: 0.5rem;
+ border: 1px solid #e5e7eb;
+ padding: 0.7rem;
+ color: #374151;
+ font-size: 0.8rem;
+ font-weight: 700;
+ transition:
+ border-color 160ms ease,
+ background-color 160ms ease,
+ color 160ms ease,
+ transform 160ms ease;
+}
+
+.ledger-report-label {
+ min-width: 0;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.ledger-report-link:hover {
+ border-color: #93c5fd;
+ background-color: #eff6ff;
+ color: #1d4ed8;
+ transform: translateX(2px);
+}
+
+body[data-theme='dark'] .ledger-report-link {
+ border-color: #374151;
+ color: #d1d5db;
+}
+
+body[data-theme='dark'] .ledger-report-link:hover {
+ border-color: #2563eb;
+ background-color: rgb(37 99 235 / 12%);
+ color: #bfdbfe;
+}
+
+.ledger-animated-row {
+ animation: ledger-row-fade-in 340ms cubic-bezier(0.16, 1, 0.3, 1) both;
+}
+
+.ledger-animated-row:nth-child(1) {
+ animation-delay: 40ms;
+}
+
+.ledger-animated-row:nth-child(2) {
+ animation-delay: 80ms;
+}
+
+.ledger-animated-row:nth-child(3) {
+ animation-delay: 120ms;
+}
+
+.ledger-animated-row:nth-child(4) {
+ animation-delay: 160ms;
+}
+
+.ledger-animated-row:nth-child(5) {
+ animation-delay: 200ms;
+}
+
+.ledger-animated-row:nth-child(6) {
+ animation-delay: 240ms;
+}
+
+.ledger-animated-row:nth-child(7) {
+ animation-delay: 280ms;
+}
+
+.ledger-animated-row:nth-child(8) {
+ animation-delay: 320ms;
+}
+
+.ledger-animated-row:nth-child(9) {
+ animation-delay: 360ms;
+}
+
+.ledger-animated-row:nth-child(10) {
+ animation-delay: 400ms;
+}
+
+@keyframes ledger-row-fade-in {
+ from {
+ opacity: 0;
+ transform: translateY(7px);
+ }
+
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+@media (prefers-reduced-motion: reduce) {
+ .ledger-dashboard-widget,
+ .ledger-kpi-value-loaded,
+ .ledger-kpi-footer,
+ .ledger-chart-frame,
+ .ledger-progress-bar,
+ .ledger-animated-row {
+ animation: none !important;
+ }
+
+ .ledger-dashboard-widget,
+ .ledger-kpi-tile,
+ .ledger-balance-row,
+ .ledger-report-link {
+ transition: none !important;
+ }
+
+ .ledger-dashboard-widget,
+ .ledger-dashboard-widget:hover,
+ .ledger-kpi-tile:hover,
+ .ledger-balance-row:hover,
+ .ledger-report-link:hover {
+ transform: none !important;
+ }
+}
+
+@media (width <= 767px) {
+ .ledger-dashboard-page {
+ align-items: flex-start;
+ flex-direction: column;
+ }
+
+ .ledger-dashboard-actions {
+ width: 100%;
+ justify-content: flex-start;
+ }
+
+ .ledger-dashboard-period-control,
+ .ledger-dashboard-period-control .form-input {
+ width: 100%;
+ }
+}
diff --git a/addon/templates/billing/invoices/index/details.hbs b/addon/templates/billing/invoices/index/details.hbs
index 1484ea8..a53eb07 100644
--- a/addon/templates/billing/invoices/index/details.hbs
+++ b/addon/templates/billing/invoices/index/details.hbs
@@ -7,7 +7,7 @@
@onOverlayReady={{fn (mut this.overlay)}}
@headerClass="no-bottom-border"
@bodyClass="no-scroll"
- @width="900px"
+ @width="700px"
>
{{outlet}}
diff --git a/addon/templates/billing/invoices/index/edit.hbs b/addon/templates/billing/invoices/index/edit.hbs
index ea490fc..b49e2f3 100644
--- a/addon/templates/billing/invoices/index/edit.hbs
+++ b/addon/templates/billing/invoices/index/edit.hbs
@@ -6,7 +6,7 @@
@saveTask={{this.save}}
@onPressCancel={{this.cancel}}
@onOverlayReady={{fn (mut this.overlay)}}
- @width="900px"
+ @width="700px"
>
diff --git a/addon/templates/billing/invoices/index/new.hbs b/addon/templates/billing/invoices/index/new.hbs
index 3628831..55ae7ed 100644
--- a/addon/templates/billing/invoices/index/new.hbs
+++ b/addon/templates/billing/invoices/index/new.hbs
@@ -7,7 +7,7 @@
@saveTask={{this.save}}
@onPressCancel={{transition-to "billing.invoices.index"}}
@onOverlayReady={{fn (mut this.overlay)}}
- @width="900px"
+ @width="700px"
>
diff --git a/addon/templates/home.hbs b/addon/templates/home.hbs
index d3a8ccf..2c8c8e4 100644
--- a/addon/templates/home.hbs
+++ b/addon/templates/home.hbs
@@ -1,5 +1,16 @@
-
+
+
+
{{outlet}}
-
\ No newline at end of file
+
diff --git a/app/components/ledger-dashboard/date-range-control.js b/app/components/ledger-dashboard/date-range-control.js
new file mode 100644
index 0000000..16f5e2c
--- /dev/null
+++ b/app/components/ledger-dashboard/date-range-control.js
@@ -0,0 +1 @@
+export { default } from '@fleetbase/ledger-engine/components/ledger-dashboard/date-range-control';
diff --git a/app/components/ledger/dashboard/activity-feed.js b/app/components/ledger/dashboard/activity-feed.js
index 939b4ae..fef087f 100644
--- a/app/components/ledger/dashboard/activity-feed.js
+++ b/app/components/ledger/dashboard/activity-feed.js
@@ -1 +1 @@
-export { default } from '@fleetbase/ledger-engine/components/dashboard/activity-feed';
+export { default } from '@fleetbase/ledger-engine/components/widget/activity-feed';
diff --git a/app/components/ledger/dashboard/invoice-summary.js b/app/components/ledger/dashboard/invoice-summary.js
index 9c2afc3..2e61b2a 100644
--- a/app/components/ledger/dashboard/invoice-summary.js
+++ b/app/components/ledger/dashboard/invoice-summary.js
@@ -1 +1 @@
-export { default } from '@fleetbase/ledger-engine/components/dashboard/invoice-summary';
+export { default } from '@fleetbase/ledger-engine/components/widget/invoice-status';
diff --git a/app/components/ledger/dashboard/kpi-metric.js b/app/components/ledger/dashboard/kpi-metric.js
index 205cf87..93cc533 100644
--- a/app/components/ledger/dashboard/kpi-metric.js
+++ b/app/components/ledger/dashboard/kpi-metric.js
@@ -1 +1 @@
-export { default } from '@fleetbase/ledger-engine/components/dashboard/kpi-metric';
+export { default } from '@fleetbase/ledger-engine/components/widget/ledger-kpi-tile';
diff --git a/app/components/ledger/dashboard/revenue-chart.js b/app/components/ledger/dashboard/revenue-chart.js
index c293e99..e4c95f4 100644
--- a/app/components/ledger/dashboard/revenue-chart.js
+++ b/app/components/ledger/dashboard/revenue-chart.js
@@ -1 +1 @@
-export { default } from '@fleetbase/ledger-engine/components/dashboard/revenue-chart';
+export { default } from '@fleetbase/ledger-engine/components/widget/revenue-trend';
diff --git a/app/components/ledger/dashboard/wallet-balances.js b/app/components/ledger/dashboard/wallet-balances.js
index 9bba3e9..627ebc3 100644
--- a/app/components/ledger/dashboard/wallet-balances.js
+++ b/app/components/ledger/dashboard/wallet-balances.js
@@ -1 +1 @@
-export { default } from '@fleetbase/ledger-engine/components/dashboard/wallet-balances';
+export { default } from '@fleetbase/ledger-engine/components/widget/wallet-balances';
diff --git a/app/components/widget/ar-aging-summary.js b/app/components/widget/ar-aging-summary.js
new file mode 100644
index 0000000..0ab26a5
--- /dev/null
+++ b/app/components/widget/ar-aging-summary.js
@@ -0,0 +1 @@
+export { default } from '@fleetbase/ledger-engine/components/widget/ar-aging-summary';
diff --git a/app/components/widget/cash-flow-summary.js b/app/components/widget/cash-flow-summary.js
new file mode 100644
index 0000000..ff4d347
--- /dev/null
+++ b/app/components/widget/cash-flow-summary.js
@@ -0,0 +1 @@
+export { default } from '@fleetbase/ledger-engine/components/widget/cash-flow-summary';
diff --git a/app/components/widget/invoice-status.js b/app/components/widget/invoice-status.js
new file mode 100644
index 0000000..2e61b2a
--- /dev/null
+++ b/app/components/widget/invoice-status.js
@@ -0,0 +1 @@
+export { default } from '@fleetbase/ledger-engine/components/widget/invoice-status';
diff --git a/app/components/widget/kpi-active-wallets.js b/app/components/widget/kpi-active-wallets.js
new file mode 100644
index 0000000..182cfa5
--- /dev/null
+++ b/app/components/widget/kpi-active-wallets.js
@@ -0,0 +1 @@
+export { default } from '@fleetbase/ledger-engine/components/widget/kpi-active-wallets';
diff --git a/app/components/widget/kpi-expenses.js b/app/components/widget/kpi-expenses.js
new file mode 100644
index 0000000..0f99a83
--- /dev/null
+++ b/app/components/widget/kpi-expenses.js
@@ -0,0 +1 @@
+export { default } from '@fleetbase/ledger-engine/components/widget/kpi-expenses';
diff --git a/app/components/widget/kpi-net-income.js b/app/components/widget/kpi-net-income.js
new file mode 100644
index 0000000..13a070c
--- /dev/null
+++ b/app/components/widget/kpi-net-income.js
@@ -0,0 +1 @@
+export { default } from '@fleetbase/ledger-engine/components/widget/kpi-net-income';
diff --git a/app/components/widget/kpi-open-invoices.js b/app/components/widget/kpi-open-invoices.js
new file mode 100644
index 0000000..91a9d83
--- /dev/null
+++ b/app/components/widget/kpi-open-invoices.js
@@ -0,0 +1 @@
+export { default } from '@fleetbase/ledger-engine/components/widget/kpi-open-invoices';
diff --git a/app/components/widget/kpi-outstanding-ar.js b/app/components/widget/kpi-outstanding-ar.js
new file mode 100644
index 0000000..63857a7
--- /dev/null
+++ b/app/components/widget/kpi-outstanding-ar.js
@@ -0,0 +1 @@
+export { default } from '@fleetbase/ledger-engine/components/widget/kpi-outstanding-ar';
diff --git a/app/components/widget/kpi-overdue-ar.js b/app/components/widget/kpi-overdue-ar.js
new file mode 100644
index 0000000..6f9e992
--- /dev/null
+++ b/app/components/widget/kpi-overdue-ar.js
@@ -0,0 +1 @@
+export { default } from '@fleetbase/ledger-engine/components/widget/kpi-overdue-ar';
diff --git a/app/components/widget/kpi-revenue.js b/app/components/widget/kpi-revenue.js
new file mode 100644
index 0000000..a14f08d
--- /dev/null
+++ b/app/components/widget/kpi-revenue.js
@@ -0,0 +1 @@
+export { default } from '@fleetbase/ledger-engine/components/widget/kpi-revenue';
diff --git a/app/components/widget/kpi-wallet-balance.js b/app/components/widget/kpi-wallet-balance.js
new file mode 100644
index 0000000..edc2eb9
--- /dev/null
+++ b/app/components/widget/kpi-wallet-balance.js
@@ -0,0 +1 @@
+export { default } from '@fleetbase/ledger-engine/components/widget/kpi-wallet-balance';
diff --git a/app/components/widget/ledger-kpi-tile.js b/app/components/widget/ledger-kpi-tile.js
new file mode 100644
index 0000000..93cc533
--- /dev/null
+++ b/app/components/widget/ledger-kpi-tile.js
@@ -0,0 +1 @@
+export { default } from '@fleetbase/ledger-engine/components/widget/ledger-kpi-tile';
diff --git a/app/components/widget/report-shortcuts.js b/app/components/widget/report-shortcuts.js
new file mode 100644
index 0000000..04c8987
--- /dev/null
+++ b/app/components/widget/report-shortcuts.js
@@ -0,0 +1 @@
+export { default } from '@fleetbase/ledger-engine/components/widget/report-shortcuts';
diff --git a/app/components/widget/revenue-trend.js b/app/components/widget/revenue-trend.js
new file mode 100644
index 0000000..e4c95f4
--- /dev/null
+++ b/app/components/widget/revenue-trend.js
@@ -0,0 +1 @@
+export { default } from '@fleetbase/ledger-engine/components/widget/revenue-trend';
diff --git a/app/services/ledger-dashboard.js b/app/services/ledger-dashboard.js
new file mode 100644
index 0000000..164025c
--- /dev/null
+++ b/app/services/ledger-dashboard.js
@@ -0,0 +1 @@
+export { default } from '@fleetbase/ledger-engine/services/ledger-dashboard';
diff --git a/composer.json b/composer.json
index e2d8bb2..e6e2bb4 100644
--- a/composer.json
+++ b/composer.json
@@ -1,6 +1,6 @@
{
"name": "fleetbase/ledger-api",
- "version": "0.0.3",
+ "version": "0.0.4",
"description": "Accounting & Invoicing Extension for Fleetbase",
"keywords": [
"fleetbase",
diff --git a/extension.json b/extension.json
index a1b8743..2b4a680 100644
--- a/extension.json
+++ b/extension.json
@@ -1,6 +1,6 @@
{
"name": "Ledger",
- "version": "0.0.3",
+ "version": "0.0.4",
"description": "Accounting & Invoicing Extension for Fleetbase",
"repository": "https://github.com/fleetbase/ledger",
"license": "AGPL-3.0-or-later",
diff --git a/package.json b/package.json
index 9431c60..65c3ef4 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@fleetbase/ledger-engine",
- "version": "0.0.3",
+ "version": "0.0.4",
"description": "Accounting & Invoicing Extension for Fleetbase",
"keywords": [
"fleetbase-extension",
@@ -44,9 +44,9 @@
},
"dependencies": {
"@babel/core": "^7.23.2",
- "@fleetbase/ember-core": "^0.3.17",
- "@fleetbase/ember-ui": "^0.3.25",
- "@fleetbase/fleetops-data": "^0.1.30",
+ "@fleetbase/ember-core": "^0.3.21",
+ "@fleetbase/ember-ui": "^0.3.33",
+ "@fleetbase/fleetops-data": "^0.1.36",
"@fortawesome/ember-fontawesome": "^2.0.0",
"@fortawesome/fontawesome-svg-core": "6.4.0",
"@fortawesome/free-brands-svg-icons": "6.4.0",
@@ -78,8 +78,7 @@
"ember-cli-sri": "^2.1.1",
"ember-cli-terser": "^4.0.2",
"ember-composable-helpers": "^5.0.0",
- "ember-concurrency": "^3.1.1",
- "ember-concurrency-decorators": "^2.0.3",
+ "ember-concurrency": "^4.0.6",
"ember-data": "^4.12.5",
"ember-engines": "^0.9.0",
"ember-load-initializers": "^2.1.2",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 67b73c2..07e4e1e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -10,16 +10,16 @@ importers:
dependencies:
'@babel/core':
specifier: ^7.23.2
- version: 7.23.2
+ version: 7.29.0
'@fleetbase/ember-core':
- specifier: ^0.3.17
- version: 0.3.17(@ember/string@3.1.1)(@ember/test-helpers@3.2.0(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(webpack@5.89.0))(ember-resolver@11.0.1(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0)))(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(eslint@8.52.0)(webpack@5.89.0)
+ specifier: ^0.3.21
+ version: 0.3.21(@ember/string@3.1.1)(ember-resolver@11.0.1(ember-source@5.4.0(@babel/core@7.29.0)(@glimmer/component@1.1.2(@babel/core@7.29.0))(rsvp@4.8.5)(webpack@5.89.0)))(ember-source@5.4.0(@babel/core@7.29.0)(@glimmer/component@1.1.2(@babel/core@7.29.0))(rsvp@4.8.5)(webpack@5.89.0))(eslint@8.52.0)(webpack@5.89.0)
'@fleetbase/ember-ui':
- specifier: ^0.3.25
- version: 0.3.25(@ember/test-helpers@3.2.0(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(webpack@5.89.0))(@glimmer/component@1.1.2(@babel/core@7.23.2))(@glimmer/tracking@1.1.2)(ember-resolver@11.0.1(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0)))(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(postcss@8.4.35)(rollup@2.79.1)(tracked-built-ins@3.4.0(@babel/core@7.23.2))(webpack@5.89.0)
+ specifier: ^0.3.33
+ version: 0.3.33(@ember/test-helpers@3.2.0(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(webpack@5.89.0))(@glimmer/component@1.1.2(@babel/core@7.23.2))(@glimmer/tracking@1.1.2)(ember-resolver@11.0.1(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0)))(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(postcss@8.5.8)(rollup@2.79.1)(tracked-built-ins@3.4.0(@babel/core@7.23.2))(webpack@5.89.0)
'@fleetbase/fleetops-data':
- specifier: ^0.1.30
- version: 0.1.30(@ember/string@3.1.1)(@ember/test-helpers@3.2.0(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(webpack@5.89.0))(ember-resolver@11.0.1(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0)))(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(eslint@8.52.0)(webpack@5.89.0)
+ specifier: ^0.1.36
+ version: 0.1.36(@ember/string@3.1.1)(ember-resolver@11.0.1(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0)))(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(eslint@8.52.0)(webpack@5.89.0)
'@fortawesome/ember-fontawesome':
specifier: ^2.0.0
version: 2.0.0(@babel/core@7.23.2)(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(rollup@2.79.1)(webpack@5.89.0)
@@ -77,7 +77,7 @@ importers:
version: 3.0.2
'@glimmer/component':
specifier: ^1.1.2
- version: 1.1.2(@babel/core@7.23.2)
+ version: 1.1.2(@babel/core@7.29.0)
'@glimmer/tracking':
specifier: ^1.1.2
version: 1.1.2
@@ -109,11 +109,8 @@ importers:
specifier: ^5.0.0
version: 5.0.0
ember-concurrency:
- specifier: ^3.1.1
- version: 3.1.1(@babel/core@7.23.2)(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))
- ember-concurrency-decorators:
- specifier: ^2.0.3
- version: 2.0.3(@babel/core@7.23.2)
+ specifier: ^4.0.6
+ version: 4.0.6(@babel/core@7.29.0)
ember-data:
specifier: ^4.12.5
version: 4.12.5(@babel/core@7.23.2)(@ember/string@3.1.1)(@glimmer/tracking@1.1.2)(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(webpack@5.89.0)
@@ -134,10 +131,10 @@ importers:
version: 8.0.1(@ember/test-helpers@3.2.0(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(webpack@5.89.0))(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(qunit@2.20.0)
ember-resolver:
specifier: ^11.0.1
- version: 11.0.1(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))
+ version: 11.0.1(ember-source@5.4.0(@babel/core@7.29.0)(@glimmer/component@1.1.2(@babel/core@7.29.0))(rsvp@4.8.5)(webpack@5.89.0))
ember-source:
specifier: ~5.4.0
- version: 5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0)
+ version: 5.4.0(@babel/core@7.29.0)(@glimmer/component@1.1.2(@babel/core@7.29.0))(rsvp@4.8.5)(webpack@5.89.0)
ember-source-channel-url:
specifier: ^3.0.0
version: 3.0.0
@@ -212,6 +209,10 @@ packages:
resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==}
engines: {node: '>=6.9.0'}
+ '@babel/code-frame@7.29.7':
+ resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==}
+ engines: {node: '>=6.9.0'}
+
'@babel/compat-data@7.23.5':
resolution: {integrity: sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==}
engines: {node: '>=6.9.0'}
@@ -220,6 +221,10 @@ packages:
resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==}
engines: {node: '>=6.9.0'}
+ '@babel/compat-data@7.29.7':
+ resolution: {integrity: sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==}
+ engines: {node: '>=6.9.0'}
+
'@babel/core@7.23.2':
resolution: {integrity: sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==}
engines: {node: '>=6.9.0'}
@@ -250,6 +255,10 @@ packages:
resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==}
engines: {node: '>=6.9.0'}
+ '@babel/generator@7.29.7':
+ resolution: {integrity: sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-annotate-as-pure@7.22.5':
resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==}
engines: {node: '>=6.9.0'}
@@ -270,6 +279,10 @@ packages:
resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==}
engines: {node: '>=6.9.0'}
+ '@babel/helper-compilation-targets@7.29.7':
+ resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-create-class-features-plugin@7.23.10':
resolution: {integrity: sha512-2XpP2XhkXzgxecPNEEK8Vz8Asj9aRxt08oKOqtiZoqV2UGZ5T+EkyP9sXQ9nwMxBIG34a7jmasVqoMop7VdPUw==}
engines: {node: '>=6.9.0'}
@@ -316,6 +329,10 @@ packages:
resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==}
engines: {node: '>=6.9.0'}
+ '@babel/helper-globals@7.29.7':
+ resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-hoist-variables@7.22.5':
resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==}
engines: {node: '>=6.9.0'}
@@ -336,6 +353,10 @@ packages:
resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==}
engines: {node: '>=6.9.0'}
+ '@babel/helper-module-imports@7.29.7':
+ resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-module-transforms@7.23.3':
resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==}
engines: {node: '>=6.9.0'}
@@ -348,6 +369,12 @@ packages:
peerDependencies:
'@babel/core': ^7.0.0
+ '@babel/helper-module-transforms@7.29.7':
+ resolution: {integrity: sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
'@babel/helper-optimise-call-expression@7.22.5':
resolution: {integrity: sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==}
engines: {node: '>=6.9.0'}
@@ -364,6 +391,10 @@ packages:
resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==}
engines: {node: '>=6.9.0'}
+ '@babel/helper-plugin-utils@7.29.7':
+ resolution: {integrity: sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-remap-async-to-generator@7.22.20':
resolution: {integrity: sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==}
engines: {node: '>=6.9.0'}
@@ -412,6 +443,10 @@ packages:
resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==}
engines: {node: '>=6.9.0'}
+ '@babel/helper-string-parser@7.29.7':
+ resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-validator-identifier@7.22.20':
resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==}
engines: {node: '>=6.9.0'}
@@ -420,6 +455,10 @@ packages:
resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==}
engines: {node: '>=6.9.0'}
+ '@babel/helper-validator-identifier@7.29.7':
+ resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-validator-option@7.23.5':
resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==}
engines: {node: '>=6.9.0'}
@@ -428,6 +467,10 @@ packages:
resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==}
engines: {node: '>=6.9.0'}
+ '@babel/helper-validator-option@7.29.7':
+ resolution: {integrity: sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-wrap-function@7.22.20':
resolution: {integrity: sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==}
engines: {node: '>=6.9.0'}
@@ -440,8 +483,8 @@ packages:
resolution: {integrity: sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ==}
engines: {node: '>=6.9.0'}
- '@babel/helpers@7.28.6':
- resolution: {integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==}
+ '@babel/helpers@7.29.7':
+ resolution: {integrity: sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==}
engines: {node: '>=6.9.0'}
'@babel/highlight@7.23.4':
@@ -458,6 +501,11 @@ packages:
engines: {node: '>=6.0.0'}
hasBin: true
+ '@babel/parser@7.29.7':
+ resolution: {integrity: sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+
'@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5':
resolution: {integrity: sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==}
engines: {node: '>=6.9.0'}
@@ -519,20 +567,6 @@ packages:
peerDependencies:
'@babel/core': ^7.0.0-0
- '@babel/plugin-proposal-nullish-coalescing-operator@7.18.6':
- resolution: {integrity: sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==}
- engines: {node: '>=6.9.0'}
- deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.
- peerDependencies:
- '@babel/core': ^7.0.0-0
-
- '@babel/plugin-proposal-optional-chaining@7.21.0':
- resolution: {integrity: sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==}
- engines: {node: '>=6.9.0'}
- deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.
- peerDependencies:
- '@babel/core': ^7.0.0-0
-
'@babel/plugin-proposal-private-methods@7.18.6':
resolution: {integrity: sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==}
engines: {node: '>=6.9.0'}
@@ -581,6 +615,12 @@ packages:
peerDependencies:
'@babel/core': ^7.0.0-0
+ '@babel/plugin-syntax-decorators@7.29.7':
+ resolution: {integrity: sha512-9MTTLbF39X6sqM92JPEsoI7++26hjZvzkxKZy64aMhWLH2mPkJ/Q3AV4QLmls3R14FpSpkOwQQfUh962JGQxxg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/plugin-syntax-dynamic-import@7.8.3':
resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==}
peerDependencies:
@@ -1265,11 +1305,6 @@ packages:
peerDependencies:
'@babel/core': ^7.0.0-0
- '@babel/plugin-transform-typescript@7.8.7':
- resolution: {integrity: sha512-7O0UsPQVNKqpHeHLpfvOG4uXmlw+MOxYvUv6Otc9uH5SYMIxvF6eBdjkWvC3f9G+VXe0RsNExyAQBeTRug/wqQ==}
- peerDependencies:
- '@babel/core': ^7.0.0-0
-
'@babel/plugin-transform-unicode-escapes@7.23.3':
resolution: {integrity: sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==}
engines: {node: '>=6.9.0'}
@@ -1361,6 +1396,10 @@ packages:
resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==}
engines: {node: '>=6.9.0'}
+ '@babel/template@7.29.7':
+ resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==}
+ engines: {node: '>=6.9.0'}
+
'@babel/traverse@7.23.9':
resolution: {integrity: sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==}
engines: {node: '>=6.9.0'}
@@ -1369,6 +1408,10 @@ packages:
resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==}
engines: {node: '>=6.9.0'}
+ '@babel/traverse@7.29.7':
+ resolution: {integrity: sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==}
+ engines: {node: '>=6.9.0'}
+
'@babel/types@7.23.9':
resolution: {integrity: sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==}
engines: {node: '>=6.9.0'}
@@ -1377,6 +1420,10 @@ packages:
resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==}
engines: {node: '>=6.9.0'}
+ '@babel/types@7.29.7':
+ resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==}
+ engines: {node: '>=6.9.0'}
+
'@cnakazawa/watch@1.0.4':
resolution: {integrity: sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ==}
engines: {node: '>=0.1.95'}
@@ -1905,26 +1952,29 @@ packages:
resolution: {integrity: sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ '@event-calendar/core@5.7.1':
+ resolution: {integrity: sha512-ms9MQagthrmRO+ytZD5dDQHjBb+r/6mwld4/psZRaBI6bciIEsmphCrxFaF9HnGvLW0htSa973TVbYMbDsDtVA==}
+
'@fleetbase/ember-accounting@0.0.1':
resolution: {integrity: sha512-61WGQ/VtmkEloBfdNEd83C9E57axiBXbBPdXAbaS3dsCBpKmqwPo1CkrYUN7vVa3oUP9ZRouVVVffbE0YDnAng==}
engines: {node: '>= 18'}
peerDependencies:
ember-source: '>= 4.0.0'
- '@fleetbase/ember-core@0.3.17':
- resolution: {integrity: sha512-fFyorS6Ir/lW2u1y/d46U/0PoIhz4JKSVJZJddveIPK3v/0shpHRRsI4gnW+EtIzE3Dgq6Z7p6pQvrPBpPw/YQ==}
+ '@fleetbase/ember-core@0.3.20':
+ resolution: {integrity: sha512-eqY15urfqFkC26TJO/irdCxke9VE7ywcLodM3K6iDEXR+FFk50YIWnXzvU8PvEQ1EZCRJdyEERvCc9FnypXFQA==}
engines: {node: '>= 18'}
- '@fleetbase/ember-core@0.3.18':
- resolution: {integrity: sha512-XA/Ysn3NlM37qK/xJCY+Uo2sZ8JTwcDaGruPi8dSVyGfYHO55m96TepCChEU18GdwosbsBBfL8C2R+fUvPsqIg==}
+ '@fleetbase/ember-core@0.3.21':
+ resolution: {integrity: sha512-hBIisQfGuuWolyzUnIx+l6M7JtiLMXxhOM1UlAITJ3kIXK0gLclHX3JxF9zoonSnkzNtOe9/TbzIFuKlJVbG9w==}
engines: {node: '>= 18'}
- '@fleetbase/ember-ui@0.3.25':
- resolution: {integrity: sha512-CM0dXMlFe3VyIGFgmbRDEK+e/Y79Ezu4T57geJF2cHr+/1f3oLvhLqPaZIs1J1TTSgcvCl3E+owcYWw2mWxLlg==}
+ '@fleetbase/ember-ui@0.3.33':
+ resolution: {integrity: sha512-XUkRFR/hPfXq1pGadPvEZVTGU7f1D4IHzXcyKVmppY5AxPjgk8PeteoFnNdwZmbGdkTFzifydeG313DltBWlUg==}
engines: {node: '>= 18'}
- '@fleetbase/fleetops-data@0.1.30':
- resolution: {integrity: sha512-n+jCGT2tFnhduHDEkBPENNn9UTaWNSygW9ZmNYiRs6fnGFaRsrMfvBrW+N9galB2dpvA7M8bJO+bl/exkb4dnA==}
+ '@fleetbase/fleetops-data@0.1.36':
+ resolution: {integrity: sha512-w8FmeoCYcWHIoaN5Oxk8XDkxI+va1dwUZCeFDJ2/6oaJ/n6sCFknki67AmYJ0cFJEqHPskUgA8uaQlqw9ZGJXA==}
engines: {node: '>= 18'}
'@floating-ui/core@1.7.5':
@@ -2222,6 +2272,11 @@ packages:
'@socket.io/component-emitter@3.1.0':
resolution: {integrity: sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==}
+ '@sveltejs/acorn-typescript@1.0.10':
+ resolution: {integrity: sha512-4WfKk68eTih+MiJD4fSbxN7E8kVBmTMPWHUPYjvl2N0rMs53YLTT8/YjKU5Dtnz5LqDjl7LEw4U7lXR2W3J5WA==}
+ peerDependencies:
+ acorn: ^8.9.0
+
'@szmarczak/http-timer@1.1.2':
resolution: {integrity: sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==}
engines: {node: '>=6'}
@@ -2447,6 +2502,9 @@ packages:
'@types/estree@1.0.5':
resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
+ '@types/estree@1.0.9':
+ resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==}
+
'@types/express-serve-static-core@4.17.43':
resolution: {integrity: sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==}
@@ -2528,6 +2586,9 @@ packages:
'@types/symlink-or-copy@1.2.2':
resolution: {integrity: sha512-MQ1AnmTLOncwEf9IVU+B2e4Hchrku5N67NkgcAHW0p3sdzPe0FNMANxEm6OJUzPniEQGkeT3OROLlCwZJLWFZA==}
+ '@types/trusted-types@2.0.7':
+ resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
+
'@ungap/structured-clone@1.2.0':
resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
@@ -2672,6 +2733,11 @@ packages:
engines: {node: '>=0.4.0'}
hasBin: true
+ acorn@8.16.0:
+ resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==}
+ engines: {node: '>=0.4.0'}
+ hasBin: true
+
ag-channel@5.0.0:
resolution: {integrity: sha512-bArHkdqQxynim981t8FLZM5TfA0v7p081OlFdOxs6clB79GSGcGlOQMDa31DT9F5VMjzqNiJmhfGwinvfU/3Zg==}
@@ -2810,6 +2876,10 @@ packages:
aria-query@5.3.0:
resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==}
+ aria-query@5.3.1:
+ resolution: {integrity: sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==}
+ engines: {node: '>= 0.4'}
+
arr-diff@4.0.0:
resolution: {integrity: sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==}
engines: {node: '>=0.10.0'}
@@ -2927,6 +2997,10 @@ packages:
resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
engines: {node: '>= 0.4'}
+ axobject-query@4.1.0:
+ resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==}
+ engines: {node: '>= 0.4'}
+
babel-code-frame@6.26.0:
resolution: {integrity: sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g==}
@@ -3107,6 +3181,11 @@ packages:
engines: {node: '>=6.0.0'}
hasBin: true
+ baseline-browser-mapping@2.10.33:
+ resolution: {integrity: sha512-bA6+tcSLpz2tIEdDXZPpPTIuxBcC4+w6SieaYyfigIa4h8GlFxbA17v22Vx3JUtuZQj9SgOsnbK+aTBzyDyEuw==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+
basic-auth@2.0.1:
resolution: {integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==}
engines: {node: '>= 0.8'}
@@ -3406,6 +3485,11 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
+ browserslist@4.28.2:
+ resolution: {integrity: sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==}
+ engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
+ hasBin: true
+
bser@2.1.1:
resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==}
@@ -3508,6 +3592,9 @@ packages:
caniuse-lite@1.0.30001774:
resolution: {integrity: sha512-DDdwPGz99nmIEv216hKSgLD+D4ikHQHjBC/seF98N9CPqRX4M5mSxT9eTV6oyisnJcuzxtZy4n17yKKQYmYQOA==}
+ caniuse-lite@1.0.30001793:
+ resolution: {integrity: sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==}
+
capture-exit@2.0.0:
resolution: {integrity: sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==}
engines: {node: 6.* || 8.* || >= 10.*}
@@ -3649,6 +3736,10 @@ packages:
resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==}
engines: {node: '>=0.8'}
+ clsx@2.1.1:
+ resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
+ engines: {node: '>=6'}
+
collection-visit@1.0.0:
resolution: {integrity: sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==}
engines: {node: '>=0.10.0'}
@@ -4148,6 +4239,9 @@ packages:
decorator-transforms@2.3.1:
resolution: {integrity: sha512-PDOk74Zqqy0946Lx4ckXxbgG6uhPScOICtrxL/pXmfznxchqNee0TaJISClGJQe6FeT8ohGqsOgdjfahm4FwEw==}
+ decorator-transforms@2.3.2:
+ resolution: {integrity: sha512-XcErcjlmCzG5ODgYjt6ZTXwd6S8fPKln/sJmw15ZXkWG2JpoQNwszis+AwF6XSGlOoG7g8MCEO97g+Yw3fk5OQ==}
+
deep-extend@0.6.0:
resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==}
engines: {node: '>=4.0.0'}
@@ -4223,6 +4317,9 @@ packages:
resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==}
engines: {node: '>=8'}
+ devalue@5.8.1:
+ resolution: {integrity: sha512-4CXDYRBGqN+57wVJkuXBYmpAVUSg3L6JAQa/DFqm238G73E1wuyc/JhGQJzN7vUf/CMphYau2zXbfWzDR5aTEw==}
+
didyoumean@1.2.2:
resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==}
@@ -4285,6 +4382,9 @@ packages:
electron-to-chromium@1.5.302:
resolution: {integrity: sha512-sM6HAN2LyK82IyPBpznDRqlTQAtuSaO+ShzFiWTvoMJLHyZ+Y39r8VMfHzwbU8MVBzQ4Wdn85+wlZl2TLGIlwg==}
+ electron-to-chromium@1.5.368:
+ resolution: {integrity: sha512-7RckJJK4uESJF9PxvfMWd3TGqIiieUTG4HxnKaKuIpGbcr+r2ZEB3g2gAhCP3Fqm42vJSzLfgab9eva/C4/XVw==}
+
element-closest@3.0.2:
resolution: {integrity: sha512-JxKQiJKX0Zr5Q2/bCaTx8P+UbfyMET1OQd61qu5xQFeWr1km3fGaxelSJtnfT27XQ5Uoztn2yIyeamAc/VX13g==}
engines: {node: '>=0.12.0'}
@@ -4468,10 +4568,6 @@ packages:
resolution: {integrity: sha512-lo5YArbJzJi5ssvaGqTt6+FnhTALnSvYVuxM7lfyL1UCMudyNJ94ovH5C7n5il7ATd6WsNiAPRUO/v+s5Jq/aA==}
engines: {node: 8.* || >= 10.*}
- ember-cli-typescript@3.1.4:
- resolution: {integrity: sha512-HJ73kL45OGRmIkPhBNFt31I1SGUvdZND+LCH21+qpq3pPlFpJG8GORyXpP+2ze8PbnITNLzwe5AwUrpyuRswdQ==}
- engines: {node: 8.* || >= 10.*}
-
ember-cli-typescript@4.2.1:
resolution: {integrity: sha512-0iKTZ+/wH6UB/VTWKvGuXlmwiE8HSIGcxHamwNhEC5x1mN3z8RfvsFZdQWYUzIWFN2Tek0gmepGRPTwWdBYl/A==}
engines: {node: 10.* || >= 12.*}
@@ -4521,10 +4617,6 @@ packages:
peerDependencies:
ember-concurrency: ^2.0.0-rc.1
- ember-concurrency-decorators@2.0.3:
- resolution: {integrity: sha512-r6O34YKI/slyYapVsuOPnmaKC4AsmBSwvgcadbdy+jHNj+mnryXPkm+3hhhRnFdlsKUKdEuXvl43lhjhYRLhhA==}
- engines: {node: 10.* || >= 12}
-
ember-concurrency-ts@0.3.1:
resolution: {integrity: sha512-lE9uqPgK1Y9PN/0BJ5zE2a+h95izRCn6FCyt7qVV3012TlblTynsBaoUuAbN1T3KfzFsrJaXwsxzRbDjEde2Sw==}
engines: {node: 10.* || >= 12}
@@ -4535,12 +4627,6 @@ packages:
resolution: {integrity: sha512-sz6sTIXN/CuLb5wdpauFa+rWXuvXXSnSHS4kuNzU5GSMDX1pLBWSuovoUk61FUe6CYRqBmT1/UushObwBGickQ==}
engines: {node: 10.* || 12.* || 14.* || >= 16}
- ember-concurrency@3.1.1:
- resolution: {integrity: sha512-doXFYYfy1C7jez+jDDlfahTp03QdjXeSY/W3Zbnx/q3UNJ9g10Shf2d7M/HvWo/TC22eU+6dPLIpqd/6q4pR+Q==}
- engines: {node: 16.* || >= 18}
- peerDependencies:
- ember-source: ^3.28.0 || ^4.0.0 || >=5.0.0
-
ember-concurrency@4.0.6:
resolution: {integrity: sha512-Ikwl2YwXVe8aBwrT1deWTcUVxVu6KxS1qeU1ks3EML1Q/nxwKgxCkGqTJavxczawO8H/SIW45dV4r7z5Yqd2Xg==}
engines: {node: 16.* || >= 18}
@@ -4831,8 +4917,8 @@ packages:
engines: {node: 12.* || 14.* || >= 16.*}
hasBin: true
- ember-tracked-storage-polyfill@1.0.0:
- resolution: {integrity: sha512-eL7lZat68E6P/D7b9UoTB5bB5Oh/0aju0Z7PCMi3aTwhaydRaxloE7TGrTRYU+NdJuyNVZXeGyxFxn2frvd3TA==}
+ ember-tracked-storage-polyfill@1.0.1:
+ resolution: {integrity: sha512-lr66R+1H9qMXIUXxwzpixS/qTwsMEpJXS5s2nOdvQP9U/JYuZT9MexpvLktSUQ1uWEhGQA8DDeeVh4R1CvLDFQ==}
engines: {node: 12.* || >= 14}
ember-truth-helpers@3.1.1:
@@ -5055,6 +5141,9 @@ packages:
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
hasBin: true
+ esm-env@1.2.2:
+ resolution: {integrity: sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==}
+
esm@3.2.25:
resolution: {integrity: sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==}
engines: {node: '>=6'}
@@ -5077,6 +5166,14 @@ packages:
resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==}
engines: {node: '>=0.10'}
+ esrap@2.2.11:
+ resolution: {integrity: sha512-gPdx+I+BjYEinNMQaBXFjbaJVyoPMU4ZODg5mE+M4DqVG9VusAVHHjcBX+zqyITlI0DIARwDMMzZwAWj36dRoQ==}
+ peerDependencies:
+ '@typescript-eslint/types': ^8.2.0
+ peerDependenciesMeta:
+ '@typescript-eslint/types':
+ optional: true
+
esrecurse@4.3.0:
resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
engines: {node: '>=4.0'}
@@ -5130,10 +5227,6 @@ packages:
resolution: {integrity: sha512-Y/URAVapfbYy2Xp/gb6A0E7iR8xeqOCXsuuaoMn7A5PzrXUK84E1gyiEfq0wQd/GHA6GsoHWwhNq8anb0mleIw==}
engines: {node: ^8.12.0 || >=9.7.0}
- execa@3.4.0:
- resolution: {integrity: sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g==}
- engines: {node: ^8.12.0 || >=9.7.0}
-
execa@4.1.0:
resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==}
engines: {node: '>=10'}
@@ -6080,6 +6173,9 @@ packages:
resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==}
engines: {node: '>=0.10.0'}
+ is-reference@3.0.3:
+ resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==}
+
is-regex@1.1.4:
resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==}
engines: {node: '>= 0.4'}
@@ -6357,6 +6453,9 @@ packages:
loader.js@4.7.0:
resolution: {integrity: sha512-9M2KvGT6duzGMgkOcTkWb+PR/Q2Oe54df/tLgHGVmFpAmtqJ553xJh6N63iFYI2yjo2PeJXbS5skHi/QpJq4vA==}
+ locate-character@3.0.0:
+ resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==}
+
locate-path@2.0.0:
resolution: {integrity: sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==}
engines: {node: '>=4'}
@@ -6499,6 +6598,9 @@ packages:
magic-string@0.25.9:
resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==}
+ magic-string@0.30.21:
+ resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
+
magic-string@0.30.7:
resolution: {integrity: sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA==}
engines: {node: '>=12'}
@@ -6850,6 +6952,10 @@ packages:
node-releases@2.0.27:
resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==}
+ node-releases@2.0.47:
+ resolution: {integrity: sha512-Uzmd6LXpouKo8EUK68IjH4+E01w/hXyV3R3g/geCJo+rXLNfh1xucB+LOzYEOQPSiUK3h/xZf0cQGcSsmyL2Og==}
+ engines: {node: '>=18'}
+
node-watch@0.7.3:
resolution: {integrity: sha512-3l4E8uMPY1HdMMryPRUAl+oIHtXtyiTlIiESNSVSNxcPfzAFzeTbXFQkZfAwBbo0B1qMSG8nUABx+Gd+YrbKrQ==}
engines: {node: '>=6'}
@@ -8513,6 +8619,10 @@ packages:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
+ svelte@5.56.1:
+ resolution: {integrity: sha512-eArsJmvl3xZVuTYD852PzIEdg2wgDdIZ1NEsIPbzAukHwi284B18No4nK2rCO9AwsWUDza4Cjvmoa4HaojTl5g==}
+ engines: {node: '>=18'}
+
svg-tags@1.0.0:
resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==}
@@ -9147,6 +9257,9 @@ packages:
resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==}
engines: {node: '>=12.20'}
+ zimmerframe@1.1.4:
+ resolution: {integrity: sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==}
+
snapshots:
'@aashutoshrathi/word-wrap@1.2.6': {}
@@ -9169,10 +9282,18 @@ snapshots:
js-tokens: 4.0.0
picocolors: 1.1.1
+ '@babel/code-frame@7.29.7':
+ dependencies:
+ '@babel/helper-validator-identifier': 7.29.7
+ js-tokens: 4.0.0
+ picocolors: 1.1.1
+
'@babel/compat-data@7.23.5': {}
'@babel/compat-data@7.29.0': {}
+ '@babel/compat-data@7.29.7': {}
+
'@babel/core@7.23.2':
dependencies:
'@ampproject/remapping': 2.2.1
@@ -9195,15 +9316,15 @@ snapshots:
'@babel/core@7.29.0':
dependencies:
- '@babel/code-frame': 7.29.0
- '@babel/generator': 7.29.1
- '@babel/helper-compilation-targets': 7.28.6
- '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0)
- '@babel/helpers': 7.28.6
- '@babel/parser': 7.29.0
- '@babel/template': 7.28.6
- '@babel/traverse': 7.29.0
- '@babel/types': 7.29.0
+ '@babel/code-frame': 7.29.7
+ '@babel/generator': 7.29.7
+ '@babel/helper-compilation-targets': 7.29.7
+ '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.0)
+ '@babel/helpers': 7.29.7
+ '@babel/parser': 7.29.7
+ '@babel/template': 7.29.7
+ '@babel/traverse': 7.29.7
+ '@babel/types': 7.29.7
'@jridgewell/remapping': 2.3.5
convert-source-map: 2.0.0
debug: 4.4.3
@@ -9244,6 +9365,14 @@ snapshots:
'@jridgewell/trace-mapping': 0.3.31
jsesc: 3.1.0
+ '@babel/generator@7.29.7':
+ dependencies:
+ '@babel/parser': 7.29.7
+ '@babel/types': 7.29.7
+ '@jridgewell/gen-mapping': 0.3.13
+ '@jridgewell/trace-mapping': 0.3.31
+ jsesc: 3.1.0
+
'@babel/helper-annotate-as-pure@7.22.5':
dependencies:
'@babel/types': 7.23.9
@@ -9272,6 +9401,14 @@ snapshots:
lru-cache: 5.1.1
semver: 6.3.1
+ '@babel/helper-compilation-targets@7.29.7':
+ dependencies:
+ '@babel/compat-data': 7.29.7
+ '@babel/helper-validator-option': 7.29.7
+ browserslist: 4.28.2
+ lru-cache: 5.1.1
+ semver: 6.3.1
+
'@babel/helper-create-class-features-plugin@7.23.10(@babel/core@7.23.2)':
dependencies:
'@babel/core': 7.23.2
@@ -9405,6 +9542,8 @@ snapshots:
'@babel/helper-globals@7.28.0': {}
+ '@babel/helper-globals@7.29.7': {}
+
'@babel/helper-hoist-variables@7.22.5':
dependencies:
'@babel/types': 7.23.9
@@ -9431,6 +9570,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@babel/helper-module-imports@7.29.7':
+ dependencies:
+ '@babel/traverse': 7.29.7
+ '@babel/types': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
+
'@babel/helper-module-transforms@7.23.3(@babel/core@7.23.2)':
dependencies:
'@babel/core': 7.23.2
@@ -9467,6 +9613,15 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.0)':
+ dependencies:
+ '@babel/core': 7.29.0
+ '@babel/helper-module-imports': 7.29.7
+ '@babel/helper-validator-identifier': 7.29.7
+ '@babel/traverse': 7.29.7
+ transitivePeerDependencies:
+ - supports-color
+
'@babel/helper-optimise-call-expression@7.22.5':
dependencies:
'@babel/types': 7.23.9
@@ -9479,6 +9634,8 @@ snapshots:
'@babel/helper-plugin-utils@7.28.6': {}
+ '@babel/helper-plugin-utils@7.29.7': {}
+
'@babel/helper-remap-async-to-generator@7.22.20(@babel/core@7.23.2)':
dependencies:
'@babel/core': 7.23.2
@@ -9566,14 +9723,20 @@ snapshots:
'@babel/helper-string-parser@7.27.1': {}
+ '@babel/helper-string-parser@7.29.7': {}
+
'@babel/helper-validator-identifier@7.22.20': {}
'@babel/helper-validator-identifier@7.28.5': {}
+ '@babel/helper-validator-identifier@7.29.7': {}
+
'@babel/helper-validator-option@7.23.5': {}
'@babel/helper-validator-option@7.27.1': {}
+ '@babel/helper-validator-option@7.29.7': {}
+
'@babel/helper-wrap-function@7.22.20':
dependencies:
'@babel/helper-function-name': 7.23.0
@@ -9596,10 +9759,10 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@babel/helpers@7.28.6':
+ '@babel/helpers@7.29.7':
dependencies:
- '@babel/template': 7.28.6
- '@babel/types': 7.29.0
+ '@babel/template': 7.29.7
+ '@babel/types': 7.29.7
'@babel/highlight@7.23.4':
dependencies:
@@ -9615,6 +9778,10 @@ snapshots:
dependencies:
'@babel/types': 7.29.0
+ '@babel/parser@7.29.7':
+ dependencies:
+ '@babel/types': 7.29.7
+
'@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5(@babel/core@7.23.2)':
dependencies:
'@babel/core': 7.23.2
@@ -9751,19 +9918,6 @@ snapshots:
'@babel/helper-split-export-declaration': 7.22.6
'@babel/plugin-syntax-decorators': 7.23.3(@babel/core@7.29.0)
- '@babel/plugin-proposal-nullish-coalescing-operator@7.18.6(@babel/core@7.23.2)':
- dependencies:
- '@babel/core': 7.23.2
- '@babel/helper-plugin-utils': 7.22.5
- '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.23.2)
-
- '@babel/plugin-proposal-optional-chaining@7.21.0(@babel/core@7.23.2)':
- dependencies:
- '@babel/core': 7.23.2
- '@babel/helper-plugin-utils': 7.22.5
- '@babel/helper-skip-transparent-expression-wrappers': 7.22.5
- '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.23.2)
-
'@babel/plugin-proposal-private-methods@7.18.6(@babel/core@7.23.2)':
dependencies:
'@babel/core': 7.23.2
@@ -9850,6 +10004,16 @@ snapshots:
'@babel/core': 7.29.0
'@babel/helper-plugin-utils': 7.28.6
+ '@babel/plugin-syntax-decorators@7.29.7(@babel/core@7.23.2)':
+ dependencies:
+ '@babel/core': 7.23.2
+ '@babel/helper-plugin-utils': 7.29.7
+
+ '@babel/plugin-syntax-decorators@7.29.7(@babel/core@7.29.0)':
+ dependencies:
+ '@babel/core': 7.29.0
+ '@babel/helper-plugin-utils': 7.29.7
+
'@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.23.2)':
dependencies:
'@babel/core': 7.23.2
@@ -11299,12 +11463,12 @@ snapshots:
'@babel/helper-plugin-utils': 7.22.5
'@babel/plugin-syntax-typescript': 7.23.3(@babel/core@7.23.2)
- '@babel/plugin-transform-typescript@7.8.7(@babel/core@7.23.2)':
+ '@babel/plugin-transform-typescript@7.5.5(@babel/core@7.29.0)':
dependencies:
- '@babel/core': 7.23.2
- '@babel/helper-create-class-features-plugin': 7.23.10(@babel/core@7.23.2)
- '@babel/helper-plugin-utils': 7.22.5
- '@babel/plugin-syntax-typescript': 7.23.3(@babel/core@7.23.2)
+ '@babel/core': 7.29.0
+ '@babel/helper-create-class-features-plugin': 7.23.10(@babel/core@7.29.0)
+ '@babel/helper-plugin-utils': 7.29.7
+ '@babel/plugin-syntax-typescript': 7.23.3(@babel/core@7.29.0)
'@babel/plugin-transform-unicode-escapes@7.23.3(@babel/core@7.23.2)':
dependencies:
@@ -11765,6 +11929,12 @@ snapshots:
'@babel/parser': 7.29.0
'@babel/types': 7.29.0
+ '@babel/template@7.29.7':
+ dependencies:
+ '@babel/code-frame': 7.29.7
+ '@babel/parser': 7.29.7
+ '@babel/types': 7.29.7
+
'@babel/traverse@7.23.9':
dependencies:
'@babel/code-frame': 7.23.5
@@ -11792,6 +11962,18 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@babel/traverse@7.29.7':
+ dependencies:
+ '@babel/code-frame': 7.29.7
+ '@babel/generator': 7.29.7
+ '@babel/helper-globals': 7.29.7
+ '@babel/parser': 7.29.7
+ '@babel/template': 7.29.7
+ '@babel/types': 7.29.7
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+
'@babel/types@7.23.9':
dependencies:
'@babel/helper-string-parser': 7.23.4
@@ -11803,6 +11985,11 @@ snapshots:
'@babel/helper-string-parser': 7.27.1
'@babel/helper-validator-identifier': 7.28.5
+ '@babel/types@7.29.7':
+ dependencies:
+ '@babel/helper-string-parser': 7.29.7
+ '@babel/helper-validator-identifier': 7.29.7
+
'@cnakazawa/watch@1.0.4':
dependencies:
exec-sh: 0.3.6
@@ -11852,201 +12039,201 @@ snapshots:
'@csstools/css-parser-algorithms': 2.5.0(@csstools/css-tokenizer@2.2.3)
'@csstools/css-tokenizer': 2.2.3
- '@csstools/postcss-cascade-layers@4.0.6(postcss@8.4.35)':
+ '@csstools/postcss-cascade-layers@4.0.6(postcss@8.5.8)':
dependencies:
'@csstools/selector-specificity': 3.1.1(postcss-selector-parser@6.0.15)
- postcss: 8.4.35
+ postcss: 8.5.8
postcss-selector-parser: 6.0.15
- '@csstools/postcss-color-function@3.0.19(postcss@8.4.35)':
+ '@csstools/postcss-color-function@3.0.19(postcss@8.5.8)':
dependencies:
'@csstools/css-color-parser': 2.0.5(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1)
'@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1)
'@csstools/css-tokenizer': 2.4.1
- '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.35)
- '@csstools/utilities': 1.0.0(postcss@8.4.35)
- postcss: 8.4.35
+ '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.5.8)
+ '@csstools/utilities': 1.0.0(postcss@8.5.8)
+ postcss: 8.5.8
- '@csstools/postcss-color-mix-function@2.0.19(postcss@8.4.35)':
+ '@csstools/postcss-color-mix-function@2.0.19(postcss@8.5.8)':
dependencies:
'@csstools/css-color-parser': 2.0.5(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1)
'@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1)
'@csstools/css-tokenizer': 2.4.1
- '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.35)
- '@csstools/utilities': 1.0.0(postcss@8.4.35)
- postcss: 8.4.35
+ '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.5.8)
+ '@csstools/utilities': 1.0.0(postcss@8.5.8)
+ postcss: 8.5.8
- '@csstools/postcss-content-alt-text@1.0.0(postcss@8.4.35)':
+ '@csstools/postcss-content-alt-text@1.0.0(postcss@8.5.8)':
dependencies:
'@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1)
'@csstools/css-tokenizer': 2.4.1
- '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.35)
- '@csstools/utilities': 1.0.0(postcss@8.4.35)
- postcss: 8.4.35
+ '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.5.8)
+ '@csstools/utilities': 1.0.0(postcss@8.5.8)
+ postcss: 8.5.8
- '@csstools/postcss-exponential-functions@1.0.9(postcss@8.4.35)':
+ '@csstools/postcss-exponential-functions@1.0.9(postcss@8.5.8)':
dependencies:
'@csstools/css-calc': 1.2.4(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1)
'@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1)
'@csstools/css-tokenizer': 2.4.1
- postcss: 8.4.35
+ postcss: 8.5.8
- '@csstools/postcss-font-format-keywords@3.0.2(postcss@8.4.35)':
+ '@csstools/postcss-font-format-keywords@3.0.2(postcss@8.5.8)':
dependencies:
- '@csstools/utilities': 1.0.0(postcss@8.4.35)
- postcss: 8.4.35
+ '@csstools/utilities': 1.0.0(postcss@8.5.8)
+ postcss: 8.5.8
postcss-value-parser: 4.2.0
- '@csstools/postcss-gamut-mapping@1.0.11(postcss@8.4.35)':
+ '@csstools/postcss-gamut-mapping@1.0.11(postcss@8.5.8)':
dependencies:
'@csstools/css-color-parser': 2.0.5(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1)
'@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1)
'@csstools/css-tokenizer': 2.4.1
- postcss: 8.4.35
+ postcss: 8.5.8
- '@csstools/postcss-gradients-interpolation-method@4.0.20(postcss@8.4.35)':
+ '@csstools/postcss-gradients-interpolation-method@4.0.20(postcss@8.5.8)':
dependencies:
'@csstools/css-color-parser': 2.0.5(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1)
'@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1)
'@csstools/css-tokenizer': 2.4.1
- '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.35)
- '@csstools/utilities': 1.0.0(postcss@8.4.35)
- postcss: 8.4.35
+ '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.5.8)
+ '@csstools/utilities': 1.0.0(postcss@8.5.8)
+ postcss: 8.5.8
- '@csstools/postcss-hwb-function@3.0.18(postcss@8.4.35)':
+ '@csstools/postcss-hwb-function@3.0.18(postcss@8.5.8)':
dependencies:
'@csstools/css-color-parser': 2.0.5(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1)
'@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1)
'@csstools/css-tokenizer': 2.4.1
- '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.35)
- '@csstools/utilities': 1.0.0(postcss@8.4.35)
- postcss: 8.4.35
+ '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.5.8)
+ '@csstools/utilities': 1.0.0(postcss@8.5.8)
+ postcss: 8.5.8
- '@csstools/postcss-ic-unit@3.0.7(postcss@8.4.35)':
+ '@csstools/postcss-ic-unit@3.0.7(postcss@8.5.8)':
dependencies:
- '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.35)
- '@csstools/utilities': 1.0.0(postcss@8.4.35)
- postcss: 8.4.35
+ '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.5.8)
+ '@csstools/utilities': 1.0.0(postcss@8.5.8)
+ postcss: 8.5.8
postcss-value-parser: 4.2.0
- '@csstools/postcss-initial@1.0.1(postcss@8.4.35)':
+ '@csstools/postcss-initial@1.0.1(postcss@8.5.8)':
dependencies:
- postcss: 8.4.35
+ postcss: 8.5.8
- '@csstools/postcss-is-pseudo-class@4.0.8(postcss@8.4.35)':
+ '@csstools/postcss-is-pseudo-class@4.0.8(postcss@8.5.8)':
dependencies:
'@csstools/selector-specificity': 3.1.1(postcss-selector-parser@6.0.15)
- postcss: 8.4.35
+ postcss: 8.5.8
postcss-selector-parser: 6.0.15
- '@csstools/postcss-light-dark-function@1.0.8(postcss@8.4.35)':
+ '@csstools/postcss-light-dark-function@1.0.8(postcss@8.5.8)':
dependencies:
'@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1)
'@csstools/css-tokenizer': 2.4.1
- '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.35)
- '@csstools/utilities': 1.0.0(postcss@8.4.35)
- postcss: 8.4.35
+ '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.5.8)
+ '@csstools/utilities': 1.0.0(postcss@8.5.8)
+ postcss: 8.5.8
- '@csstools/postcss-logical-float-and-clear@2.0.1(postcss@8.4.35)':
+ '@csstools/postcss-logical-float-and-clear@2.0.1(postcss@8.5.8)':
dependencies:
- postcss: 8.4.35
+ postcss: 8.5.8
- '@csstools/postcss-logical-overflow@1.0.1(postcss@8.4.35)':
+ '@csstools/postcss-logical-overflow@1.0.1(postcss@8.5.8)':
dependencies:
- postcss: 8.4.35
+ postcss: 8.5.8
- '@csstools/postcss-logical-overscroll-behavior@1.0.1(postcss@8.4.35)':
+ '@csstools/postcss-logical-overscroll-behavior@1.0.1(postcss@8.5.8)':
dependencies:
- postcss: 8.4.35
+ postcss: 8.5.8
- '@csstools/postcss-logical-resize@2.0.1(postcss@8.4.35)':
+ '@csstools/postcss-logical-resize@2.0.1(postcss@8.5.8)':
dependencies:
- postcss: 8.4.35
+ postcss: 8.5.8
postcss-value-parser: 4.2.0
- '@csstools/postcss-logical-viewport-units@2.0.11(postcss@8.4.35)':
+ '@csstools/postcss-logical-viewport-units@2.0.11(postcss@8.5.8)':
dependencies:
'@csstools/css-tokenizer': 2.4.1
- '@csstools/utilities': 1.0.0(postcss@8.4.35)
- postcss: 8.4.35
+ '@csstools/utilities': 1.0.0(postcss@8.5.8)
+ postcss: 8.5.8
- '@csstools/postcss-media-minmax@1.1.8(postcss@8.4.35)':
+ '@csstools/postcss-media-minmax@1.1.8(postcss@8.5.8)':
dependencies:
'@csstools/css-calc': 1.2.4(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1)
'@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1)
'@csstools/css-tokenizer': 2.4.1
'@csstools/media-query-list-parser': 2.1.13(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1)
- postcss: 8.4.35
+ postcss: 8.5.8
- '@csstools/postcss-media-queries-aspect-ratio-number-values@2.0.11(postcss@8.4.35)':
+ '@csstools/postcss-media-queries-aspect-ratio-number-values@2.0.11(postcss@8.5.8)':
dependencies:
'@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1)
'@csstools/css-tokenizer': 2.4.1
'@csstools/media-query-list-parser': 2.1.13(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1)
- postcss: 8.4.35
+ postcss: 8.5.8
- '@csstools/postcss-nested-calc@3.0.2(postcss@8.4.35)':
+ '@csstools/postcss-nested-calc@3.0.2(postcss@8.5.8)':
dependencies:
- '@csstools/utilities': 1.0.0(postcss@8.4.35)
- postcss: 8.4.35
+ '@csstools/utilities': 1.0.0(postcss@8.5.8)
+ postcss: 8.5.8
postcss-value-parser: 4.2.0
- '@csstools/postcss-normalize-display-values@3.0.2(postcss@8.4.35)':
+ '@csstools/postcss-normalize-display-values@3.0.2(postcss@8.5.8)':
dependencies:
- postcss: 8.4.35
+ postcss: 8.5.8
postcss-value-parser: 4.2.0
- '@csstools/postcss-oklab-function@3.0.19(postcss@8.4.35)':
+ '@csstools/postcss-oklab-function@3.0.19(postcss@8.5.8)':
dependencies:
'@csstools/css-color-parser': 2.0.5(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1)
'@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1)
'@csstools/css-tokenizer': 2.4.1
- '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.35)
- '@csstools/utilities': 1.0.0(postcss@8.4.35)
- postcss: 8.4.35
+ '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.5.8)
+ '@csstools/utilities': 1.0.0(postcss@8.5.8)
+ postcss: 8.5.8
- '@csstools/postcss-progressive-custom-properties@3.3.0(postcss@8.4.35)':
+ '@csstools/postcss-progressive-custom-properties@3.3.0(postcss@8.5.8)':
dependencies:
- postcss: 8.4.35
+ postcss: 8.5.8
postcss-value-parser: 4.2.0
- '@csstools/postcss-relative-color-syntax@2.0.19(postcss@8.4.35)':
+ '@csstools/postcss-relative-color-syntax@2.0.19(postcss@8.5.8)':
dependencies:
'@csstools/css-color-parser': 2.0.5(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1)
'@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1)
'@csstools/css-tokenizer': 2.4.1
- '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.35)
- '@csstools/utilities': 1.0.0(postcss@8.4.35)
- postcss: 8.4.35
+ '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.5.8)
+ '@csstools/utilities': 1.0.0(postcss@8.5.8)
+ postcss: 8.5.8
- '@csstools/postcss-scope-pseudo-class@3.0.1(postcss@8.4.35)':
+ '@csstools/postcss-scope-pseudo-class@3.0.1(postcss@8.5.8)':
dependencies:
- postcss: 8.4.35
+ postcss: 8.5.8
postcss-selector-parser: 6.0.15
- '@csstools/postcss-stepped-value-functions@3.0.10(postcss@8.4.35)':
+ '@csstools/postcss-stepped-value-functions@3.0.10(postcss@8.5.8)':
dependencies:
'@csstools/css-calc': 1.2.4(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1)
'@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1)
'@csstools/css-tokenizer': 2.4.1
- postcss: 8.4.35
+ postcss: 8.5.8
- '@csstools/postcss-text-decoration-shorthand@3.0.7(postcss@8.4.35)':
+ '@csstools/postcss-text-decoration-shorthand@3.0.7(postcss@8.5.8)':
dependencies:
'@csstools/color-helpers': 4.2.1
- postcss: 8.4.35
+ postcss: 8.5.8
postcss-value-parser: 4.2.0
- '@csstools/postcss-trigonometric-functions@3.0.10(postcss@8.4.35)':
+ '@csstools/postcss-trigonometric-functions@3.0.10(postcss@8.5.8)':
dependencies:
'@csstools/css-calc': 1.2.4(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1)
'@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1)
'@csstools/css-tokenizer': 2.4.1
- postcss: 8.4.35
+ postcss: 8.5.8
- '@csstools/postcss-unset-value@3.0.1(postcss@8.4.35)':
+ '@csstools/postcss-unset-value@3.0.1(postcss@8.5.8)':
dependencies:
- postcss: 8.4.35
+ postcss: 8.5.8
'@csstools/selector-resolve-nested@1.1.0(postcss-selector-parser@6.1.2)':
dependencies:
@@ -12064,11 +12251,11 @@ snapshots:
dependencies:
postcss-selector-parser: 6.1.2
- '@csstools/utilities@1.0.0(postcss@8.4.35)':
+ '@csstools/utilities@1.0.0(postcss@8.5.8)':
dependencies:
- postcss: 8.4.35
+ postcss: 8.5.8
- '@ember-data/adapter@4.12.5(@ember-data/store@4.12.5(@babel/core@7.23.2)(@ember-data/graph@4.12.5)(@ember-data/json-api@4.12.5)(@ember-data/legacy-compat@4.12.5)(@ember-data/model@4.12.5)(@ember-data/tracking@4.12.5)(@ember/string@3.1.1)(@glimmer/tracking@1.1.2)(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0)))(@ember/string@3.1.1)(ember-inflector@4.0.2)':
+ '@ember-data/adapter@4.12.5(@ember-data/store@4.12.5)(@ember/string@3.1.1)(ember-inflector@4.0.2)':
dependencies:
'@ember-data/private-build-infra': 4.12.5
'@ember-data/store': 4.12.5(@babel/core@7.23.2)(@ember-data/graph@4.12.5)(@ember-data/json-api@4.12.5)(@ember-data/legacy-compat@4.12.5)(@ember-data/model@4.12.5)(@ember-data/tracking@4.12.5)(@ember/string@3.1.1)(@glimmer/tracking@1.1.2)(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))
@@ -12198,7 +12385,7 @@ snapshots:
'@ember-data/rfc395-data@0.0.4': {}
- '@ember-data/serializer@4.12.5(@ember-data/store@4.12.5(@babel/core@7.23.2)(@ember-data/graph@4.12.5)(@ember-data/json-api@4.12.5)(@ember-data/legacy-compat@4.12.5)(@ember-data/model@4.12.5)(@ember-data/tracking@4.12.5)(@ember/string@3.1.1)(@glimmer/tracking@1.1.2)(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0)))(@ember/string@3.1.1)(ember-inflector@4.0.2)':
+ '@ember-data/serializer@4.12.5(@ember-data/store@4.12.5)(@ember/string@3.1.1)(ember-inflector@4.0.2)':
dependencies:
'@ember-data/private-build-infra': 4.12.5
'@ember-data/store': 4.12.5(@babel/core@7.23.2)(@ember-data/graph@4.12.5)(@ember-data/json-api@4.12.5)(@ember-data/legacy-compat@4.12.5)(@ember-data/model@4.12.5)(@ember-data/tracking@4.12.5)(@ember/string@3.1.1)(@glimmer/tracking@1.1.2)(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))
@@ -12476,7 +12663,7 @@ snapshots:
'@eslint/eslintrc@2.1.4':
dependencies:
ajv: 6.12.6
- debug: 4.3.4
+ debug: 4.4.3
espree: 9.6.1
globals: 13.24.0
ignore: 5.3.1
@@ -12489,6 +12676,12 @@ snapshots:
'@eslint/js@8.52.0': {}
+ '@event-calendar/core@5.7.1':
+ dependencies:
+ svelte: 5.56.1
+ transitivePeerDependencies:
+ - '@typescript-eslint/types'
+
'@fleetbase/ember-accounting@0.0.1(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))':
dependencies:
'@babel/core': 7.23.2
@@ -12498,7 +12691,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@fleetbase/ember-core@0.3.17(@ember/string@3.1.1)(@ember/test-helpers@3.2.0(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(webpack@5.89.0))(ember-resolver@11.0.1(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0)))(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(eslint@8.52.0)(webpack@5.89.0)':
+ '@fleetbase/ember-core@0.3.20(@ember/string@3.1.1)(ember-resolver@11.0.1(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0)))(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(eslint@8.52.0)(webpack@5.89.0)':
dependencies:
'@babel/core': 7.23.2
compress-json: 3.4.0
@@ -12515,12 +12708,11 @@ snapshots:
ember-intl: 6.3.2(@babel/core@7.23.2)(webpack@5.89.0)
ember-loading: 2.0.0(@babel/core@7.23.2)
ember-local-storage: 2.0.7(@babel/core@7.23.2)
- ember-simple-auth: 6.1.0(@babel/core@7.23.2)(@ember/test-helpers@3.2.0(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(webpack@5.89.0))(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(eslint@8.52.0)
+ ember-simple-auth: 6.1.0(@babel/core@7.23.2)(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(eslint@8.52.0)
ember-wormhole: 0.6.0
socketcluster-client: 17.2.2
transitivePeerDependencies:
- '@ember/string'
- - '@ember/test-helpers'
- '@glint/template'
- bufferutil
- ember-resolver
@@ -12531,29 +12723,28 @@ snapshots:
- utf-8-validate
- webpack
- '@fleetbase/ember-core@0.3.18(@ember/string@3.1.1)(@ember/test-helpers@3.2.0(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(webpack@5.89.0))(ember-resolver@11.0.1(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0)))(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(eslint@8.52.0)(webpack@5.89.0)':
+ '@fleetbase/ember-core@0.3.21(@ember/string@3.1.1)(ember-resolver@11.0.1(ember-source@5.4.0(@babel/core@7.29.0)(@glimmer/component@1.1.2(@babel/core@7.29.0))(rsvp@4.8.5)(webpack@5.89.0)))(ember-source@5.4.0(@babel/core@7.29.0)(@glimmer/component@1.1.2(@babel/core@7.29.0))(rsvp@4.8.5)(webpack@5.89.0))(eslint@8.52.0)(webpack@5.89.0)':
dependencies:
'@babel/core': 7.23.2
compress-json: 3.4.0
date-fns: 2.30.0
ember-auto-import: 2.8.1(webpack@5.89.0)
- ember-can: 6.0.0(@babel/core@7.23.2)(@ember/string@3.1.1)(ember-inflector@4.0.3(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0)))(ember-resolver@11.0.1(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0)))(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))
+ ember-can: 6.0.0(@babel/core@7.23.2)(@ember/string@3.1.1)(ember-inflector@4.0.3(ember-source@5.4.0(@babel/core@7.29.0)(@glimmer/component@1.1.2(@babel/core@7.29.0))(rsvp@4.8.5)(webpack@5.89.0)))(ember-resolver@11.0.1(ember-source@5.4.0(@babel/core@7.29.0)(@glimmer/component@1.1.2(@babel/core@7.29.0))(rsvp@4.8.5)(webpack@5.89.0)))(ember-source@5.4.0(@babel/core@7.29.0)(@glimmer/component@1.1.2(@babel/core@7.29.0))(rsvp@4.8.5)(webpack@5.89.0))
ember-cli-babel: 8.2.0(@babel/core@7.23.2)
ember-cli-htmlbars: 6.3.0
- ember-cli-notifications: 9.1.0(@babel/core@7.23.2)(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))
+ ember-cli-notifications: 9.1.0(@babel/core@7.23.2)(ember-source@5.4.0(@babel/core@7.29.0)(@glimmer/component@1.1.2(@babel/core@7.29.0))(rsvp@4.8.5)(webpack@5.89.0))
ember-concurrency: 4.0.6(@babel/core@7.23.2)
ember-decorators: 6.1.1
ember-get-config: 2.1.1(@babel/core@7.23.2)
- ember-inflector: 4.0.3(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))
+ ember-inflector: 4.0.3(ember-source@5.4.0(@babel/core@7.29.0)(@glimmer/component@1.1.2(@babel/core@7.29.0))(rsvp@4.8.5)(webpack@5.89.0))
ember-intl: 6.3.2(@babel/core@7.23.2)(webpack@5.89.0)
ember-loading: 2.0.0(@babel/core@7.23.2)
ember-local-storage: 2.0.7(@babel/core@7.23.2)
- ember-simple-auth: 6.1.0(@babel/core@7.23.2)(@ember/test-helpers@3.2.0(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(webpack@5.89.0))(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(eslint@8.52.0)
+ ember-simple-auth: 6.1.0(@babel/core@7.23.2)(ember-source@5.4.0(@babel/core@7.29.0)(@glimmer/component@1.1.2(@babel/core@7.29.0))(rsvp@4.8.5)(webpack@5.89.0))(eslint@8.52.0)
ember-wormhole: 0.6.0
socketcluster-client: 17.2.2
transitivePeerDependencies:
- '@ember/string'
- - '@ember/test-helpers'
- '@glint/template'
- bufferutil
- ember-resolver
@@ -12564,13 +12755,14 @@ snapshots:
- utf-8-validate
- webpack
- '@fleetbase/ember-ui@0.3.25(@ember/test-helpers@3.2.0(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(webpack@5.89.0))(@glimmer/component@1.1.2(@babel/core@7.23.2))(@glimmer/tracking@1.1.2)(ember-resolver@11.0.1(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0)))(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(postcss@8.4.35)(rollup@2.79.1)(tracked-built-ins@3.4.0(@babel/core@7.23.2))(webpack@5.89.0)':
+ '@fleetbase/ember-ui@0.3.33(@ember/test-helpers@3.2.0(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(webpack@5.89.0))(@glimmer/component@1.1.2(@babel/core@7.23.2))(@glimmer/tracking@1.1.2)(ember-resolver@11.0.1(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0)))(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(postcss@8.5.8)(rollup@2.79.1)(tracked-built-ins@3.4.0(@babel/core@7.23.2))(webpack@5.89.0)':
dependencies:
'@babel/core': 7.23.2
'@ember/render-modifiers': 2.1.0(@babel/core@7.23.2)(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))
'@ember/string': 3.1.1
'@embroider/addon': 0.30.0
'@embroider/macros': 1.20.0(@babel/core@7.23.2)
+ '@event-calendar/core': 5.7.1
'@fleetbase/ember-accounting': 0.0.1(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))
'@floating-ui/dom': 1.7.6
'@fortawesome/ember-fontawesome': 2.0.0(@babel/core@7.23.2)(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(rollup@2.79.1)(webpack@5.89.0)
@@ -12602,7 +12794,7 @@ snapshots:
'@tiptap/starter-kit': 2.27.2
air-datepicker: 3.6.0
autonumeric: 4.10.9
- autoprefixer: 10.4.27(postcss@8.4.35)
+ autoprefixer: 10.4.27(postcss@8.5.8)
chart.js: 4.5.1
chartjs-adapter-date-fns: 3.0.0(chart.js@4.5.1)(date-fns@2.30.0)
date-fns: 2.30.0
@@ -12641,12 +12833,12 @@ snapshots:
interactjs: 1.10.27
intl-tel-input: 22.0.2
leaflet: 1.9.4
- postcss-at-rules-variables: 0.3.0(postcss@8.4.35)
- postcss-conditionals-renewed: 1.0.0(postcss@8.4.35)
- postcss-each: 1.1.0(postcss@8.4.35)
- postcss-import: 15.1.0(postcss@8.4.35)
- postcss-mixins: 9.0.4(postcss@8.4.35)
- postcss-preset-env: 9.6.0(postcss@8.4.35)
+ postcss-at-rules-variables: 0.3.0(postcss@8.5.8)
+ postcss-conditionals-renewed: 1.0.0(postcss@8.5.8)
+ postcss-each: 1.1.0(postcss@8.5.8)
+ postcss-import: 15.1.0(postcss@8.5.8)
+ postcss-mixins: 9.0.4(postcss@8.5.8)
+ postcss-preset-env: 9.6.0(postcss@8.5.8)
tailwindcss: 3.4.19
transitivePeerDependencies:
- '@ember/test-helpers'
@@ -12654,6 +12846,7 @@ snapshots:
- '@glimmer/tracking'
- '@glint/environment-ember-loose'
- '@glint/template'
+ - '@typescript-eslint/types'
- ember-cli-mirage
- ember-resolver
- ember-source
@@ -12668,16 +12861,15 @@ snapshots:
- webpack-command
- yaml
- '@fleetbase/fleetops-data@0.1.30(@ember/string@3.1.1)(@ember/test-helpers@3.2.0(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(webpack@5.89.0))(ember-resolver@11.0.1(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0)))(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(eslint@8.52.0)(webpack@5.89.0)':
+ '@fleetbase/fleetops-data@0.1.36(@ember/string@3.1.1)(ember-resolver@11.0.1(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0)))(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(eslint@8.52.0)(webpack@5.89.0)':
dependencies:
'@babel/core': 7.23.2
- '@fleetbase/ember-core': 0.3.18(@ember/string@3.1.1)(@ember/test-helpers@3.2.0(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(webpack@5.89.0))(ember-resolver@11.0.1(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0)))(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(eslint@8.52.0)(webpack@5.89.0)
+ '@fleetbase/ember-core': 0.3.20(@ember/string@3.1.1)(ember-resolver@11.0.1(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0)))(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(eslint@8.52.0)(webpack@5.89.0)
date-fns: 2.30.0
ember-cli-babel: 8.2.0(@babel/core@7.23.2)
ember-cli-htmlbars: 6.3.0
transitivePeerDependencies:
- '@ember/string'
- - '@ember/test-helpers'
- '@glint/template'
- bufferutil
- ember-resolver
@@ -12825,21 +13017,41 @@ snapshots:
- '@babel/core'
- supports-color
- '@glimmer/destroyable@0.84.3':
- dependencies:
- '@glimmer/env': 0.1.7
- '@glimmer/global-context': 0.84.3
- '@glimmer/interfaces': 0.84.3
- '@glimmer/util': 0.84.3
-
- '@glimmer/di@0.1.11': {}
-
- '@glimmer/encoder@0.84.3':
+ '@glimmer/component@1.1.2(@babel/core@7.29.0)':
dependencies:
+ '@glimmer/di': 0.1.11
'@glimmer/env': 0.1.7
- '@glimmer/interfaces': 0.84.3
- '@glimmer/vm': 0.84.3
-
+ '@glimmer/util': 0.44.0
+ broccoli-file-creator: 2.1.1
+ broccoli-merge-trees: 3.0.2
+ ember-cli-babel: 7.26.11
+ ember-cli-get-component-path-option: 1.0.0
+ ember-cli-is-package-missing: 1.0.0
+ ember-cli-normalize-entity-name: 1.0.0
+ ember-cli-path-utils: 1.0.0
+ ember-cli-string-utils: 1.1.0
+ ember-cli-typescript: 3.0.0(@babel/core@7.29.0)
+ ember-cli-version-checker: 3.1.3
+ ember-compatibility-helpers: 1.2.7(@babel/core@7.29.0)
+ transitivePeerDependencies:
+ - '@babel/core'
+ - supports-color
+
+ '@glimmer/destroyable@0.84.3':
+ dependencies:
+ '@glimmer/env': 0.1.7
+ '@glimmer/global-context': 0.84.3
+ '@glimmer/interfaces': 0.84.3
+ '@glimmer/util': 0.84.3
+
+ '@glimmer/di@0.1.11': {}
+
+ '@glimmer/encoder@0.84.3':
+ dependencies:
+ '@glimmer/env': 0.1.7
+ '@glimmer/interfaces': 0.84.3
+ '@glimmer/vm': 0.84.3
+
'@glimmer/env@0.1.7': {}
'@glimmer/global-context@0.84.3':
@@ -12950,6 +13162,12 @@ snapshots:
transitivePeerDependencies:
- '@babel/core'
+ '@glimmer/vm-babel-plugins@0.84.3(@babel/core@7.29.0)':
+ dependencies:
+ babel-plugin-debug-macros: 0.3.4(@babel/core@7.29.0)
+ transitivePeerDependencies:
+ - '@babel/core'
+
'@glimmer/vm@0.84.3':
dependencies:
'@glimmer/interfaces': 0.84.3
@@ -12965,7 +13183,7 @@ snapshots:
'@humanwhocodes/config-array@0.11.14':
dependencies:
'@humanwhocodes/object-schema': 2.0.2
- debug: 4.3.4
+ debug: 4.4.3
minimatch: 3.1.2
transitivePeerDependencies:
- supports-color
@@ -13007,8 +13225,8 @@ snapshots:
'@jridgewell/source-map@0.3.5':
dependencies:
- '@jridgewell/gen-mapping': 0.3.3
- '@jridgewell/trace-mapping': 0.3.22
+ '@jridgewell/gen-mapping': 0.3.13
+ '@jridgewell/trace-mapping': 0.3.31
'@jridgewell/sourcemap-codec@1.4.15': {}
@@ -13123,6 +13341,10 @@ snapshots:
'@socket.io/component-emitter@3.1.0': {}
+ '@sveltejs/acorn-typescript@1.0.10(acorn@8.16.0)':
+ dependencies:
+ acorn: 8.16.0
+
'@szmarczak/http-timer@1.1.2':
dependencies:
defer-to-connect: 1.1.3
@@ -13361,6 +13583,8 @@ snapshots:
'@types/estree@1.0.5': {}
+ '@types/estree@1.0.9': {}
+
'@types/express-serve-static-core@4.17.43':
dependencies:
'@types/node': 20.11.19
@@ -13454,6 +13678,8 @@ snapshots:
'@types/symlink-or-copy@1.2.2': {}
+ '@types/trusted-types@2.0.7': {}
+
'@ungap/structured-clone@1.2.0': {}
'@webassemblyjs/ast@1.11.6':
@@ -13650,6 +13876,8 @@ snapshots:
acorn@8.11.3: {}
+ acorn@8.16.0: {}
+
ag-channel@5.0.0:
dependencies:
consumable-stream: 2.0.0
@@ -13773,6 +14001,8 @@ snapshots:
dependencies:
dequal: 2.0.3
+ aria-query@5.3.1: {}
+
arr-diff@4.0.0: {}
arr-flatten@1.1.0: {}
@@ -13882,13 +14112,13 @@ snapshots:
autonumeric@4.10.9: {}
- autoprefixer@10.4.27(postcss@8.4.35):
+ autoprefixer@10.4.27(postcss@8.5.8):
dependencies:
browserslist: 4.28.1
caniuse-lite: 1.0.30001774
fraction.js: 5.3.4
picocolors: 1.1.1
- postcss: 8.4.35
+ postcss: 8.5.8
postcss-value-parser: 4.2.0
available-typed-arrays@1.0.6: {}
@@ -13897,6 +14127,8 @@ snapshots:
dependencies:
possible-typed-array-names: 1.1.0
+ axobject-query@4.1.0: {}
+
babel-code-frame@6.26.0:
dependencies:
chalk: 1.1.3
@@ -13984,6 +14216,11 @@ snapshots:
'@babel/core': 7.23.2
semver: 5.7.2
+ babel-plugin-debug-macros@0.2.0(@babel/core@7.29.0):
+ dependencies:
+ '@babel/core': 7.29.0
+ semver: 5.7.2
+
babel-plugin-debug-macros@0.3.4(@babel/core@7.23.2):
dependencies:
'@babel/core': 7.23.2
@@ -14009,7 +14246,7 @@ snapshots:
babel-plugin-filter-imports@4.0.0:
dependencies:
- '@babel/types': 7.23.9
+ '@babel/types': 7.29.7
lodash: 4.17.21
babel-plugin-htmlbars-inline-precompile@3.2.0: {}
@@ -14238,6 +14475,8 @@ snapshots:
baseline-browser-mapping@2.10.0: {}
+ baseline-browser-mapping@2.10.33: {}
+
basic-auth@2.0.1:
dependencies:
safe-buffer: 5.1.2
@@ -14970,6 +15209,14 @@ snapshots:
node-releases: 2.0.27
update-browserslist-db: 1.2.3(browserslist@4.28.1)
+ browserslist@4.28.2:
+ dependencies:
+ baseline-browser-mapping: 2.10.33
+ caniuse-lite: 1.0.30001793
+ electron-to-chromium: 1.5.368
+ node-releases: 2.0.47
+ update-browserslist-db: 1.2.3(browserslist@4.28.2)
+
bser@2.1.1:
dependencies:
node-int64: 0.4.0
@@ -15107,6 +15354,8 @@ snapshots:
caniuse-lite@1.0.30001774: {}
+ caniuse-lite@1.0.30001793: {}
+
capture-exit@2.0.0:
dependencies:
rsvp: 4.8.5
@@ -15271,6 +15520,8 @@ snapshots:
clone@2.1.2: {}
+ clsx@2.1.1: {}
+
collection-visit@1.0.0:
dependencies:
map-visit: 1.0.0
@@ -15517,9 +15768,9 @@ snapshots:
crypto-random-string@2.0.0: {}
- css-blank-pseudo@6.0.2(postcss@8.4.35):
+ css-blank-pseudo@6.0.2(postcss@8.5.8):
dependencies:
- postcss: 8.4.35
+ postcss: 8.5.8
postcss-selector-parser: 6.0.15
css-color-converter@2.0.0:
@@ -15530,10 +15781,10 @@ snapshots:
css-functions-list@3.2.1: {}
- css-has-pseudo@6.0.5(postcss@8.4.35):
+ css-has-pseudo@6.0.5(postcss@8.5.8):
dependencies:
'@csstools/selector-specificity': 3.1.1(postcss-selector-parser@6.0.15)
- postcss: 8.4.35
+ postcss: 8.5.8
postcss-selector-parser: 6.0.15
postcss-value-parser: 4.2.0
@@ -15551,9 +15802,9 @@ snapshots:
semver: 7.6.0
webpack: 5.89.0
- css-prefers-color-scheme@9.0.1(postcss@8.4.35):
+ css-prefers-color-scheme@9.0.1(postcss@8.5.8):
dependencies:
- postcss: 8.4.35
+ postcss: 8.5.8
css-tree@2.3.1:
dependencies:
@@ -15609,7 +15860,14 @@ snapshots:
decorator-transforms@1.2.1(@babel/core@7.23.2):
dependencies:
- '@babel/plugin-syntax-decorators': 7.28.6(@babel/core@7.23.2)
+ '@babel/plugin-syntax-decorators': 7.29.7(@babel/core@7.23.2)
+ babel-import-util: 2.1.1
+ transitivePeerDependencies:
+ - '@babel/core'
+
+ decorator-transforms@1.2.1(@babel/core@7.29.0):
+ dependencies:
+ '@babel/plugin-syntax-decorators': 7.29.7(@babel/core@7.29.0)
babel-import-util: 2.1.1
transitivePeerDependencies:
- '@babel/core'
@@ -15628,6 +15886,13 @@ snapshots:
transitivePeerDependencies:
- '@babel/core'
+ decorator-transforms@2.3.2(@babel/core@7.23.2):
+ dependencies:
+ '@babel/plugin-syntax-decorators': 7.29.7(@babel/core@7.23.2)
+ babel-import-util: 3.0.1
+ transitivePeerDependencies:
+ - '@babel/core'
+
deep-extend@0.6.0: {}
deep-is@0.1.4: {}
@@ -15690,6 +15955,8 @@ snapshots:
detect-newline@3.1.0: {}
+ devalue@5.8.1: {}
+
didyoumean@1.2.2: {}
diff@5.2.0: {}
@@ -15751,6 +16018,8 @@ snapshots:
electron-to-chromium@1.5.302: {}
+ electron-to-chromium@1.5.368: {}
+
element-closest@3.0.2: {}
elliptic@6.6.1:
@@ -15986,6 +16255,18 @@ snapshots:
- '@babel/core'
- supports-color
+ ember-can@6.0.0(@babel/core@7.23.2)(@ember/string@3.1.1)(ember-inflector@4.0.3(ember-source@5.4.0(@babel/core@7.29.0)(@glimmer/component@1.1.2(@babel/core@7.29.0))(rsvp@4.8.5)(webpack@5.89.0)))(ember-resolver@11.0.1(ember-source@5.4.0(@babel/core@7.29.0)(@glimmer/component@1.1.2(@babel/core@7.29.0))(rsvp@4.8.5)(webpack@5.89.0)))(ember-source@5.4.0(@babel/core@7.29.0)(@glimmer/component@1.1.2(@babel/core@7.29.0))(rsvp@4.8.5)(webpack@5.89.0)):
+ dependencies:
+ '@ember/string': 3.1.1
+ '@embroider/addon-shim': 1.10.2
+ decorator-transforms: 2.3.1(@babel/core@7.23.2)
+ ember-inflector: 4.0.3(ember-source@5.4.0(@babel/core@7.29.0)(@glimmer/component@1.1.2(@babel/core@7.29.0))(rsvp@4.8.5)(webpack@5.89.0))
+ ember-resolver: 11.0.1(ember-source@5.4.0(@babel/core@7.29.0)(@glimmer/component@1.1.2(@babel/core@7.29.0))(rsvp@4.8.5)(webpack@5.89.0))
+ ember-source: 5.4.0(@babel/core@7.29.0)(@glimmer/component@1.1.2(@babel/core@7.29.0))(rsvp@4.8.5)(webpack@5.89.0)
+ transitivePeerDependencies:
+ - '@babel/core'
+ - supports-color
+
ember-cli-babel-plugin-helpers@1.1.1: {}
ember-cli-babel@7.26.11:
@@ -16269,6 +16550,15 @@ snapshots:
- '@babel/core'
- supports-color
+ ember-cli-notifications@9.1.0(@babel/core@7.23.2)(ember-source@5.4.0(@babel/core@7.29.0)(@glimmer/component@1.1.2(@babel/core@7.29.0))(rsvp@4.8.5)(webpack@5.89.0)):
+ dependencies:
+ '@embroider/addon-shim': 1.10.2
+ decorator-transforms: 2.3.1(@babel/core@7.23.2)
+ ember-source: 5.4.0(@babel/core@7.29.0)(@glimmer/component@1.1.2(@babel/core@7.29.0))(rsvp@4.8.5)(webpack@5.89.0)
+ transitivePeerDependencies:
+ - '@babel/core'
+ - supports-color
+
ember-cli-path-utils@1.0.0: {}
ember-cli-postcss@8.2.0:
@@ -16372,16 +16662,13 @@ snapshots:
- '@babel/core'
- supports-color
- ember-cli-typescript@3.1.4(@babel/core@7.23.2):
+ ember-cli-typescript@3.0.0(@babel/core@7.29.0):
dependencies:
- '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6(@babel/core@7.23.2)
- '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.23.2)
- '@babel/plugin-transform-typescript': 7.8.7(@babel/core@7.23.2)
+ '@babel/plugin-transform-typescript': 7.5.5(@babel/core@7.29.0)
ansi-to-html: 0.6.15
- broccoli-stew: 3.0.0
- debug: 4.3.4
+ debug: 4.4.3
ember-cli-babel-plugin-helpers: 1.1.1
- execa: 3.4.0
+ execa: 2.1.0
fs-extra: 8.1.0
resolve: 1.22.8
rsvp: 4.8.5
@@ -16602,6 +16889,17 @@ snapshots:
- '@babel/core'
- supports-color
+ ember-compatibility-helpers@1.2.7(@babel/core@7.29.0):
+ dependencies:
+ babel-plugin-debug-macros: 0.2.0(@babel/core@7.29.0)
+ ember-cli-version-checker: 5.1.2
+ find-up: 5.0.0
+ fs-extra: 9.1.0
+ semver: 5.7.2
+ transitivePeerDependencies:
+ - '@babel/core'
+ - supports-color
+
ember-composability-tools@1.2.0(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(webpack@5.89.0):
dependencies:
'@babel/core': 7.23.2
@@ -16638,16 +16936,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- ember-concurrency-decorators@2.0.3(@babel/core@7.23.2):
- dependencies:
- '@ember-decorators/utils': 6.1.1
- ember-cli-babel: 7.26.11
- ember-cli-htmlbars: 4.5.0
- ember-cli-typescript: 3.1.4(@babel/core@7.23.2)
- transitivePeerDependencies:
- - '@babel/core'
- - supports-color
-
ember-concurrency-ts@0.3.1(ember-concurrency@2.3.7(@babel/core@7.23.2)):
dependencies:
ember-cli-babel: 7.26.11
@@ -16670,27 +16958,24 @@ snapshots:
- '@babel/core'
- supports-color
- ember-concurrency@3.1.1(@babel/core@7.23.2)(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0)):
+ ember-concurrency@4.0.6(@babel/core@7.23.2):
dependencies:
- '@babel/helper-plugin-utils': 7.22.5
- '@babel/types': 7.23.9
- '@glimmer/tracking': 1.1.2
- ember-cli-babel: 7.26.11
- ember-cli-babel-plugin-helpers: 1.1.1
- ember-cli-htmlbars: 6.3.0
- ember-compatibility-helpers: 1.2.7(@babel/core@7.23.2)
- ember-source: 5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0)
+ '@babel/helper-module-imports': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+ '@babel/types': 7.29.7
+ '@embroider/addon-shim': 1.10.2
+ decorator-transforms: 1.2.1(@babel/core@7.23.2)
transitivePeerDependencies:
- '@babel/core'
- supports-color
- ember-concurrency@4.0.6(@babel/core@7.23.2):
+ ember-concurrency@4.0.6(@babel/core@7.29.0):
dependencies:
- '@babel/helper-module-imports': 7.28.6
- '@babel/helper-plugin-utils': 7.28.6
- '@babel/types': 7.29.0
+ '@babel/helper-module-imports': 7.29.7
+ '@babel/helper-plugin-utils': 7.29.7
+ '@babel/types': 7.29.7
'@embroider/addon-shim': 1.10.2
- decorator-transforms: 1.2.1(@babel/core@7.23.2)
+ decorator-transforms: 1.2.1(@babel/core@7.29.0)
transitivePeerDependencies:
- '@babel/core'
- supports-color
@@ -16702,6 +16987,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ ember-cookies@1.3.0(ember-source@5.4.0(@babel/core@7.29.0)(@glimmer/component@1.1.2(@babel/core@7.29.0))(rsvp@4.8.5)(webpack@5.89.0)):
+ dependencies:
+ '@embroider/addon-shim': 1.10.2
+ ember-source: 5.4.0(@babel/core@7.29.0)(@glimmer/component@1.1.2(@babel/core@7.29.0))(rsvp@4.8.5)(webpack@5.89.0)
+ transitivePeerDependencies:
+ - supports-color
+
ember-copy@2.0.1:
dependencies:
ember-cli-babel: 7.26.11
@@ -16710,7 +17002,7 @@ snapshots:
ember-data@4.12.5(@babel/core@7.23.2)(@ember/string@3.1.1)(@glimmer/tracking@1.1.2)(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(webpack@5.89.0):
dependencies:
- '@ember-data/adapter': 4.12.5(@ember-data/store@4.12.5(@babel/core@7.23.2)(@ember-data/graph@4.12.5)(@ember-data/json-api@4.12.5)(@ember-data/legacy-compat@4.12.5)(@ember-data/model@4.12.5)(@ember-data/tracking@4.12.5)(@ember/string@3.1.1)(@glimmer/tracking@1.1.2)(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0)))(@ember/string@3.1.1)(ember-inflector@4.0.2)
+ '@ember-data/adapter': 4.12.5(@ember-data/store@4.12.5)(@ember/string@3.1.1)(ember-inflector@4.0.2)
'@ember-data/debug': 4.12.5(@ember-data/store@4.12.5)(@ember/string@3.1.1)(webpack@5.89.0)
'@ember-data/graph': 4.12.5(@ember-data/store@4.12.5)
'@ember-data/json-api': 4.12.5(@ember-data/graph@4.12.5)(@ember-data/store@4.12.5)
@@ -16718,7 +17010,7 @@ snapshots:
'@ember-data/model': 4.12.5(@babel/core@7.23.2)(@ember-data/debug@4.12.5)(@ember-data/graph@4.12.5)(@ember-data/json-api@4.12.5)(@ember-data/legacy-compat@4.12.5)(@ember-data/store@4.12.5)(@ember-data/tracking@4.12.5)(@ember/string@3.1.1)(ember-inflector@4.0.3(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0)))(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))
'@ember-data/private-build-infra': 4.12.5
'@ember-data/request': 4.12.5
- '@ember-data/serializer': 4.12.5(@ember-data/store@4.12.5(@babel/core@7.23.2)(@ember-data/graph@4.12.5)(@ember-data/json-api@4.12.5)(@ember-data/legacy-compat@4.12.5)(@ember-data/model@4.12.5)(@ember-data/tracking@4.12.5)(@ember/string@3.1.1)(@glimmer/tracking@1.1.2)(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0)))(@ember/string@3.1.1)(ember-inflector@4.0.2)
+ '@ember-data/serializer': 4.12.5(@ember-data/store@4.12.5)(@ember/string@3.1.1)(ember-inflector@4.0.2)
'@ember-data/store': 4.12.5(@babel/core@7.23.2)(@ember-data/graph@4.12.5)(@ember-data/json-api@4.12.5)(@ember-data/legacy-compat@4.12.5)(@ember-data/model@4.12.5)(@ember-data/tracking@4.12.5)(@ember/string@3.1.1)(@glimmer/tracking@1.1.2)(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))
'@ember-data/tracking': 4.12.5
'@ember/edition-utils': 1.2.0
@@ -16902,6 +17194,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ ember-inflector@4.0.3(ember-source@5.4.0(@babel/core@7.29.0)(@glimmer/component@1.1.2(@babel/core@7.29.0))(rsvp@4.8.5)(webpack@5.89.0)):
+ dependencies:
+ ember-cli-babel: 7.26.11
+ ember-source: 5.4.0(@babel/core@7.29.0)(@glimmer/component@1.1.2(@babel/core@7.29.0))(rsvp@4.8.5)(webpack@5.89.0)
+ transitivePeerDependencies:
+ - supports-color
+
ember-intl@6.3.2(@babel/core@7.23.2)(webpack@5.89.0):
dependencies:
'@formatjs/icu-messageformat-parser': 2.7.6
@@ -17158,6 +17457,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ ember-resolver@11.0.1(ember-source@5.4.0(@babel/core@7.29.0)(@glimmer/component@1.1.2(@babel/core@7.29.0))(rsvp@4.8.5)(webpack@5.89.0)):
+ dependencies:
+ ember-cli-babel: 7.26.11
+ optionalDependencies:
+ ember-source: 5.4.0(@babel/core@7.29.0)(@glimmer/component@1.1.2(@babel/core@7.29.0))(rsvp@4.8.5)(webpack@5.89.0)
+ transitivePeerDependencies:
+ - supports-color
+
ember-responsive@5.0.0:
dependencies:
ember-cli-babel: 7.26.11
@@ -17168,13 +17475,13 @@ snapshots:
ember-router-generator@2.0.0:
dependencies:
- '@babel/parser': 7.23.9
- '@babel/traverse': 7.23.9
+ '@babel/parser': 7.29.7
+ '@babel/traverse': 7.29.7
recast: 0.18.10
transitivePeerDependencies:
- supports-color
- ember-simple-auth@6.1.0(@babel/core@7.23.2)(@ember/test-helpers@3.2.0(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(webpack@5.89.0))(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(eslint@8.52.0):
+ ember-simple-auth@6.1.0(@babel/core@7.23.2)(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(eslint@8.52.0):
dependencies:
'@babel/eslint-parser': 7.28.6(@babel/core@7.23.2)(eslint@8.52.0)
'@ember/test-waiters': 3.1.0
@@ -17183,8 +17490,22 @@ snapshots:
ember-cli-is-package-missing: 1.0.0
ember-cookies: 1.3.0(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))
silent-error: 1.1.1
- optionalDependencies:
- '@ember/test-helpers': 3.2.0(ember-source@5.4.0(@babel/core@7.23.2)(@glimmer/component@1.1.2(@babel/core@7.23.2))(rsvp@4.8.5)(webpack@5.89.0))(webpack@5.89.0)
+ transitivePeerDependencies:
+ - '@babel/core'
+ - '@glint/template'
+ - ember-source
+ - eslint
+ - supports-color
+
+ ember-simple-auth@6.1.0(@babel/core@7.23.2)(ember-source@5.4.0(@babel/core@7.29.0)(@glimmer/component@1.1.2(@babel/core@7.29.0))(rsvp@4.8.5)(webpack@5.89.0))(eslint@8.52.0):
+ dependencies:
+ '@babel/eslint-parser': 7.28.6(@babel/core@7.23.2)(eslint@8.52.0)
+ '@ember/test-waiters': 3.1.0
+ '@embroider/addon-shim': 1.10.2
+ '@embroider/macros': 1.20.0(@babel/core@7.23.2)
+ ember-cli-is-package-missing: 1.0.0
+ ember-cookies: 1.3.0(ember-source@5.4.0(@babel/core@7.29.0)(@glimmer/component@1.1.2(@babel/core@7.29.0))(rsvp@4.8.5)(webpack@5.89.0))
+ silent-error: 1.1.1
transitivePeerDependencies:
- '@babel/core'
- '@glint/template'
@@ -17253,6 +17574,61 @@ snapshots:
- supports-color
- webpack
+ ember-source@5.4.0(@babel/core@7.29.0)(@glimmer/component@1.1.2(@babel/core@7.29.0))(rsvp@4.8.5)(webpack@5.89.0):
+ dependencies:
+ '@babel/helper-module-imports': 7.29.7
+ '@babel/plugin-transform-block-scoping': 7.23.4(@babel/core@7.29.0)
+ '@ember/edition-utils': 1.2.0
+ '@glimmer/compiler': 0.84.3
+ '@glimmer/component': 1.1.2(@babel/core@7.29.0)
+ '@glimmer/destroyable': 0.84.3
+ '@glimmer/env': 0.1.7
+ '@glimmer/global-context': 0.84.3
+ '@glimmer/interfaces': 0.84.3
+ '@glimmer/manager': 0.84.3
+ '@glimmer/node': 0.84.3
+ '@glimmer/opcode-compiler': 0.84.3
+ '@glimmer/owner': 0.84.3
+ '@glimmer/program': 0.84.3
+ '@glimmer/reference': 0.84.3
+ '@glimmer/runtime': 0.84.3
+ '@glimmer/syntax': 0.84.3
+ '@glimmer/util': 0.84.3
+ '@glimmer/validator': 0.84.3
+ '@glimmer/vm-babel-plugins': 0.84.3(@babel/core@7.29.0)
+ '@simple-dom/interface': 1.4.0
+ babel-plugin-debug-macros: 0.3.4(@babel/core@7.29.0)
+ babel-plugin-filter-imports: 4.0.0
+ backburner.js: 2.8.0
+ broccoli-concat: 4.2.5
+ broccoli-debug: 0.6.5
+ broccoli-file-creator: 2.1.1
+ broccoli-funnel: 3.0.8
+ broccoli-merge-trees: 4.2.0
+ chalk: 4.1.2
+ ember-auto-import: 2.8.1(webpack@5.89.0)
+ ember-cli-babel: 7.26.11
+ ember-cli-get-component-path-option: 1.0.0
+ ember-cli-is-package-missing: 1.0.0
+ ember-cli-normalize-entity-name: 1.0.0
+ ember-cli-path-utils: 1.0.0
+ ember-cli-string-utils: 1.1.0
+ ember-cli-typescript-blueprint-polyfill: 0.1.0
+ ember-cli-version-checker: 5.1.2
+ ember-router-generator: 2.0.0
+ inflection: 2.0.1
+ resolve: 1.22.8
+ route-recognizer: 0.3.4
+ router_js: 8.0.3(route-recognizer@0.3.4)(rsvp@4.8.5)
+ semver: 7.6.0
+ silent-error: 1.1.1
+ transitivePeerDependencies:
+ - '@babel/core'
+ - '@glint/template'
+ - rsvp
+ - supports-color
+ - webpack
+
ember-style-modifier@3.1.1(@babel/core@7.23.2)(@ember/string@3.1.1)(webpack@5.89.0):
dependencies:
'@ember/string': 3.1.1
@@ -17344,10 +17720,9 @@ snapshots:
transitivePeerDependencies:
- supports-color
- ember-tracked-storage-polyfill@1.0.0:
+ ember-tracked-storage-polyfill@1.0.1:
dependencies:
ember-cli-babel: 7.26.11
- ember-cli-htmlbars: 5.7.2
transitivePeerDependencies:
- supports-color
@@ -17654,7 +18029,7 @@ snapshots:
ajv: 6.12.6
chalk: 4.1.2
cross-spawn: 7.0.3
- debug: 4.3.4
+ debug: 4.4.3
doctrine: 3.0.0
escape-string-regexp: 4.0.0
eslint-scope: 7.2.2
@@ -17684,6 +18059,8 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ esm-env@1.2.2: {}
+
esm@3.2.25: {}
espree@9.6.1:
@@ -17700,6 +18077,10 @@ snapshots:
dependencies:
estraverse: 5.3.0
+ esrap@2.2.11:
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.5
+
esrecurse@4.3.0:
dependencies:
estraverse: 5.3.0
@@ -17753,19 +18134,6 @@ snapshots:
signal-exit: 3.0.7
strip-final-newline: 2.0.0
- execa@3.4.0:
- dependencies:
- cross-spawn: 7.0.3
- get-stream: 5.2.0
- human-signals: 1.1.1
- is-stream: 2.0.1
- merge-stream: 2.0.0
- npm-run-path: 4.0.1
- onetime: 5.1.2
- p-finally: 2.0.1
- signal-exit: 3.0.7
- strip-final-newline: 2.0.0
-
execa@4.1.0:
dependencies:
cross-spawn: 7.0.3
@@ -18964,6 +19332,10 @@ snapshots:
is-plain-object@5.0.0: {}
+ is-reference@3.0.3:
+ dependencies:
+ '@types/estree': 1.0.9
+
is-regex@1.1.4:
dependencies:
call-bind: 1.0.7
@@ -19215,6 +19587,8 @@ snapshots:
loader.js@4.7.0: {}
+ locate-character@3.0.0: {}
+
locate-path@2.0.0:
dependencies:
p-locate: 2.0.0
@@ -19341,6 +19715,10 @@ snapshots:
dependencies:
sourcemap-codec: 1.4.8
+ magic-string@0.30.21:
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.5
+
magic-string@0.30.7:
dependencies:
'@jridgewell/sourcemap-codec': 1.4.15
@@ -19752,6 +20130,8 @@ snapshots:
node-releases@2.0.27: {}
+ node-releases@2.0.47: {}
+
node-watch@0.7.3: {}
nopt@3.0.6:
@@ -20105,119 +20485,112 @@ snapshots:
possible-typed-array-names@1.1.0: {}
- postcss-at-rules-variables@0.3.0(postcss@8.4.35):
+ postcss-at-rules-variables@0.3.0(postcss@8.5.8):
dependencies:
- postcss: 8.4.35
+ postcss: 8.5.8
- postcss-attribute-case-insensitive@6.0.3(postcss@8.4.35):
+ postcss-attribute-case-insensitive@6.0.3(postcss@8.5.8):
dependencies:
- postcss: 8.4.35
+ postcss: 8.5.8
postcss-selector-parser: 6.0.15
- postcss-clamp@4.1.0(postcss@8.4.35):
+ postcss-clamp@4.1.0(postcss@8.5.8):
dependencies:
- postcss: 8.4.35
+ postcss: 8.5.8
postcss-value-parser: 4.2.0
- postcss-color-functional-notation@6.0.14(postcss@8.4.35):
+ postcss-color-functional-notation@6.0.14(postcss@8.5.8):
dependencies:
'@csstools/css-color-parser': 2.0.5(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1)
'@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1)
'@csstools/css-tokenizer': 2.4.1
- '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.35)
- '@csstools/utilities': 1.0.0(postcss@8.4.35)
- postcss: 8.4.35
+ '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.5.8)
+ '@csstools/utilities': 1.0.0(postcss@8.5.8)
+ postcss: 8.5.8
- postcss-color-hex-alpha@9.0.4(postcss@8.4.35):
+ postcss-color-hex-alpha@9.0.4(postcss@8.5.8):
dependencies:
- '@csstools/utilities': 1.0.0(postcss@8.4.35)
- postcss: 8.4.35
+ '@csstools/utilities': 1.0.0(postcss@8.5.8)
+ postcss: 8.5.8
postcss-value-parser: 4.2.0
- postcss-color-rebeccapurple@9.0.3(postcss@8.4.35):
+ postcss-color-rebeccapurple@9.0.3(postcss@8.5.8):
dependencies:
- '@csstools/utilities': 1.0.0(postcss@8.4.35)
- postcss: 8.4.35
+ '@csstools/utilities': 1.0.0(postcss@8.5.8)
+ postcss: 8.5.8
postcss-value-parser: 4.2.0
- postcss-conditionals-renewed@1.0.0(postcss@8.4.35):
+ postcss-conditionals-renewed@1.0.0(postcss@8.5.8):
dependencies:
css-color-converter: 2.0.0
css-unit-converter: 1.1.2
- postcss: 8.4.35
+ postcss: 8.5.8
- postcss-custom-media@10.0.8(postcss@8.4.35):
+ postcss-custom-media@10.0.8(postcss@8.5.8):
dependencies:
'@csstools/cascade-layer-name-parser': 1.0.13(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1)
'@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1)
'@csstools/css-tokenizer': 2.4.1
'@csstools/media-query-list-parser': 2.1.13(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1)
- postcss: 8.4.35
+ postcss: 8.5.8
- postcss-custom-properties@13.3.12(postcss@8.4.35):
+ postcss-custom-properties@13.3.12(postcss@8.5.8):
dependencies:
'@csstools/cascade-layer-name-parser': 1.0.13(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1)
'@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1)
'@csstools/css-tokenizer': 2.4.1
- '@csstools/utilities': 1.0.0(postcss@8.4.35)
- postcss: 8.4.35
+ '@csstools/utilities': 1.0.0(postcss@8.5.8)
+ postcss: 8.5.8
postcss-value-parser: 4.2.0
- postcss-custom-selectors@7.1.12(postcss@8.4.35):
+ postcss-custom-selectors@7.1.12(postcss@8.5.8):
dependencies:
'@csstools/cascade-layer-name-parser': 1.0.13(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1)
'@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1)
'@csstools/css-tokenizer': 2.4.1
- postcss: 8.4.35
+ postcss: 8.5.8
postcss-selector-parser: 6.1.2
- postcss-dir-pseudo-class@8.0.1(postcss@8.4.35):
+ postcss-dir-pseudo-class@8.0.1(postcss@8.5.8):
dependencies:
- postcss: 8.4.35
+ postcss: 8.5.8
postcss-selector-parser: 6.0.15
- postcss-double-position-gradients@5.0.7(postcss@8.4.35):
+ postcss-double-position-gradients@5.0.7(postcss@8.5.8):
dependencies:
- '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.35)
- '@csstools/utilities': 1.0.0(postcss@8.4.35)
- postcss: 8.4.35
+ '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.5.8)
+ '@csstools/utilities': 1.0.0(postcss@8.5.8)
+ postcss: 8.5.8
postcss-value-parser: 4.2.0
- postcss-each@1.1.0(postcss@8.4.35):
+ postcss-each@1.1.0(postcss@8.5.8):
dependencies:
- postcss: 8.4.35
- postcss-simple-vars: 6.0.3(postcss@8.4.35)
+ postcss: 8.5.8
+ postcss-simple-vars: 6.0.3(postcss@8.5.8)
- postcss-focus-visible@9.0.1(postcss@8.4.35):
+ postcss-focus-visible@9.0.1(postcss@8.5.8):
dependencies:
- postcss: 8.4.35
+ postcss: 8.5.8
postcss-selector-parser: 6.0.15
- postcss-focus-within@8.0.1(postcss@8.4.35):
+ postcss-focus-within@8.0.1(postcss@8.5.8):
dependencies:
- postcss: 8.4.35
+ postcss: 8.5.8
postcss-selector-parser: 6.0.15
- postcss-font-variant@5.0.0(postcss@8.4.35):
- dependencies:
- postcss: 8.4.35
-
- postcss-gap-properties@5.0.1(postcss@8.4.35):
+ postcss-font-variant@5.0.0(postcss@8.5.8):
dependencies:
- postcss: 8.4.35
+ postcss: 8.5.8
- postcss-image-set-function@6.0.3(postcss@8.4.35):
+ postcss-gap-properties@5.0.1(postcss@8.5.8):
dependencies:
- '@csstools/utilities': 1.0.0(postcss@8.4.35)
- postcss: 8.4.35
- postcss-value-parser: 4.2.0
+ postcss: 8.5.8
- postcss-import@15.1.0(postcss@8.4.35):
+ postcss-image-set-function@6.0.3(postcss@8.5.8):
dependencies:
- postcss: 8.4.35
+ '@csstools/utilities': 1.0.0(postcss@8.5.8)
+ postcss: 8.5.8
postcss-value-parser: 4.2.0
- read-cache: 1.0.0
- resolve: 1.22.11
postcss-import@15.1.0(postcss@8.5.8):
dependencies:
@@ -20226,24 +20599,19 @@ snapshots:
read-cache: 1.0.0
resolve: 1.22.11
- postcss-js@4.1.0(postcss@8.4.35):
- dependencies:
- camelcase-css: 2.0.1
- postcss: 8.4.35
-
postcss-js@4.1.0(postcss@8.5.8):
dependencies:
camelcase-css: 2.0.1
postcss: 8.5.8
- postcss-lab-function@6.0.19(postcss@8.4.35):
+ postcss-lab-function@6.0.19(postcss@8.5.8):
dependencies:
'@csstools/css-color-parser': 2.0.5(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1)
'@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1)
'@csstools/css-tokenizer': 2.4.1
- '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.35)
- '@csstools/utilities': 1.0.0(postcss@8.4.35)
- postcss: 8.4.35
+ '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.5.8)
+ '@csstools/utilities': 1.0.0(postcss@8.5.8)
+ postcss: 8.5.8
postcss-load-config@6.0.1(jiti@1.21.7)(postcss@8.5.8):
dependencies:
@@ -20252,18 +20620,18 @@ snapshots:
jiti: 1.21.7
postcss: 8.5.8
- postcss-logical@7.0.1(postcss@8.4.35):
+ postcss-logical@7.0.1(postcss@8.5.8):
dependencies:
- postcss: 8.4.35
+ postcss: 8.5.8
postcss-value-parser: 4.2.0
- postcss-mixins@9.0.4(postcss@8.4.35):
+ postcss-mixins@9.0.4(postcss@8.5.8):
dependencies:
fast-glob: 3.3.2
- postcss: 8.4.35
- postcss-js: 4.1.0(postcss@8.4.35)
- postcss-simple-vars: 7.0.1(postcss@8.4.35)
- sugarss: 4.0.1(postcss@8.4.35)
+ postcss: 8.5.8
+ postcss-js: 4.1.0(postcss@8.5.8)
+ postcss-simple-vars: 7.0.1(postcss@8.5.8)
+ sugarss: 4.0.1(postcss@8.5.8)
postcss-modules-extract-imports@3.0.0(postcss@8.4.35):
dependencies:
@@ -20291,104 +20659,104 @@ snapshots:
postcss: 8.5.8
postcss-selector-parser: 6.1.2
- postcss-nesting@12.1.5(postcss@8.4.35):
+ postcss-nesting@12.1.5(postcss@8.5.8):
dependencies:
'@csstools/selector-resolve-nested': 1.1.0(postcss-selector-parser@6.1.2)
'@csstools/selector-specificity': 3.1.1(postcss-selector-parser@6.1.2)
- postcss: 8.4.35
+ postcss: 8.5.8
postcss-selector-parser: 6.1.2
- postcss-opacity-percentage@2.0.0(postcss@8.4.35):
+ postcss-opacity-percentage@2.0.0(postcss@8.5.8):
dependencies:
- postcss: 8.4.35
+ postcss: 8.5.8
- postcss-overflow-shorthand@5.0.1(postcss@8.4.35):
+ postcss-overflow-shorthand@5.0.1(postcss@8.5.8):
dependencies:
- postcss: 8.4.35
+ postcss: 8.5.8
postcss-value-parser: 4.2.0
- postcss-page-break@3.0.4(postcss@8.4.35):
+ postcss-page-break@3.0.4(postcss@8.5.8):
dependencies:
- postcss: 8.4.35
+ postcss: 8.5.8
- postcss-place@9.0.1(postcss@8.4.35):
+ postcss-place@9.0.1(postcss@8.5.8):
dependencies:
- postcss: 8.4.35
+ postcss: 8.5.8
postcss-value-parser: 4.2.0
- postcss-preset-env@9.6.0(postcss@8.4.35):
- dependencies:
- '@csstools/postcss-cascade-layers': 4.0.6(postcss@8.4.35)
- '@csstools/postcss-color-function': 3.0.19(postcss@8.4.35)
- '@csstools/postcss-color-mix-function': 2.0.19(postcss@8.4.35)
- '@csstools/postcss-content-alt-text': 1.0.0(postcss@8.4.35)
- '@csstools/postcss-exponential-functions': 1.0.9(postcss@8.4.35)
- '@csstools/postcss-font-format-keywords': 3.0.2(postcss@8.4.35)
- '@csstools/postcss-gamut-mapping': 1.0.11(postcss@8.4.35)
- '@csstools/postcss-gradients-interpolation-method': 4.0.20(postcss@8.4.35)
- '@csstools/postcss-hwb-function': 3.0.18(postcss@8.4.35)
- '@csstools/postcss-ic-unit': 3.0.7(postcss@8.4.35)
- '@csstools/postcss-initial': 1.0.1(postcss@8.4.35)
- '@csstools/postcss-is-pseudo-class': 4.0.8(postcss@8.4.35)
- '@csstools/postcss-light-dark-function': 1.0.8(postcss@8.4.35)
- '@csstools/postcss-logical-float-and-clear': 2.0.1(postcss@8.4.35)
- '@csstools/postcss-logical-overflow': 1.0.1(postcss@8.4.35)
- '@csstools/postcss-logical-overscroll-behavior': 1.0.1(postcss@8.4.35)
- '@csstools/postcss-logical-resize': 2.0.1(postcss@8.4.35)
- '@csstools/postcss-logical-viewport-units': 2.0.11(postcss@8.4.35)
- '@csstools/postcss-media-minmax': 1.1.8(postcss@8.4.35)
- '@csstools/postcss-media-queries-aspect-ratio-number-values': 2.0.11(postcss@8.4.35)
- '@csstools/postcss-nested-calc': 3.0.2(postcss@8.4.35)
- '@csstools/postcss-normalize-display-values': 3.0.2(postcss@8.4.35)
- '@csstools/postcss-oklab-function': 3.0.19(postcss@8.4.35)
- '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.4.35)
- '@csstools/postcss-relative-color-syntax': 2.0.19(postcss@8.4.35)
- '@csstools/postcss-scope-pseudo-class': 3.0.1(postcss@8.4.35)
- '@csstools/postcss-stepped-value-functions': 3.0.10(postcss@8.4.35)
- '@csstools/postcss-text-decoration-shorthand': 3.0.7(postcss@8.4.35)
- '@csstools/postcss-trigonometric-functions': 3.0.10(postcss@8.4.35)
- '@csstools/postcss-unset-value': 3.0.1(postcss@8.4.35)
- autoprefixer: 10.4.27(postcss@8.4.35)
+ postcss-preset-env@9.6.0(postcss@8.5.8):
+ dependencies:
+ '@csstools/postcss-cascade-layers': 4.0.6(postcss@8.5.8)
+ '@csstools/postcss-color-function': 3.0.19(postcss@8.5.8)
+ '@csstools/postcss-color-mix-function': 2.0.19(postcss@8.5.8)
+ '@csstools/postcss-content-alt-text': 1.0.0(postcss@8.5.8)
+ '@csstools/postcss-exponential-functions': 1.0.9(postcss@8.5.8)
+ '@csstools/postcss-font-format-keywords': 3.0.2(postcss@8.5.8)
+ '@csstools/postcss-gamut-mapping': 1.0.11(postcss@8.5.8)
+ '@csstools/postcss-gradients-interpolation-method': 4.0.20(postcss@8.5.8)
+ '@csstools/postcss-hwb-function': 3.0.18(postcss@8.5.8)
+ '@csstools/postcss-ic-unit': 3.0.7(postcss@8.5.8)
+ '@csstools/postcss-initial': 1.0.1(postcss@8.5.8)
+ '@csstools/postcss-is-pseudo-class': 4.0.8(postcss@8.5.8)
+ '@csstools/postcss-light-dark-function': 1.0.8(postcss@8.5.8)
+ '@csstools/postcss-logical-float-and-clear': 2.0.1(postcss@8.5.8)
+ '@csstools/postcss-logical-overflow': 1.0.1(postcss@8.5.8)
+ '@csstools/postcss-logical-overscroll-behavior': 1.0.1(postcss@8.5.8)
+ '@csstools/postcss-logical-resize': 2.0.1(postcss@8.5.8)
+ '@csstools/postcss-logical-viewport-units': 2.0.11(postcss@8.5.8)
+ '@csstools/postcss-media-minmax': 1.1.8(postcss@8.5.8)
+ '@csstools/postcss-media-queries-aspect-ratio-number-values': 2.0.11(postcss@8.5.8)
+ '@csstools/postcss-nested-calc': 3.0.2(postcss@8.5.8)
+ '@csstools/postcss-normalize-display-values': 3.0.2(postcss@8.5.8)
+ '@csstools/postcss-oklab-function': 3.0.19(postcss@8.5.8)
+ '@csstools/postcss-progressive-custom-properties': 3.3.0(postcss@8.5.8)
+ '@csstools/postcss-relative-color-syntax': 2.0.19(postcss@8.5.8)
+ '@csstools/postcss-scope-pseudo-class': 3.0.1(postcss@8.5.8)
+ '@csstools/postcss-stepped-value-functions': 3.0.10(postcss@8.5.8)
+ '@csstools/postcss-text-decoration-shorthand': 3.0.7(postcss@8.5.8)
+ '@csstools/postcss-trigonometric-functions': 3.0.10(postcss@8.5.8)
+ '@csstools/postcss-unset-value': 3.0.1(postcss@8.5.8)
+ autoprefixer: 10.4.27(postcss@8.5.8)
browserslist: 4.28.1
- css-blank-pseudo: 6.0.2(postcss@8.4.35)
- css-has-pseudo: 6.0.5(postcss@8.4.35)
- css-prefers-color-scheme: 9.0.1(postcss@8.4.35)
+ css-blank-pseudo: 6.0.2(postcss@8.5.8)
+ css-has-pseudo: 6.0.5(postcss@8.5.8)
+ css-prefers-color-scheme: 9.0.1(postcss@8.5.8)
cssdb: 8.8.0
- postcss: 8.4.35
- postcss-attribute-case-insensitive: 6.0.3(postcss@8.4.35)
- postcss-clamp: 4.1.0(postcss@8.4.35)
- postcss-color-functional-notation: 6.0.14(postcss@8.4.35)
- postcss-color-hex-alpha: 9.0.4(postcss@8.4.35)
- postcss-color-rebeccapurple: 9.0.3(postcss@8.4.35)
- postcss-custom-media: 10.0.8(postcss@8.4.35)
- postcss-custom-properties: 13.3.12(postcss@8.4.35)
- postcss-custom-selectors: 7.1.12(postcss@8.4.35)
- postcss-dir-pseudo-class: 8.0.1(postcss@8.4.35)
- postcss-double-position-gradients: 5.0.7(postcss@8.4.35)
- postcss-focus-visible: 9.0.1(postcss@8.4.35)
- postcss-focus-within: 8.0.1(postcss@8.4.35)
- postcss-font-variant: 5.0.0(postcss@8.4.35)
- postcss-gap-properties: 5.0.1(postcss@8.4.35)
- postcss-image-set-function: 6.0.3(postcss@8.4.35)
- postcss-lab-function: 6.0.19(postcss@8.4.35)
- postcss-logical: 7.0.1(postcss@8.4.35)
- postcss-nesting: 12.1.5(postcss@8.4.35)
- postcss-opacity-percentage: 2.0.0(postcss@8.4.35)
- postcss-overflow-shorthand: 5.0.1(postcss@8.4.35)
- postcss-page-break: 3.0.4(postcss@8.4.35)
- postcss-place: 9.0.1(postcss@8.4.35)
- postcss-pseudo-class-any-link: 9.0.2(postcss@8.4.35)
- postcss-replace-overflow-wrap: 4.0.0(postcss@8.4.35)
- postcss-selector-not: 7.0.2(postcss@8.4.35)
-
- postcss-pseudo-class-any-link@9.0.2(postcss@8.4.35):
+ postcss: 8.5.8
+ postcss-attribute-case-insensitive: 6.0.3(postcss@8.5.8)
+ postcss-clamp: 4.1.0(postcss@8.5.8)
+ postcss-color-functional-notation: 6.0.14(postcss@8.5.8)
+ postcss-color-hex-alpha: 9.0.4(postcss@8.5.8)
+ postcss-color-rebeccapurple: 9.0.3(postcss@8.5.8)
+ postcss-custom-media: 10.0.8(postcss@8.5.8)
+ postcss-custom-properties: 13.3.12(postcss@8.5.8)
+ postcss-custom-selectors: 7.1.12(postcss@8.5.8)
+ postcss-dir-pseudo-class: 8.0.1(postcss@8.5.8)
+ postcss-double-position-gradients: 5.0.7(postcss@8.5.8)
+ postcss-focus-visible: 9.0.1(postcss@8.5.8)
+ postcss-focus-within: 8.0.1(postcss@8.5.8)
+ postcss-font-variant: 5.0.0(postcss@8.5.8)
+ postcss-gap-properties: 5.0.1(postcss@8.5.8)
+ postcss-image-set-function: 6.0.3(postcss@8.5.8)
+ postcss-lab-function: 6.0.19(postcss@8.5.8)
+ postcss-logical: 7.0.1(postcss@8.5.8)
+ postcss-nesting: 12.1.5(postcss@8.5.8)
+ postcss-opacity-percentage: 2.0.0(postcss@8.5.8)
+ postcss-overflow-shorthand: 5.0.1(postcss@8.5.8)
+ postcss-page-break: 3.0.4(postcss@8.5.8)
+ postcss-place: 9.0.1(postcss@8.5.8)
+ postcss-pseudo-class-any-link: 9.0.2(postcss@8.5.8)
+ postcss-replace-overflow-wrap: 4.0.0(postcss@8.5.8)
+ postcss-selector-not: 7.0.2(postcss@8.5.8)
+
+ postcss-pseudo-class-any-link@9.0.2(postcss@8.5.8):
dependencies:
- postcss: 8.4.35
+ postcss: 8.5.8
postcss-selector-parser: 6.0.15
- postcss-replace-overflow-wrap@4.0.0(postcss@8.4.35):
+ postcss-replace-overflow-wrap@4.0.0(postcss@8.5.8):
dependencies:
- postcss: 8.4.35
+ postcss: 8.5.8
postcss-resolve-nested-selector@0.1.1: {}
@@ -20396,9 +20764,9 @@ snapshots:
dependencies:
postcss: 8.4.35
- postcss-selector-not@7.0.2(postcss@8.4.35):
+ postcss-selector-not@7.0.2(postcss@8.5.8):
dependencies:
- postcss: 8.4.35
+ postcss: 8.5.8
postcss-selector-parser: 6.0.15
postcss-selector-parser@6.0.15:
@@ -20411,13 +20779,13 @@ snapshots:
cssesc: 3.0.0
util-deprecate: 1.0.2
- postcss-simple-vars@6.0.3(postcss@8.4.35):
+ postcss-simple-vars@6.0.3(postcss@8.5.8):
dependencies:
- postcss: 8.4.35
+ postcss: 8.5.8
- postcss-simple-vars@7.0.1(postcss@8.4.35):
+ postcss-simple-vars@7.0.1(postcss@8.5.8):
dependencies:
- postcss: 8.4.35
+ postcss: 8.5.8
postcss-value-parser@4.2.0: {}
@@ -20832,9 +21200,9 @@ snapshots:
remove-types@1.0.0:
dependencies:
- '@babel/core': 7.23.2
- '@babel/plugin-syntax-decorators': 7.23.3(@babel/core@7.23.2)
- '@babel/plugin-transform-typescript': 7.23.6(@babel/core@7.23.2)
+ '@babel/core': 7.29.0
+ '@babel/plugin-syntax-decorators': 7.29.7(@babel/core@7.29.0)
+ '@babel/plugin-transform-typescript': 7.23.6(@babel/core@7.29.0)
prettier: 2.8.8
transitivePeerDependencies:
- supports-color
@@ -21612,9 +21980,9 @@ snapshots:
tinyglobby: 0.2.15
ts-interface-checker: 0.1.13
- sugarss@4.0.1(postcss@8.4.35):
+ sugarss@4.0.1(postcss@8.5.8):
dependencies:
- postcss: 8.4.35
+ postcss: 8.5.8
sum-up@1.0.3:
dependencies:
@@ -21641,6 +22009,27 @@ snapshots:
supports-preserve-symlinks-flag@1.0.0: {}
+ svelte@5.56.1:
+ dependencies:
+ '@jridgewell/remapping': 2.3.5
+ '@jridgewell/sourcemap-codec': 1.5.5
+ '@sveltejs/acorn-typescript': 1.0.10(acorn@8.16.0)
+ '@types/estree': 1.0.9
+ '@types/trusted-types': 2.0.7
+ acorn: 8.16.0
+ aria-query: 5.3.1
+ axobject-query: 4.1.0
+ clsx: 2.1.1
+ devalue: 5.8.1
+ esm-env: 1.2.2
+ esrap: 2.2.11
+ is-reference: 3.0.3
+ locate-character: 3.0.0
+ magic-string: 0.30.21
+ zimmerframe: 1.1.4
+ transitivePeerDependencies:
+ - '@typescript-eslint/types'
+
svg-tags@1.0.0: {}
symlink-or-copy@1.3.1: {}
@@ -21738,7 +22127,7 @@ snapshots:
terser-webpack-plugin@5.3.10(webpack@5.89.0):
dependencies:
- '@jridgewell/trace-mapping': 0.3.22
+ '@jridgewell/trace-mapping': 0.3.31
jest-worker: 27.5.1
schema-utils: 3.3.0
serialize-javascript: 6.0.2
@@ -21956,8 +22345,8 @@ snapshots:
tracked-built-ins@3.4.0(@babel/core@7.23.2):
dependencies:
'@embroider/addon-shim': 1.10.2
- decorator-transforms: 2.3.1(@babel/core@7.23.2)
- ember-tracked-storage-polyfill: 1.0.0
+ decorator-transforms: 2.3.2(@babel/core@7.23.2)
+ ember-tracked-storage-polyfill: 1.0.1
transitivePeerDependencies:
- '@babel/core'
- supports-color
@@ -22138,6 +22527,12 @@ snapshots:
escalade: 3.2.0
picocolors: 1.1.1
+ update-browserslist-db@1.2.3(browserslist@4.28.2):
+ dependencies:
+ browserslist: 4.28.2
+ escalade: 3.2.0
+ picocolors: 1.1.1
+
uri-js@4.4.1:
dependencies:
punycode: 2.3.1
@@ -22475,3 +22870,5 @@ snapshots:
yocto-queue@0.1.0: {}
yocto-queue@1.0.0: {}
+
+ zimmerframe@1.1.4: {}
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
new file mode 100644
index 0000000..bf39b1a
--- /dev/null
+++ b/pnpm-workspace.yaml
@@ -0,0 +1,8 @@
+allowBuilds:
+ '@fortawesome/fontawesome-common-types': false
+ '@fortawesome/fontawesome-svg-core': false
+ '@fortawesome/free-brands-svg-icons': false
+ '@fortawesome/free-solid-svg-icons': false
+ core-js: false
+ fsevents: false
+minimumReleaseAge: 0
\ No newline at end of file
diff --git a/server/migrations/2024_01_01_000023_backfill_revenue_recognition_journal_entries.php b/server/migrations/2024_01_01_000023_backfill_revenue_recognition_journal_entries.php
index b837ee6..36c4327 100644
--- a/server/migrations/2024_01_01_000023_backfill_revenue_recognition_journal_entries.php
+++ b/server/migrations/2024_01_01_000023_backfill_revenue_recognition_journal_entries.php
@@ -4,8 +4,7 @@
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
-return new class extends Migration
-{
+return new class extends Migration {
/**
* Backfill revenue-recognition journal entries for invoices that were
* created before InvoiceController::onAfterCreate started calling
@@ -43,14 +42,20 @@ public function up(): void
$query->select(DB::raw(1))
->from('ledger_journals')
->whereNull('ledger_journals.deleted_at')
- ->where('ledger_journals.type', 'revenue_recognition')
- ->whereRaw("JSON_UNQUOTE(JSON_EXTRACT(ledger_journals.meta, '$.invoice_uuid')) = ledger_invoices.uuid");
+ ->whereColumn('ledger_journals.company_uuid', 'ledger_invoices.company_uuid')
+ ->whereColumn('ledger_journals.amount', 'ledger_invoices.total_amount')
+ ->where(function ($query) {
+ $query->where(function ($query) {
+ $query->where('ledger_journals.type', 'revenue_recognition')
+ ->whereRaw("JSON_UNQUOTE(JSON_EXTRACT(ledger_journals.meta, '$.invoice_uuid')) = ledger_invoices.uuid");
+ })->orWhereRaw("ledger_journals.description = CONCAT('Revenue recognition for invoice ', ledger_invoices.number)");
+ });
})
->get(['uuid', 'public_id', 'company_uuid', 'total_amount', 'currency', 'number', 'created_at']);
foreach ($invoices as $invoice) {
// Resolve or create the AR and Revenue accounts for this company
- $arAccount = $this->resolveAccount($invoice->company_uuid, 'AR-DEFAULT', 'asset', 'Accounts Receivable');
+ $arAccount = $this->resolveAccount($invoice->company_uuid, 'AR-DEFAULT', 'asset', 'Accounts Receivable');
$revAccount = $this->resolveAccount($invoice->company_uuid, 'REV-DEFAULT', 'revenue', 'Sales Revenue');
if (!$arAccount || !$revAccount) {
@@ -129,6 +134,7 @@ private function resolveAccount(string $companyUuid, string $code, string $type,
->update(['status' => 'active']);
$account->status = 'active';
}
+
return $account;
}
diff --git a/server/resources/views/mail/invoice-sent.blade.php b/server/resources/views/mail/invoice-sent.blade.php
new file mode 100644
index 0000000..687bd9a
--- /dev/null
+++ b/server/resources/views/mail/invoice-sent.blade.php
@@ -0,0 +1,156 @@
+
+
+
+
+
+ Invoice {{ $invoiceNumber }}
+
+
+
+
+
+
+
+
+ @if ($companyLogoUrl)
+
+ @else
+ {{ $companyName }}
+ @endif
+ |
+
+
+
+
+
+ |
+ Invoice
+ {{ $invoiceNumber }}
+
+ @if ($orderLabel)
+ {{ $companyName }} sent you an invoice for order {{ $orderLabel }}.
+ @else
+ {{ $companyName }} sent you an invoice.
+ @endif
+
+ |
+
+
+
+
+
+ |
+ Bill To
+ {{ $customerName ?: 'Customer' }}
+ @if ($customerEmail)
+ {{ $customerEmail }}
+ @endif
+ |
+
+
+ @if ($invoiceDate)
+
+ | Invoice date |
+ {{ $invoiceDate }} |
+
+ @endif
+ @if ($dueDate)
+
+ | Due date |
+ {{ $dueDate }} |
+
+ @endif
+ @if ($orderLabel)
+
+ | Order |
+ {{ $orderLabel }} |
+
+ @endif
+
+ |
+
+
+ |
+
+
+
+
+
+
+ | Description |
+ Qty |
+ Unit Price |
+ Amount |
+
+
+
+ @forelse ($items as $item)
+
+ | {{ $item['description'] }} |
+ {{ $item['quantity'] }} |
+ {{ $item['unitPrice'] }} |
+ {{ $item['amount'] }} |
+
+ @empty
+
+ | No line items were recorded. |
+
+ @endforelse
+
+
+ |
+
+
+
+
+
+ |
+
+
+
+ | Subtotal |
+ {{ $subtotal }} |
+
+
+ | Tax |
+ {{ $tax }} |
+
+
+ | Total |
+ {{ $total }} |
+
+ @if ($hasAmountPaid)
+
+ | Amount paid |
+ {{ $amountPaid }} |
+
+ @endif
+
+ | Balance due |
+ {{ $balance }} |
+
+
+ |
+
+
+ |
+
+
+ |
+ View Invoice
+ |
+
+
+ |
+
+
+ |
+ This invoice was sent by {{ $companyName }}.
+ |
+
+
+ |
+
+
+
+
diff --git a/server/src/Http/Controllers/Internal/v1/InvoiceController.php b/server/src/Http/Controllers/Internal/v1/InvoiceController.php
index 9fe0306..ca8816f 100644
--- a/server/src/Http/Controllers/Internal/v1/InvoiceController.php
+++ b/server/src/Http/Controllers/Internal/v1/InvoiceController.php
@@ -4,8 +4,10 @@
use Fleetbase\Ledger\Http\Controllers\LedgerResourceController;
use Fleetbase\Ledger\Http\Resources\v1\Invoice as InvoiceResource;
+use Fleetbase\Ledger\Http\Resources\v1\Transaction as TransactionResource;
use Fleetbase\Ledger\Models\Invoice;
use Fleetbase\Ledger\Models\InvoiceItem;
+use Fleetbase\Ledger\Models\Transaction;
use Fleetbase\Ledger\Services\InvoiceService;
use Fleetbase\Services\TemplateRenderService;
use Illuminate\Http\JsonResponse;
@@ -104,6 +106,42 @@ public function recordPayment(string $id, Request $request): InvoiceResource
return new InvoiceResource($invoice->load(['customer', 'items', 'template']));
}
+ /**
+ * List transactions related to an invoice.
+ */
+ public function transactions(string $id, Request $request)
+ {
+ $invoice = Invoice::where('company_uuid', session('company'))
+ ->where(fn ($q) => $q->where('uuid', $id)->orWhere('public_id', $id))
+ ->firstOrFail();
+
+ $transactions = Transaction::where('company_uuid', session('company'))
+ ->where(function ($query) use ($invoice) {
+ $query->where('subject_uuid', $invoice->uuid)
+ ->orWhere('context_uuid', $invoice->uuid);
+
+ if ($invoice->transaction_uuid) {
+ $query->orWhere('uuid', $invoice->transaction_uuid);
+ }
+ })
+ ->with([
+ 'items',
+ 'journal.debitAccount',
+ 'journal.creditAccount',
+ 'subject',
+ 'payer',
+ 'payee',
+ 'initiator',
+ 'context',
+ ])
+ ->orderBy('created_at', $request->input('sort') === 'created_at' ? 'asc' : 'desc')
+ ->paginate($request->integer('limit', 50));
+
+ TransactionResource::wrap('transactions');
+
+ return TransactionResource::collection($transactions);
+ }
+
/**
* Mark an invoice as sent (without dispatching a notification).
*/
@@ -128,14 +166,12 @@ public function send(string $id, Request $request): InvoiceResource
->with('customer')
->firstOrFail();
- if (!$invoice->customer || !$invoice->customer->email) {
- abort(422, 'Invoice customer does not have a valid email address.');
+ try {
+ $invoice = app(InvoiceService::class)->send($invoice);
+ } catch (\InvalidArgumentException $e) {
+ abort(422, $e->getMessage());
}
- $invoice->markAsSent();
-
- // TODO (M5): Dispatch InvoiceSentNotification to $invoice->customer->email
-
return new InvoiceResource($invoice->load(['customer', 'items', 'template']));
}
diff --git a/server/src/Http/Controllers/Internal/v1/ReportController.php b/server/src/Http/Controllers/Internal/v1/ReportController.php
index f3e8536..d1b2a3a 100644
--- a/server/src/Http/Controllers/Internal/v1/ReportController.php
+++ b/server/src/Http/Controllers/Internal/v1/ReportController.php
@@ -82,6 +82,90 @@ public function dashboard(Request $request): JsonResponse
]);
}
+ public function dashboardSummary(Request $request): JsonResponse
+ {
+ $request->validate([
+ 'start_date' => 'nullable|date',
+ 'end_date' => 'nullable|date',
+ ]);
+
+ return response()->json([
+ 'status' => 'ok',
+ 'data' => $this->ledgerService->getDashboardSummary(session('company'), $request->input('start_date'), $request->input('end_date')),
+ ]);
+ }
+
+ public function dashboardRevenueTrend(Request $request): JsonResponse
+ {
+ $request->validate([
+ 'start_date' => 'nullable|date',
+ 'end_date' => 'nullable|date',
+ ]);
+
+ return response()->json([
+ 'status' => 'ok',
+ 'data' => $this->ledgerService->getDashboardRevenueTrend(session('company'), $request->input('start_date'), $request->input('end_date')),
+ ]);
+ }
+
+ public function dashboardCashFlowSummary(Request $request): JsonResponse
+ {
+ $request->validate([
+ 'start_date' => 'nullable|date',
+ 'end_date' => 'nullable|date',
+ ]);
+
+ return response()->json([
+ 'status' => 'ok',
+ 'data' => $this->ledgerService->getDashboardCashFlowSummary(session('company'), $request->input('start_date'), $request->input('end_date')),
+ ]);
+ }
+
+ public function dashboardInvoiceStatus(): JsonResponse
+ {
+ return response()->json([
+ 'status' => 'ok',
+ 'data' => $this->ledgerService->getDashboardInvoiceStatus(session('company')),
+ ]);
+ }
+
+ public function dashboardArAgingSummary(Request $request): JsonResponse
+ {
+ $request->validate([
+ 'as_of_date' => 'nullable|date',
+ ]);
+
+ return response()->json([
+ 'status' => 'ok',
+ 'data' => $this->ledgerService->getDashboardArAgingSummary(session('company'), $request->input('as_of_date')),
+ ]);
+ }
+
+ public function dashboardWalletBalances(Request $request): JsonResponse
+ {
+ $request->validate([
+ 'date_from' => 'nullable|date',
+ 'date_to' => 'nullable|date',
+ ]);
+
+ return response()->json([
+ 'status' => 'ok',
+ 'data' => $this->ledgerService->getDashboardWalletBalances(session('company'), $request->input('date_from'), $request->input('date_to')),
+ ]);
+ }
+
+ public function dashboardActivity(Request $request): JsonResponse
+ {
+ $request->validate([
+ 'limit' => 'nullable|integer|min:1|max:25',
+ ]);
+
+ return response()->json([
+ 'status' => 'ok',
+ 'data' => $this->ledgerService->getDashboardActivity(session('company'), (int) $request->input('limit', 10)),
+ ]);
+ }
+
// =========================================================================
// Trial Balance
// =========================================================================
diff --git a/server/src/Http/Controllers/Public/PublicInvoiceController.php b/server/src/Http/Controllers/Public/PublicInvoiceController.php
index aa35793..2cb3f33 100644
--- a/server/src/Http/Controllers/Public/PublicInvoiceController.php
+++ b/server/src/Http/Controllers/Public/PublicInvoiceController.php
@@ -132,13 +132,24 @@ public function pay(Request $request, string $publicId): JsonResponse
], 422);
}
- // Resolve the gateway driver
- try {
- $driver = $this->gatewayManager->gateway($request->input('gateway_id'));
- } catch (\Exception $e) {
+ $gateway = Gateway::query()
+ ->where('company_uuid', $invoice->company_uuid)
+ ->where('status', 'active')
+ ->where(function ($query) use ($request) {
+ $gatewayId = $request->input('gateway_id');
+
+ $query->where('uuid', $gatewayId)
+ ->orWhere('public_id', $gatewayId);
+ })
+ ->first();
+
+ if (!$gateway) {
return response()->json(['error' => 'Payment gateway not found or unavailable.'], 422);
}
+ $driver = $this->gatewayManager->driver($gateway->driver)
+ ->initialize($gateway->decryptedConfig(), $gateway->is_sandbox);
+
// ── Stripe: hosted Checkout Session ───────────────────────────────────
if ($driver instanceof StripeDriver) {
return $this->initiateStripeCheckout($driver, $invoice, $request);
diff --git a/server/src/Http/Resources/v1/Invoice.php b/server/src/Http/Resources/v1/Invoice.php
index 20f14f8..9f4570c 100644
--- a/server/src/Http/Resources/v1/Invoice.php
+++ b/server/src/Http/Resources/v1/Invoice.php
@@ -35,12 +35,14 @@ public function toArray($request)
return $this->setCustomerType($this->transformMorphResource($this->customer));
}),
// ── Related records ────────────────────────────────────────────
- 'order_uuid' => $this->when($isInternal, $this->order_uuid),
- 'order' => $this->whenLoaded('order'),
- 'transaction_uuid' => $this->when($isInternal, $this->transaction_uuid),
- 'transaction' => $this->whenLoaded('transaction'),
- 'template_uuid' => $this->when($isInternal, $this->template_uuid),
- 'template' => $this->whenLoaded('template'),
+ 'order_uuid' => $this->when($this->order_uuid, $this->order_uuid),
+ 'order_public_id' => $this->when($this->order_uuid, fn () => data_get($this->order, 'public_id')),
+ 'order_tracking_number' => $this->when($this->order_uuid, fn () => data_get($this->order, 'trackingNumber.tracking_number')),
+ 'order' => $this->whenLoaded('order'),
+ 'transaction_uuid' => $this->when($isInternal, $this->transaction_uuid),
+ 'transaction' => $this->whenLoaded('transaction'),
+ 'template_uuid' => $this->when($isInternal, $this->template_uuid),
+ 'template' => $this->whenLoaded('template'),
// ── Invoice details ────────────────────────────────────────────
'number' => $this->number,
'status' => $this->status,
diff --git a/server/src/Listeners/HandleSuccessfulPayment.php b/server/src/Listeners/HandleSuccessfulPayment.php
index ca57858..b0c8178 100644
--- a/server/src/Listeners/HandleSuccessfulPayment.php
+++ b/server/src/Listeners/HandleSuccessfulPayment.php
@@ -135,7 +135,7 @@ public function handle(PaymentSucceeded $event): void
[
'company_uuid' => $companyUuid,
'currency' => $currency,
- 'type' => 'gateway_payment',
+ 'journal_type' => 'gateway_payment',
'gateway_transaction_uuid' => $gatewayTransaction->uuid,
'meta' => [
'gateway_driver' => $gateway->driver,
diff --git a/server/src/Models/Invoice.php b/server/src/Models/Invoice.php
index f93c2a1..b6ac32a 100644
--- a/server/src/Models/Invoice.php
+++ b/server/src/Models/Invoice.php
@@ -137,7 +137,7 @@ class Invoice extends Model
*
* @var array
*/
- protected $with = ['customer', 'items', 'template'];
+ protected $with = ['customer', 'items', 'template', 'order.trackingNumber'];
/**
* The attributes excluded from the model's JSON form.
diff --git a/server/src/Notifications/InvoiceSent.php b/server/src/Notifications/InvoiceSent.php
new file mode 100644
index 0000000..714fe3e
--- /dev/null
+++ b/server/src/Notifications/InvoiceSent.php
@@ -0,0 +1,167 @@
+invoice->loadMissing(['customer', 'items', 'order.trackingNumber']);
+
+ $number = $this->invoiceNumber();
+ $companyName = $this->companyName();
+ $currency = strtoupper((string) ($this->invoice->currency ?: 'USD'));
+
+ return (new MailMessage())
+ ->from(config('mail.from.address'), $companyName)
+ ->subject("Invoice {$number} from {$companyName}")
+ ->view('ledger::mail.invoice-sent', [
+ 'companyName' => $companyName,
+ 'companyLogoUrl' => $this->companyLogoUrl(),
+ 'customerName' => $this->customerName(),
+ 'customerEmail' => $this->customerEmail(),
+ 'invoiceNumber' => $number,
+ 'invoiceDate' => $this->formatDate($this->invoice->date),
+ 'dueDate' => $this->formatDate($this->invoice->due_date),
+ 'orderLabel' => $this->orderLabel(),
+ 'items' => $this->lineItems(),
+ 'subtotal' => $this->formatMoney($this->invoice->subtotal, $currency),
+ 'tax' => $this->formatMoney($this->invoice->tax, $currency),
+ 'total' => $this->formatMoney($this->invoice->total_amount, $currency),
+ 'amountPaid' => $this->formatMoney($this->invoice->amount_paid, $currency),
+ 'balance' => $this->formatMoney($this->invoice->balance, $currency),
+ 'hasAmountPaid' => (int) $this->invoice->amount_paid > 0,
+ 'invoiceUrl' => $this->invoiceUrl(),
+ ]);
+ }
+
+ protected function invoiceNumber(): string
+ {
+ return $this->invoice->number ?: $this->invoice->public_id;
+ }
+
+ protected function companyName(): string
+ {
+ $company = $this->company();
+
+ return $company?->name ?: 'Your service provider';
+ }
+
+ protected function companyLogoUrl(): ?string
+ {
+ return $this->company()?->logo_url;
+ }
+
+ protected function orderLabel(): ?string
+ {
+ $order = $this->invoice->order;
+ if (!$order) {
+ return null;
+ }
+
+ return $order->tracking_number
+ ?? $order->trackingNumber?->tracking_number
+ ?? $order->public_id
+ ?? $order->uuid;
+ }
+
+ protected function lineItems(): array
+ {
+ if (!$this->invoice->items || $this->invoice->items->isEmpty()) {
+ return [];
+ }
+
+ return $this->invoice->items
+ ->map(function ($item) {
+ $currency = strtoupper((string) ($this->invoice->currency ?: 'USD'));
+ $quantity = (float) ($item->quantity ?: 1);
+ $unitPrice = $item->unit_price ?? ($quantity > 0 ? ((int) $item->amount / $quantity) : $item->amount);
+
+ return [
+ 'description' => Str::limit((string) ($item->description ?: 'Invoice item'), 140),
+ 'quantity' => $this->formatQuantity($quantity),
+ 'unitPrice' => $this->formatMoney($unitPrice, $currency),
+ 'amount' => $this->formatMoney($item->amount, $currency),
+ ];
+ })
+ ->values()
+ ->all();
+ }
+
+ protected function formatMoney($amount, string $currency): string
+ {
+ return $currency . ' ' . number_format(((int) $amount) / 100, 2);
+ }
+
+ protected function invoiceUrl(): string
+ {
+ return Utils::consoleUrl('~/invoice', [
+ 'id' => $this->invoice->public_id,
+ ]);
+ }
+
+ protected function customerName(): ?string
+ {
+ $customer = $this->invoice->customer;
+
+ return $customer?->name
+ ?? $customer?->display_name
+ ?? $customer?->email
+ ?? null;
+ }
+
+ protected function customerEmail(): ?string
+ {
+ $customer = $this->invoice->customer;
+
+ return $customer?->email
+ ?? $customer?->contact_email
+ ?? null;
+ }
+
+ protected function company(): ?Company
+ {
+ if ($this->company === null) {
+ $this->company = Company::where('uuid', $this->invoice->company_uuid)->first();
+ }
+
+ return $this->company;
+ }
+
+ protected function formatDate($date): ?string
+ {
+ if (!$date) {
+ return null;
+ }
+
+ return Carbon::parse($date)->format('M j, Y');
+ }
+
+ protected function formatQuantity(float $quantity): string
+ {
+ return fmod($quantity, 1.0) === 0.0 ? (string) (int) $quantity : rtrim(rtrim(number_format($quantity, 2), '0'), '.');
+ }
+}
diff --git a/server/src/Observers/OrderAccountingObserver.php b/server/src/Observers/OrderAccountingObserver.php
new file mode 100644
index 0000000..f9536fa
--- /dev/null
+++ b/server/src/Observers/OrderAccountingObserver.php
@@ -0,0 +1,440 @@
+type !== 'storefront') {
+ return;
+ }
+
+ try {
+ DB::transaction(function () use ($order) {
+ $companyUuid = $order->company_uuid;
+ $currency = $order->getMeta('currency', 'USD');
+ $total = (int) $order->getMeta('total', 0);
+
+ if ($total <= 0) {
+ Log::channel('ledger')->info('[Ledger] OrderAccountingObserver: skipping Storefront order with zero total.', [
+ 'order_uuid' => $order->uuid,
+ ]);
+
+ return;
+ }
+
+ $alreadyRecorded = Journal::where('type', 'storefront_sale')
+ ->where('meta->order_uuid', $order->uuid)
+ ->exists();
+
+ if ($alreadyRecorded) {
+ return;
+ }
+
+ $cashAccount = Account::updateOrCreate(
+ ['company_uuid' => $companyUuid, 'code' => 'CASH-DEFAULT'],
+ [
+ 'name' => 'Cash',
+ 'type' => Account::TYPE_ASSET,
+ 'description' => 'Default cash account',
+ 'is_system_account' => true,
+ 'status' => 'active',
+ ]
+ );
+
+ $revenueAccount = Account::updateOrCreate(
+ ['company_uuid' => $companyUuid, 'code' => 'REV-DEFAULT'],
+ [
+ 'name' => 'Sales Revenue',
+ 'type' => Account::TYPE_REVENUE,
+ 'description' => 'Default sales revenue account',
+ 'is_system_account' => true,
+ 'status' => 'active',
+ ]
+ );
+
+ $meta = [
+ 'order_uuid' => $order->uuid,
+ 'order_id' => $order->public_id,
+ 'subject_uuid' => $order->uuid,
+ 'subject_type' => get_class($order),
+ ];
+
+ foreach (['seed', 'seed_id'] as $seedMetaKey) {
+ if ($order->hasMeta($seedMetaKey)) {
+ $meta[$seedMetaKey] = $order->getMeta($seedMetaKey);
+ }
+ }
+
+ $this->ledgerService->createJournalEntry(
+ $cashAccount,
+ $revenueAccount,
+ $total,
+ "Storefront sale - Order {$order->public_id}",
+ [
+ 'company_uuid' => $companyUuid,
+ 'currency' => $currency,
+ 'journal_type' => 'storefront_sale',
+ 'entry_date' => now(),
+ 'meta' => $meta,
+ ]
+ );
+
+ Log::channel('ledger')->info('[Ledger] OrderAccountingObserver: Storefront sale journal entry created.', [
+ 'order_uuid' => $order->uuid,
+ 'total' => $total,
+ 'currency' => $currency,
+ ]);
+ });
+ } catch (\Throwable $e) {
+ // Never let a Ledger failure abort the order creation flow.
+ Log::channel('ledger')->error('[Ledger] OrderAccountingObserver: failed to create Storefront sale journal.', [
+ 'error' => $e->getMessage(),
+ 'order_uuid' => $order->uuid ?? null,
+ ]);
+ }
+ }
+
+ /**
+ * Handle the Order "updated" event.
+ */
+ public function updated($order): void
+ {
+ if (!$order->wasChanged('status')) {
+ return;
+ }
+
+ $previousStatus = $this->normalizeStatus((string) $order->getOriginal('status'));
+ $currentStatus = $this->normalizeStatus((string) $order->status);
+
+ if (!$this->isCanceledStatus($previousStatus) && $this->isCanceledStatus($currentStatus)) {
+ $this->handleOrderCanceled($order, $previousStatus, $currentStatus);
+
+ return;
+ }
+
+ if ($this->isCanceledStatus($previousStatus) && !$this->isCanceledStatus($currentStatus)) {
+ $this->handleOrderRestored($order, $previousStatus, $currentStatus);
+ }
+ }
+
+ private function handleOrderCanceled($order, string $previousStatus, string $currentStatus): void
+ {
+ try {
+ DB::transaction(function () use ($order, $previousStatus, $currentStatus) {
+ $reversedStorefrontSales = $this->reverseStorefrontSaleJournals($order, $previousStatus, $currentStatus);
+ $reversedInvoiceRevenue = $this->reverseOrderInvoiceRevenue($order, $previousStatus, $currentStatus);
+
+ if ($reversedStorefrontSales === 0 && $reversedInvoiceRevenue === 0) {
+ Log::channel('ledger')->info('[Ledger] OrderAccountingObserver: order canceled with no linked Ledger revenue to reverse.', [
+ 'order_uuid' => $order->uuid,
+ ]);
+ }
+ });
+ } catch (\Throwable $e) {
+ // Never let a Ledger failure abort the order cancellation flow.
+ Log::channel('ledger')->error('[Ledger] OrderAccountingObserver: failed to reverse order revenue.', [
+ 'error' => $e->getMessage(),
+ 'order_uuid' => $order->uuid ?? null,
+ ]);
+ }
+ }
+
+ private function handleOrderRestored($order, string $previousStatus, string $currentStatus): void
+ {
+ try {
+ DB::transaction(function () use ($order, $previousStatus, $currentStatus) {
+ $reinstatedStorefrontSales = $this->reinstateReversedJournals(
+ $order,
+ 'storefront_sale_reversal',
+ 'storefront_sale_reinstatement',
+ "Storefront sale reinstatement - Order {$order->public_id}",
+ $previousStatus,
+ $currentStatus
+ );
+
+ $reinstatedInvoiceRevenue = $this->reinstateReversedJournals(
+ $order,
+ 'revenue_recognition_reversal',
+ 'revenue_recognition_reinstatement',
+ "Invoice revenue reinstatement - Order {$order->public_id}",
+ $previousStatus,
+ $currentStatus
+ );
+
+ $this->restoreOrderInvoices($order);
+
+ if ($reinstatedStorefrontSales === 0 && $reinstatedInvoiceRevenue === 0) {
+ Log::channel('ledger')->info('[Ledger] OrderAccountingObserver: order restored with no reversed Ledger revenue to reinstate.', [
+ 'order_uuid' => $order->uuid,
+ ]);
+ }
+ });
+ } catch (\Throwable $e) {
+ // Never let a Ledger failure abort the order restoration flow.
+ Log::channel('ledger')->error('[Ledger] OrderAccountingObserver: failed to reinstate order revenue.', [
+ 'error' => $e->getMessage(),
+ 'order_uuid' => $order->uuid ?? null,
+ ]);
+ }
+ }
+
+ private function reverseStorefrontSaleJournals($order, string $previousStatus, string $currentStatus): int
+ {
+ $journals = Journal::with(['debitAccount', 'creditAccount'])
+ ->where('type', 'storefront_sale')
+ ->where('status', 'posted')
+ ->where('meta->order_uuid', $order->uuid)
+ ->get();
+
+ return $this->reverseJournals(
+ $journals,
+ $order,
+ 'storefront_sale_reversal',
+ "Storefront sale reversal - Order {$order->public_id} canceled",
+ $previousStatus,
+ $currentStatus
+ );
+ }
+
+ private function reverseOrderInvoiceRevenue($order, string $previousStatus, string $currentStatus): int
+ {
+ $invoices = Invoice::where('order_uuid', $order->uuid)->get();
+
+ foreach ($invoices as $invoice) {
+ $this->cancelOpenInvoice($invoice);
+ }
+
+ if ($invoices->isEmpty()) {
+ return 0;
+ }
+
+ $journals = Journal::with(['debitAccount', 'creditAccount'])
+ ->where('type', 'revenue_recognition')
+ ->where('status', 'posted')
+ ->whereIn('meta->invoice_uuid', $invoices->pluck('uuid')->all())
+ ->get();
+
+ return $this->reverseJournals(
+ $journals,
+ $order,
+ 'revenue_recognition_reversal',
+ "Invoice revenue reversal - Order {$order->public_id} canceled",
+ $previousStatus,
+ $currentStatus
+ );
+ }
+
+ private function reverseJournals($journals, $order, string $reversalType, string $description, string $previousStatus, string $currentStatus): int
+ {
+ $created = 0;
+
+ foreach ($journals as $journal) {
+ if (!$journal->debitAccount || !$journal->creditAccount || $journal->amount <= 0) {
+ continue;
+ }
+
+ if ($this->journalIsCurrentlyReversed($journal->uuid, $reversalType)) {
+ continue;
+ }
+
+ $meta = $this->correctionMeta($order, $journal, [
+ 'reverses_journal_uuid' => $journal->uuid,
+ 'reverses_journal_id' => $journal->public_id,
+ 'original_journal_type' => $journal->type,
+ 'original_status' => $previousStatus,
+ 'canceled_status' => $currentStatus,
+ ]);
+
+ $this->ledgerService->createJournalEntry(
+ $journal->creditAccount,
+ $journal->debitAccount,
+ (int) $journal->amount,
+ $description,
+ [
+ 'company_uuid' => $journal->company_uuid,
+ 'currency' => $journal->currency,
+ 'journal_type' => $reversalType,
+ 'entry_date' => now(),
+ 'meta' => $meta,
+ ]
+ );
+
+ $created++;
+ }
+
+ return $created;
+ }
+
+ private function reinstateReversedJournals($order, string $reversalType, string $reinstatementType, string $description, string $previousStatus, string $currentStatus): int
+ {
+ $reversals = Journal::with(['debitAccount', 'creditAccount'])
+ ->where('type', $reversalType)
+ ->where('status', 'posted')
+ ->where('meta->order_uuid', $order->uuid)
+ ->get();
+
+ $created = 0;
+
+ foreach ($reversals as $reversal) {
+ if (!$reversal->debitAccount || !$reversal->creditAccount || $reversal->amount <= 0) {
+ continue;
+ }
+
+ if ($this->journalExists($reinstatementType, 'reinstates_journal_uuid', $reversal->uuid)) {
+ continue;
+ }
+
+ $meta = $this->correctionMeta($order, $reversal, [
+ 'reinstates_journal_uuid' => $reversal->uuid,
+ 'reinstates_journal_id' => $reversal->public_id,
+ 'reverses_journal_uuid' => $reversal->getMeta('reverses_journal_uuid'),
+ 'reverses_journal_id' => $reversal->getMeta('reverses_journal_id'),
+ 'reversal_journal_type' => $reversal->type,
+ 'restored_from_status' => $previousStatus,
+ 'restored_status' => $currentStatus,
+ ]);
+
+ $this->ledgerService->createJournalEntry(
+ $reversal->creditAccount,
+ $reversal->debitAccount,
+ (int) $reversal->amount,
+ $description,
+ [
+ 'company_uuid' => $reversal->company_uuid,
+ 'currency' => $reversal->currency,
+ 'journal_type' => $reinstatementType,
+ 'entry_date' => now(),
+ 'meta' => $meta,
+ ]
+ );
+
+ $created++;
+ }
+
+ return $created;
+ }
+
+ private function cancelOpenInvoice(Invoice $invoice): void
+ {
+ if (in_array($invoice->status, ['paid', 'void', 'cancelled'], true)) {
+ return;
+ }
+
+ $invoice->updateMeta([
+ 'order_cancellation_previous_status' => $invoice->status,
+ 'order_cancellation_status_changed' => true,
+ ]);
+
+ $invoice->updateQuietly([
+ 'status' => $invoice->status === 'draft' ? 'void' : 'cancelled',
+ ]);
+ }
+
+ private function restoreOrderInvoices($order): void
+ {
+ Invoice::where('order_uuid', $order->uuid)
+ ->whereIn('status', ['void', 'cancelled'])
+ ->get()
+ ->each(function (Invoice $invoice) {
+ if (!$invoice->getMeta('order_cancellation_status_changed', false)) {
+ return;
+ }
+
+ $previousInvoiceStatus = $invoice->getMeta('order_cancellation_previous_status', 'draft');
+
+ $invoice->updateMeta([
+ 'order_cancellation_status_changed' => false,
+ 'order_cancellation_restored_at' => now()->toIso8601String(),
+ 'order_cancellation_restored_status' => $previousInvoiceStatus,
+ ]);
+
+ $invoice->updateQuietly([
+ 'status' => $previousInvoiceStatus,
+ ]);
+ });
+ }
+
+ private function correctionMeta($order, Journal $journal, array $meta): array
+ {
+ $journalMeta = $journal->getMeta();
+
+ $baseMeta = [
+ 'order_uuid' => $order->uuid,
+ 'order_id' => $order->public_id,
+ 'subject_uuid' => $order->uuid,
+ 'subject_type' => get_class($order),
+ ];
+
+ foreach (['invoice_uuid', 'seed', 'seed_id'] as $metaKey) {
+ if (isset($journalMeta[$metaKey])) {
+ $baseMeta[$metaKey] = $journalMeta[$metaKey];
+ } elseif ($order->hasMeta($metaKey)) {
+ $baseMeta[$metaKey] = $order->getMeta($metaKey);
+ }
+ }
+
+ return array_merge($baseMeta, $meta);
+ }
+
+ private function journalExists(string $journalType, string $metaKey, string $journalUuid): bool
+ {
+ return Journal::where('type', $journalType)
+ ->where("meta->{$metaKey}", $journalUuid)
+ ->exists();
+ }
+
+ private function journalIsCurrentlyReversed(string $journalUuid, string $reversalType): bool
+ {
+ $latestReversal = Journal::where('type', $reversalType)
+ ->where('meta->reverses_journal_uuid', $journalUuid)
+ ->orderBy('created_at', 'desc')
+ ->first();
+
+ if (!$latestReversal) {
+ return false;
+ }
+
+ $reinstatementType = str_replace('_reversal', '_reinstatement', $reversalType);
+
+ return !$this->journalExists($reinstatementType, 'reinstates_journal_uuid', $latestReversal->uuid);
+ }
+
+ private function normalizeStatus(string $status): string
+ {
+ return strtolower(trim($status));
+ }
+
+ private function isCanceledStatus(string $status): bool
+ {
+ return in_array($status, self::CANCELED_STATUSES, true);
+ }
+}
diff --git a/server/src/Observers/PurchaseRateObserver.php b/server/src/Observers/PurchaseRateObserver.php
index 83070c7..66799eb 100644
--- a/server/src/Observers/PurchaseRateObserver.php
+++ b/server/src/Observers/PurchaseRateObserver.php
@@ -2,8 +2,8 @@
namespace Fleetbase\Ledger\Observers;
-use Fleetbase\Ledger\Services\InvoiceService;
use Fleetbase\Ledger\Models\Invoice;
+use Fleetbase\Ledger\Services\InvoiceService;
use Illuminate\Support\Facades\Log;
/**
diff --git a/server/src/Observers/StorefrontOrderObserver.php b/server/src/Observers/StorefrontOrderObserver.php
deleted file mode 100644
index fff6fc8..0000000
--- a/server/src/Observers/StorefrontOrderObserver.php
+++ /dev/null
@@ -1,129 +0,0 @@
-type === 'storefront'`.
- * This is a first-class column on the orders table, always set by the
- * Storefront package, and is the authoritative signal.
- *
- * Accounting flow
- * ---------------
- * DEBIT CASH-DEFAULT (asset ↑ — cash received from customer)
- * CREDIT REV-DEFAULT (revenue ↑ — earned at point of sale)
- *
- * No invoice is created. Storefront orders are point-of-sale transactions;
- * the order record itself is the receipt. Creating a Ledger invoice would
- * be confusing and redundant.
- *
- * This observer is registered in LedgerServiceProvider only when the
- * Fleet-Ops Order class is present. No hard dependency is introduced.
- */
-class StorefrontOrderObserver
-{
- public function __construct(protected LedgerService $ledgerService)
- {
- }
-
- /**
- * Handle the Order "created" event.
- */
- public function created($order): void
- {
- if ($order->type !== 'storefront') {
- return;
- }
-
- try {
- DB::transaction(function () use ($order) {
- $companyUuid = $order->company_uuid;
- $currency = $order->getMeta('currency', 'USD');
- $total = (int) $order->getMeta('total', 0);
-
- if ($total <= 0) {
- Log::channel('ledger')->info('[Ledger] StorefrontOrderObserver: skipping order with zero total.', [
- 'order_uuid' => $order->uuid,
- ]);
-
- return;
- }
-
- // Idempotency: skip if a journal entry already exists for this order.
- $alreadyRecorded = \Fleetbase\Ledger\Models\Journal::where(
- 'meta->order_uuid', $order->uuid
- )->exists();
-
- if ($alreadyRecorded) {
- return;
- }
-
- $cashAccount = Account::updateOrCreate(
- ['company_uuid' => $companyUuid, 'code' => 'CASH-DEFAULT'],
- [
- 'name' => 'Cash',
- 'type' => 'asset',
- 'description' => 'Default cash account',
- 'is_system_account' => true,
- 'status' => 'active',
- ]
- );
-
- $revenueAccount = Account::updateOrCreate(
- ['company_uuid' => $companyUuid, 'code' => 'REV-DEFAULT'],
- [
- 'name' => 'Sales Revenue',
- 'type' => Account::TYPE_REVENUE,
- 'description' => 'Default sales revenue account',
- 'is_system_account' => true,
- 'status' => 'active',
- ]
- );
-
- $this->ledgerService->createJournalEntry(
- $cashAccount,
- $revenueAccount,
- $total,
- "Storefront sale — Order {$order->public_id}",
- [
- 'company_uuid' => $companyUuid,
- 'currency' => $currency,
- 'type' => 'storefront_sale',
- 'subject_uuid' => $order->uuid,
- 'subject_type' => get_class($order),
- 'entry_date' => now(),
- 'meta' => [
- 'order_uuid' => $order->uuid,
- 'order_id' => $order->public_id,
- ],
- ]
- );
-
- Log::channel('ledger')->info('[Ledger] StorefrontOrderObserver: journal entry created.', [
- 'order_uuid' => $order->uuid,
- 'total' => $total,
- 'currency' => $currency,
- ]);
- });
- } catch (\Throwable $e) {
- // Never let a Ledger failure abort the Storefront order creation flow.
- Log::channel('ledger')->error('[Ledger] StorefrontOrderObserver: failed.', [
- 'error' => $e->getMessage(),
- 'order_uuid' => $order->uuid ?? null,
- ]);
- }
- }
-}
diff --git a/server/src/Providers/LedgerServiceProvider.php b/server/src/Providers/LedgerServiceProvider.php
index deaf4eb..c435340 100644
--- a/server/src/Providers/LedgerServiceProvider.php
+++ b/server/src/Providers/LedgerServiceProvider.php
@@ -41,7 +41,7 @@ class LedgerServiceProvider extends CoreServiceProvider
// Optional integrations — silently skipped when the package is not installed.
// CoreServiceProvider::registerObservers() guards each entry with Utils::classExists().
'Fleetbase\\FleetOps\\Models\\PurchaseRate' => \Fleetbase\Ledger\Observers\PurchaseRateObserver::class,
- 'Fleetbase\\FleetOps\\Models\\Order' => \Fleetbase\Ledger\Observers\StorefrontOrderObserver::class,
+ 'Fleetbase\\FleetOps\\Models\\Order' => \Fleetbase\Ledger\Observers\OrderAccountingObserver::class,
];
/**
@@ -94,6 +94,7 @@ public function boot()
$this->registerExpansionsFrom(__DIR__ . '/../Expansions');
$this->loadRoutesFrom(__DIR__ . '/../routes.php');
$this->loadMigrationsFrom(__DIR__ . '/../../migrations');
+ $this->loadViewsFrom(__DIR__ . '/../../resources/views', 'ledger');
// Register event-listener bindings for the payment gateway system
$this->registerPaymentEvents();
diff --git a/server/src/Services/InvoiceService.php b/server/src/Services/InvoiceService.php
index f4294ba..082f8f5 100644
--- a/server/src/Services/InvoiceService.php
+++ b/server/src/Services/InvoiceService.php
@@ -7,7 +7,9 @@
use Fleetbase\Ledger\Models\Invoice;
use Fleetbase\Ledger\Models\InvoiceItem;
use Fleetbase\Ledger\Models\Transaction;
+use Fleetbase\Ledger\Notifications\InvoiceSent;
use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Notification;
class InvoiceService
{
@@ -89,6 +91,47 @@ public function createFromOrder(Order $order, array $options = [], ?object $purc
});
}
+ /**
+ * Send an invoice to its customer using the standard Ledger sent flow.
+ */
+ public function send(Invoice $invoice): Invoice
+ {
+ $invoice->loadMissing(['customer']);
+
+ if (in_array($invoice->status, ['paid', 'void', 'cancelled'], true)) {
+ throw new \InvalidArgumentException('Invoice cannot be sent in its current status.');
+ }
+
+ $email = $this->customerEmail($invoice);
+ if (!$email) {
+ throw new \InvalidArgumentException('Invoice customer does not have a valid email address.');
+ }
+
+ if ($invoice->status === 'draft') {
+ $invoice->markAsSent();
+ }
+
+ Notification::route('mail', $email)->notify(new InvoiceSent($invoice->fresh(['customer', 'items', 'template'])));
+
+ return $invoice->fresh(['customer', 'items', 'template']);
+ }
+
+ /**
+ * Resolve the best customer email available on the invoice customer model.
+ */
+ protected function customerEmail(Invoice $invoice): ?string
+ {
+ $customer = $invoice->customer;
+ if (!$customer) {
+ return null;
+ }
+
+ return $customer->email
+ ?? $customer->contact_email
+ ?? $customer->billing_email
+ ?? null;
+ }
+
/**
* Create invoice line items from a FleetOps order.
*
@@ -446,9 +489,12 @@ public function recogniseRevenue(Invoice $invoice): void
[
'company_uuid' => $invoice->company_uuid,
'currency' => $invoice->currency,
- 'type' => 'revenue_recognition',
- 'subject_uuid' => $invoice->uuid,
- 'subject_type' => Invoice::class,
+ 'journal_type' => 'revenue_recognition',
+ 'meta' => [
+ 'invoice_uuid' => $invoice->uuid,
+ 'subject_uuid' => $invoice->uuid,
+ 'subject_type' => Invoice::class,
+ ],
]
);
}
diff --git a/server/src/Services/LedgerService.php b/server/src/Services/LedgerService.php
index 978b75a..f5c8a3f 100644
--- a/server/src/Services/LedgerService.php
+++ b/server/src/Services/LedgerService.php
@@ -76,6 +76,11 @@ public function createJournalEntry(
$companyUuid = $options['company_uuid'] ?? session('company');
$currency = $options['currency'] ?? $debitAccount->currency ?? 'USD';
$meta = $options['meta'] ?? [];
+ foreach (['subject_uuid', 'subject_type', 'gateway_transaction_uuid'] as $metaKey) {
+ if (array_key_exists($metaKey, $options) && !array_key_exists($metaKey, $meta)) {
+ $meta[$metaKey] = $options[$metaKey];
+ }
+ }
// Create the double-entry Journal record, linked to the caller's Transaction if provided
$journal = Journal::create([
@@ -86,7 +91,7 @@ public function createJournalEntry(
'amount' => $amount,
'currency' => $currency,
'description' => $description,
- 'type' => $options['journal_type'] ?? 'general',
+ 'type' => $options['journal_type'] ?? $options['type'] ?? 'general',
'status' => 'posted',
'reference' => $options['reference'] ?? null,
'memo' => $options['memo'] ?? $description,
@@ -352,67 +357,256 @@ public function getIncomeStatement(string $companyUuid, ?string $startDate = nul
$startDate = $startDate ?? now()->startOfMonth()->toDateString();
$endDate = $endDate ?? now()->toDateString();
- $accounts = Account::where('company_uuid', $companyUuid)
- ->where('status', 'active')
- ->whereIn('type', [Account::TYPE_REVENUE, Account::TYPE_EXPENSE])
- ->orderBy('code')
+ $activity = $this->getProfitAndLossActivity($companyUuid, $startDate, $endDate);
+ $revenues = $activity['revenues'];
+ $expenses = $activity['expenses'];
+ $totalRevenue = $activity['total_revenue'];
+ $totalExpenses = $activity['total_expenses'];
+ $netIncome = $totalRevenue - $totalExpenses;
+
+ return [
+ 'period' => [
+ 'from' => $startDate,
+ 'to' => $endDate,
+ ],
+ 'revenues' => $revenues,
+ 'expenses' => $expenses,
+ 'total_revenue' => (int) $totalRevenue,
+ 'total_expenses' => (int) $totalExpenses,
+ 'net_income' => (int) $netIncome,
+ 'profitable' => $netIncome >= 0,
+ 'currency' => $activity['currency'],
+ 'daily' => $activity['daily'],
+ 'audit' => $activity['audit'],
+ ];
+ }
+
+ /**
+ * Return normalized profit and loss journal activity for reports and dashboard widgets.
+ */
+ protected function getProfitAndLossActivity(string $companyUuid, string $startDate, string $endDate): array
+ {
+ $rows = Journal::where('company_uuid', $companyUuid)
+ ->whereBetween('entry_date', [$startDate, $endDate])
+ ->where(function ($query) {
+ $query->whereHas('creditAccount', fn ($q) => $q->whereIn('type', [Account::TYPE_REVENUE, Account::TYPE_EXPENSE]))
+ ->orWhereHas('debitAccount', fn ($q) => $q->whereIn('type', [Account::TYPE_REVENUE, Account::TYPE_EXPENSE]));
+ })
+ ->with(['creditAccount', 'debitAccount'])
+ ->orderBy('entry_date')
+ ->orderBy('created_at')
->get();
- $revenues = [];
- $expenses = [];
+ [$journals, $duplicates] = $this->deduplicateProfitAndLossJournals($rows);
+ $revenues = [];
+ $expenses = [];
+ $daily = collect();
+ $revenueByType = [];
+ $expenseByType = [];
- foreach ($accounts as $account) {
- // Income statement uses only activity within the period
- $debits = Journal::where('debit_account_uuid', $account->uuid)
- ->whereBetween('entry_date', [$startDate, $endDate])
- ->sum('amount');
+ $cursor = now()->parse($startDate);
+ $end = now()->parse($endDate);
+
+ while ($cursor->lte($end)) {
+ $key = $cursor->toDateString();
+ $daily->put($key, ['date' => $key, 'revenue' => 0, 'expenses' => 0]);
+ $cursor->addDay();
+ }
- $credits = Journal::where('credit_account_uuid', $account->uuid)
- ->whereBetween('entry_date', [$startDate, $endDate])
- ->sum('amount');
+ foreach ($journals as $journal) {
+ $date = $journal->entry_date instanceof \DateTimeInterface ? $journal->entry_date->format('Y-m-d') : (string) $journal->entry_date;
- if ($account->type === Account::TYPE_REVENUE) {
- $balance = (int) ($credits - $debits); // credit-normal
- } else {
- $balance = (int) ($debits - $credits); // debit-normal
+ if (!$daily->has($date)) {
+ $daily->put($date, ['date' => $date, 'revenue' => 0, 'expenses' => 0]);
}
- if ($balance === 0) {
- continue;
+ $dailyEntry = $daily->get($date);
+
+ if ($journal->creditAccount?->type === Account::TYPE_REVENUE) {
+ $amount = (int) $journal->amount;
+ $accountKey = $journal->creditAccount->uuid;
+ $typeKey = $journal->type ?: 'general';
+
+ $revenues[$accountKey] ??= $this->makeProfitAndLossAccountRow($journal->creditAccount);
+ $revenues[$accountKey]['balance'] += $amount;
+ $dailyEntry['revenue'] += $amount;
+ $revenueByType[$typeKey] = ($revenueByType[$typeKey] ?? 0) + $amount;
}
- $row = [
- 'uuid' => $account->uuid,
- 'code' => $account->code,
- 'name' => $account->name,
- 'balance' => $balance,
- ];
+ if ($journal->debitAccount?->type === Account::TYPE_REVENUE) {
+ $amount = (int) $journal->amount;
+ $accountKey = $journal->debitAccount->uuid;
+ $typeKey = $journal->type ?: 'general';
- if ($account->type === Account::TYPE_REVENUE) {
- $revenues[] = $row;
- } else {
- $expenses[] = $row;
+ $revenues[$accountKey] ??= $this->makeProfitAndLossAccountRow($journal->debitAccount);
+ $revenues[$accountKey]['balance'] -= $amount;
+ $dailyEntry['revenue'] -= $amount;
+ $revenueByType[$typeKey] = ($revenueByType[$typeKey] ?? 0) - $amount;
}
+
+ if ($journal->debitAccount?->type === Account::TYPE_EXPENSE) {
+ $amount = (int) $journal->amount;
+ $accountKey = $journal->debitAccount->uuid;
+ $typeKey = $journal->type ?: 'general';
+
+ $expenses[$accountKey] ??= $this->makeProfitAndLossAccountRow($journal->debitAccount);
+ $expenses[$accountKey]['balance'] += $amount;
+ $dailyEntry['expenses'] += $amount;
+ $expenseByType[$typeKey] = ($expenseByType[$typeKey] ?? 0) + $amount;
+ }
+
+ if ($journal->creditAccount?->type === Account::TYPE_EXPENSE) {
+ $amount = (int) $journal->amount;
+ $accountKey = $journal->creditAccount->uuid;
+ $typeKey = $journal->type ?: 'general';
+
+ $expenses[$accountKey] ??= $this->makeProfitAndLossAccountRow($journal->creditAccount);
+ $expenses[$accountKey]['balance'] -= $amount;
+ $dailyEntry['expenses'] -= $amount;
+ $expenseByType[$typeKey] = ($expenseByType[$typeKey] ?? 0) - $amount;
+ }
+
+ $daily->put($date, $dailyEntry);
}
- $totalRevenue = array_sum(array_column($revenues, 'balance'));
- $totalExpenses = array_sum(array_column($expenses, 'balance'));
- $netIncome = $totalRevenue - $totalExpenses;
+ $revenues = collect($revenues)->filter(fn ($row) => $row['balance'] !== 0)->sortBy('code')->values();
+ $expenses = collect($expenses)->filter(fn ($row) => $row['balance'] !== 0)->sortBy('code')->values();
+ $currency = $this->resolveCurrencyFromJournals($journals) ?? $this->resolveDashboardCurrency();
return [
- 'period' => [
- 'from' => $startDate,
- 'to' => $endDate,
+ 'revenues' => $revenues->all(),
+ 'expenses' => $expenses->all(),
+ 'total_revenue' => (int) $revenues->sum('balance'),
+ 'total_expenses' => (int) $expenses->sum('balance'),
+ 'daily' => $daily->sortKeys()->values(),
+ 'currency' => $currency,
+ 'audit' => [
+ 'source' => 'ledger_journals',
+ 'amount_unit' => 'minor',
+ 'journal_rows' => $rows->count(),
+ 'counted_rows' => $journals->count(),
+ 'deduplicated_rows' => $duplicates,
+ 'revenue_by_type' => $revenueByType,
+ 'expense_by_type' => $expenseByType,
+ 'duplicate_strategy' => 'source_record_fingerprint',
],
- 'revenues' => $revenues,
- 'expenses' => $expenses,
- 'total_revenue' => (int) $totalRevenue,
- 'total_expenses' => (int) $totalExpenses,
- 'net_income' => (int) $netIncome,
- 'profitable' => $netIncome >= 0,
];
}
+ /**
+ * Keep one accounting journal per authoritative invoice/order/gateway source.
+ */
+ protected function deduplicateProfitAndLossJournals(Collection $rows): array
+ {
+ $seen = [];
+ $duplicates = 0;
+ $journals = collect();
+
+ foreach ($rows as $journal) {
+ $key = $this->profitAndLossJournalFingerprint($journal);
+
+ if ($key && array_key_exists($key, $seen)) {
+ $duplicates++;
+ continue;
+ }
+
+ if ($key) {
+ $seen[$key] = true;
+ }
+
+ $journals->push($journal);
+ }
+
+ return [$journals, $duplicates];
+ }
+
+ /**
+ * Build a stable source fingerprint for revenue/expense rows that are backed by another record.
+ */
+ protected function profitAndLossJournalFingerprint(Journal $journal): ?string
+ {
+ $meta = $journal->meta ?? [];
+ $companyUuid = $journal->company_uuid;
+ $description = (string) $journal->description;
+
+ if (str_ends_with((string) $journal->type, '_reversal')) {
+ $reversesJournalUuid = data_get($meta, 'reverses_journal_uuid');
+
+ return implode('|', [
+ 'journal-reversal',
+ $companyUuid,
+ (string) $journal->type,
+ $reversesJournalUuid ?: $journal->uuid,
+ ]);
+ }
+
+ if (str_ends_with((string) $journal->type, '_reinstatement')) {
+ $reinstatesJournalUuid = data_get($meta, 'reinstates_journal_uuid');
+
+ return implode('|', [
+ 'journal-reinstatement',
+ $companyUuid,
+ (string) $journal->type,
+ $reinstatesJournalUuid ?: $journal->uuid,
+ ]);
+ }
+
+ if (preg_match('/Revenue recognition for invoice\s+([^\s\[]+)/', $description, $matches)) {
+ return implode('|', [
+ 'invoice-number',
+ $companyUuid,
+ $matches[1],
+ (string) $journal->amount,
+ (string) $journal->currency,
+ ]);
+ }
+
+ $invoiceUuid = data_get($meta, 'invoice_uuid');
+ if ($invoiceUuid) {
+ return implode('|', ['invoice', $companyUuid, $invoiceUuid]);
+ }
+
+ $orderUuid = data_get($meta, 'order_uuid');
+ if ($orderUuid) {
+ return implode('|', ['order', $companyUuid, $orderUuid]);
+ }
+
+ $gatewayTransactionUuid = data_get($meta, 'gateway_transaction_uuid');
+ if ($gatewayTransactionUuid) {
+ return implode('|', ['gateway-transaction', $companyUuid, $gatewayTransactionUuid]);
+ }
+
+ $transactionUuid = $journal->transaction_uuid;
+ if ($transactionUuid && in_array($journal->type, ['revenue', 'expense', 'gateway_payment', 'wallet_fee', 'refund'], true)) {
+ return implode('|', ['transaction', $companyUuid, $transactionUuid, (string) $journal->type]);
+ }
+
+ return null;
+ }
+
+ /**
+ * Build a report row from an account model.
+ */
+ protected function makeProfitAndLossAccountRow(Account $account): array
+ {
+ return [
+ 'uuid' => $account->uuid,
+ 'code' => $account->code,
+ 'name' => $account->name,
+ 'balance' => 0,
+ ];
+ }
+
+ /**
+ * Resolve the currency used by counted journal rows when all rows agree.
+ */
+ protected function resolveCurrencyFromJournals(Collection $journals): ?string
+ {
+ $currencies = $journals->pluck('currency')->filter()->unique()->values();
+
+ return $currencies->count() === 1 ? $currencies->first() : null;
+ }
+
// =========================================================================
// Cash Flow Summary
// =========================================================================
@@ -533,6 +727,277 @@ protected function computeNetFlow(array $items): int
return $net;
}
+ /**
+ * Return owner/operator KPI tiles for the redesigned dashboard.
+ */
+ public function getDashboardSummary(string $companyUuid, ?string $startDate = null, ?string $endDate = null): array
+ {
+ $dashboard = $this->getDashboardMetrics($companyUuid, $startDate, $endDate);
+ $currency = $dashboard['currency'] ?? $this->resolveDashboardCurrency($dashboard['kpis']['wallet_totals'] ?? []);
+
+ $outstandingAr = $dashboard['kpis']['outstanding_ar'] ?? ['total' => 0, 'overdue' => 0];
+ $invoiceCounts = collect($dashboard['invoice_counts'] ?? []);
+ $walletTotals = collect($dashboard['kpis']['wallet_totals'] ?? []);
+ $walletMetric = $walletTotals->count() === 1 ? (int) ($walletTotals->first()['total'] ?? 0) : null;
+
+ return [
+ 'period' => $dashboard['period'],
+ 'currency' => $currency,
+ 'audit' => $dashboard['audit'] ?? [],
+ 'metrics' => [
+ 'total_revenue' => $this->makeDashboardMetric('Total Revenue', $dashboard['kpis']['total_revenue'] ?? [], 'money', $currency),
+ 'total_expenses' => $this->makeDashboardMetric('Total Expenses', $dashboard['kpis']['total_expenses'] ?? [], 'money', $currency, true),
+ 'net_income' => $this->makeDashboardMetric('Net Income', $dashboard['kpis']['net_income'] ?? [], 'money', $currency),
+ 'outstanding_ar' => [
+ 'label' => 'Outstanding AR',
+ 'value' => (int) ($outstandingAr['total'] ?? 0),
+ 'previous' => null,
+ 'delta_percent' => null,
+ 'format' => 'money',
+ 'currency' => $currency,
+ 'inverse' => true,
+ ],
+ 'overdue_ar' => [
+ 'label' => 'Overdue AR',
+ 'value' => (int) ($outstandingAr['overdue'] ?? 0),
+ 'previous' => null,
+ 'delta_percent' => null,
+ 'format' => 'money',
+ 'currency' => $currency,
+ 'inverse' => true,
+ ],
+ 'open_invoices' => [
+ 'label' => 'Open Invoices',
+ 'value' => (int) $invoiceCounts->except(['paid', 'cancelled', 'void'])->sum(),
+ 'previous' => null,
+ 'delta_percent' => null,
+ 'format' => 'count',
+ 'currency' => $currency,
+ 'inverse' => true,
+ ],
+ 'wallet_balance' => [
+ 'label' => 'Wallet Balance',
+ 'value' => $walletMetric,
+ 'previous' => null,
+ 'delta_percent' => null,
+ 'format' => 'money',
+ 'currency' => $walletTotals->count() === 1 ? $walletTotals->first()['currency'] : $currency,
+ 'inverse' => false,
+ 'multi_currency' => $walletTotals->count() > 1,
+ 'currencies' => $walletTotals->values(),
+ ],
+ 'active_wallets' => [
+ 'label' => 'Active Wallets',
+ 'value' => (int) $walletTotals->sum('count'),
+ 'previous' => null,
+ 'delta_percent' => null,
+ 'format' => 'count',
+ 'currency' => $currency,
+ 'inverse' => false,
+ ],
+ ],
+ ];
+ }
+
+ /**
+ * Return revenue and expense trend rows for chart widgets.
+ */
+ public function getDashboardRevenueTrend(string $companyUuid, ?string $startDate = null, ?string $endDate = null): array
+ {
+ $startDate = $startDate ?? now()->subDays(29)->toDateString();
+ $endDate = $endDate ?? now()->toDateString();
+ $activity = $this->getProfitAndLossActivity($companyUuid, $startDate, $endDate);
+ $points = $activity['daily'];
+ $revenue = (int) $points->sum('revenue');
+ $expenses = (int) $points->sum('expenses');
+
+ return [
+ 'period' => [
+ 'from' => $startDate,
+ 'to' => $endDate,
+ ],
+ 'currency' => $activity['currency'],
+ 'audit' => $activity['audit'],
+ 'summary' => [
+ 'revenue' => $revenue,
+ 'expenses' => $expenses,
+ 'net' => $revenue - $expenses,
+ ],
+ 'labels' => $points->pluck('date')->values(),
+ 'datasets' => [
+ [
+ 'label' => 'Revenue',
+ 'data' => $points->pluck('revenue')->values(),
+ 'borderColor' => '#059669',
+ 'backgroundColor' => 'rgba(5, 150, 105, 0.12)',
+ 'tension' => 0.35,
+ 'fill' => true,
+ ],
+ [
+ 'label' => 'Expenses',
+ 'data' => $points->pluck('expenses')->values(),
+ 'borderColor' => '#dc2626',
+ 'backgroundColor' => 'rgba(220, 38, 38, 0.08)',
+ 'tension' => 0.35,
+ 'fill' => true,
+ ],
+ ],
+ ];
+ }
+
+ /**
+ * Return a condensed cash flow summary for the dashboard.
+ */
+ public function getDashboardCashFlowSummary(string $companyUuid, ?string $startDate = null, ?string $endDate = null): array
+ {
+ $cashFlow = $this->getCashFlowSummary($companyUuid, $startDate, $endDate);
+
+ return [
+ 'period' => $cashFlow['period'],
+ 'currency' => $this->resolveDashboardCurrency(),
+ 'operating' => (int) ($cashFlow['operating_activities']['net_flow'] ?? 0),
+ 'financing' => (int) ($cashFlow['financing_activities']['net_flow'] ?? 0),
+ 'investing' => (int) ($cashFlow['investing_activities']['net_flow'] ?? 0),
+ 'net_cash_change' => (int) ($cashFlow['net_cash_change'] ?? 0),
+ 'cash_account' => $cashFlow['cash_account'],
+ ];
+ }
+
+ /**
+ * Return invoice counts and balances by status.
+ */
+ public function getDashboardInvoiceStatus(string $companyUuid): array
+ {
+ $statuses = ['draft', 'sent', 'paid', 'overdue', 'cancelled', 'void'];
+ $rows = Invoice::where('company_uuid', $companyUuid)
+ ->select('status', 'currency', DB::raw('count(*) as count'), DB::raw('sum(total_amount) as total'), DB::raw('sum(balance) as balance'))
+ ->groupBy('status', 'currency')
+ ->get();
+
+ $summary = collect($statuses)->map(function ($status) use ($rows) {
+ $matches = $rows->where('status', $status);
+
+ return [
+ 'status' => $status,
+ 'count' => (int) $matches->sum('count'),
+ 'total' => (int) $matches->sum('total'),
+ 'balance' => (int) $matches->sum('balance'),
+ 'currency' => $matches->pluck('currency')->filter()->unique()->count() === 1 ? $matches->first()?->currency : null,
+ ];
+ })->values();
+
+ return [
+ 'total_count' => (int) $summary->sum('count'),
+ 'total_open' => (int) $summary->whereNotIn('status', ['paid', 'cancelled', 'void'])->sum('balance'),
+ 'summary' => $summary,
+ ];
+ }
+
+ /**
+ * Return compact AR aging buckets for dashboard widgets.
+ */
+ public function getDashboardArAgingSummary(string $companyUuid, ?string $asOfDate = null): array
+ {
+ $aging = $this->getArAging($companyUuid, $asOfDate);
+
+ return [
+ 'as_of_date' => $aging['as_of_date'],
+ 'grand_total' => $aging['grand_total'],
+ 'total_invoices' => $aging['total_invoices'],
+ 'buckets' => collect($aging['buckets'])->map(fn ($bucket, $key) => [
+ 'key' => $key,
+ 'label' => $bucket['label'],
+ 'days_range' => $bucket['days_range'],
+ 'total' => (int) $bucket['total'],
+ 'invoice_count' => count($bucket['invoices'] ?? []),
+ ])->values(),
+ ];
+ }
+
+ /**
+ * Return dashboard-ready wallet totals and top wallet rows.
+ */
+ public function getDashboardWalletBalances(string $companyUuid, ?string $dateFrom = null, ?string $dateTo = null): array
+ {
+ $dashboard = $this->getDashboardMetrics($companyUuid, $dateFrom, $dateTo);
+
+ $topWallets = Wallet::where('company_uuid', $companyUuid)
+ ->where('status', Wallet::STATUS_ACTIVE)
+ ->with('subject')
+ ->orderBy('balance', 'desc')
+ ->limit(10)
+ ->get()
+ ->map(fn ($wallet) => [
+ 'wallet_public_id' => $wallet->public_id,
+ 'name' => $wallet->name,
+ 'type' => $wallet->type,
+ 'balance' => (int) $wallet->balance,
+ 'formatted_balance' => $wallet->formatted_balance,
+ 'currency' => $wallet->currency,
+ 'subject' => $wallet->subject ? [
+ 'name' => $wallet->subject->name ?? $wallet->subject->email ?? $wallet->subject->public_id ?? $wallet->subject->uuid,
+ ] : null,
+ ]);
+
+ return [
+ 'period' => $dashboard['period'],
+ 'totals' => $dashboard['kpis']['wallet_totals'] ?? [],
+ 'top_wallets' => $topWallets,
+ ];
+ }
+
+ /**
+ * Return recent financial activity for the dashboard feed.
+ */
+ public function getDashboardActivity(string $companyUuid, int $limit = 10): array
+ {
+ $journals = Journal::where('company_uuid', $companyUuid)
+ ->with(['debitAccount', 'creditAccount'])
+ ->orderBy('created_at', 'desc')
+ ->limit($limit)
+ ->get()
+ ->map(fn ($journal) => [
+ 'type' => 'journal',
+ 'public_id' => $journal->public_id,
+ 'description' => $journal->description,
+ 'amount' => (int) $journal->amount,
+ 'currency' => $journal->currency,
+ 'status' => $journal->status,
+ 'created_at' => $journal->created_at,
+ 'debit' => $journal->debitAccount?->name,
+ 'credit' => $journal->creditAccount?->name,
+ ]);
+
+ return [
+ 'items' => $journals,
+ ];
+ }
+
+ protected function makeDashboardMetric(string $label, array $source, string $format, string $currency, bool $inverse = false): array
+ {
+ return [
+ 'label' => $label,
+ 'value' => (int) ($source['current'] ?? 0),
+ 'previous' => isset($source['previous']) ? (int) $source['previous'] : null,
+ 'delta_percent' => $source['change_pct'] ?? null,
+ 'format' => $format,
+ 'currency' => $source['currency'] ?? $currency,
+ 'inverse' => $inverse,
+ 'audit' => $source['audit'] ?? null,
+ ];
+ }
+
+ protected function resolveDashboardCurrency(iterable $walletTotals = []): string
+ {
+ foreach ($walletTotals as $row) {
+ if (!empty($row['currency'])) {
+ return $row['currency'];
+ }
+ }
+
+ return 'USD';
+ }
+
// =========================================================================
// Accounts Receivable Aging
// =========================================================================
@@ -687,17 +1152,15 @@ public function getDashboardMetrics(string $companyUuid, ?string $startDate = nu
]);
// Revenue trend — daily breakdown for the current period
- $revenueTrend = Journal::where('company_uuid', $companyUuid)
- ->whereHas('creditAccount', fn ($q) => $q->where('type', Account::TYPE_REVENUE))
- ->whereBetween('entry_date', [$startDate, $endDate])
- ->select('entry_date', DB::raw('sum(amount) as daily_revenue'))
- ->groupBy('entry_date')
- ->orderBy('entry_date')
- ->get()
- ->map(fn ($r) => [
- 'date' => $r->entry_date,
- 'daily_revenue' => (int) $r->daily_revenue,
- ]);
+ $revenueTrend = collect($currentIncome['daily'] ?? []);
+ if ($revenueTrend->isEmpty()) {
+ $revenueTrend = $this->getProfitAndLossActivity($companyUuid, $startDate, $endDate)['daily'];
+ }
+
+ $revenueTrend = $revenueTrend->map(fn ($r) => [
+ 'date' => $r['date'],
+ 'daily_revenue' => (int) $r['revenue'],
+ ]);
// Recent journal entries
$recentJournals = Journal::where('company_uuid', $companyUuid)
@@ -713,22 +1176,29 @@ public function getDashboardMetrics(string $companyUuid, ?string $startDate = nu
'previous_from' => $prevStartDate,
'previous_to' => $prevEndDate,
],
- 'kpis' => [
+ 'currency' => $currentIncome['currency'] ?? $this->resolveDashboardCurrency($walletTotals),
+ 'kpis' => [
'total_revenue' => [
'current' => $currentIncome['total_revenue'],
'previous' => $previousIncome['total_revenue'],
'change_pct' => $this->percentageChange($previousIncome['total_revenue'], $currentIncome['total_revenue']),
+ 'currency' => $currentIncome['currency'],
+ 'audit' => $currentIncome['audit'],
],
'total_expenses' => [
'current' => $currentIncome['total_expenses'],
'previous' => $previousIncome['total_expenses'],
'change_pct' => $this->percentageChange($previousIncome['total_expenses'], $currentIncome['total_expenses']),
+ 'currency' => $currentIncome['currency'],
+ 'audit' => $currentIncome['audit'],
],
'net_income' => [
'current' => $currentIncome['net_income'],
'previous' => $previousIncome['net_income'],
'change_pct' => $this->percentageChange($previousIncome['net_income'], $currentIncome['net_income']),
'profitable' => $currentIncome['net_income'] >= 0,
+ 'currency' => $currentIncome['currency'],
+ 'audit' => $currentIncome['audit'],
],
'outstanding_ar' => [
'total' => (int) $outstandingAr,
@@ -739,6 +1209,10 @@ public function getDashboardMetrics(string $companyUuid, ?string $startDate = nu
'invoice_counts' => $invoiceCounts,
'revenue_trend' => $revenueTrend,
'recent_journals' => $recentJournals,
+ 'audit' => [
+ 'income_statement' => $currentIncome['audit'],
+ 'previous_period' => $previousIncome['audit'],
+ ],
];
}
diff --git a/server/src/routes.php b/server/src/routes.php
index 81e7893..dbe9266 100644
--- a/server/src/routes.php
+++ b/server/src/routes.php
@@ -95,6 +95,7 @@ function ($router, $controller) {
function ($router, $controller) {
$router->post('create-from-order', $controller('createFromOrder'));
$router->post('{id}/record-payment', $controller('recordPayment'));
+ $router->get('{id}/transactions', $controller('transactions'));
$router->post('{id}/mark-as-sent', $controller('markAsSent'));
$router->post('{id}/send', $controller('send'));
$router->post('{id}/preview', $controller('preview'));
@@ -173,6 +174,13 @@ function ($router, $controller) {
// ----------------------------------------------------------------
$router->get('reports/general-ledger', 'ReportController@generalLedger');
$router->get('reports/dashboard', 'ReportController@dashboard');
+ $router->get('reports/dashboard/summary', 'ReportController@dashboardSummary');
+ $router->get('reports/dashboard/revenue-trend', 'ReportController@dashboardRevenueTrend');
+ $router->get('reports/dashboard/cash-flow-summary', 'ReportController@dashboardCashFlowSummary');
+ $router->get('reports/dashboard/invoice-status', 'ReportController@dashboardInvoiceStatus');
+ $router->get('reports/dashboard/ar-aging-summary', 'ReportController@dashboardArAgingSummary');
+ $router->get('reports/dashboard/wallet-balances', 'ReportController@dashboardWalletBalances');
+ $router->get('reports/dashboard/activity', 'ReportController@dashboardActivity');
$router->get('reports/trial-balance', 'ReportController@trialBalance');
$router->get('reports/balance-sheet', 'ReportController@balanceSheet');
$router->get('reports/income-statement', 'ReportController@incomeStatement');
diff --git a/server/tests/Feature.php b/server/tests/Feature.php
index 61cd84c..ac5c80b 100644
--- a/server/tests/Feature.php
+++ b/server/tests/Feature.php
@@ -3,3 +3,55 @@
test('example', function () {
expect(true)->toBeTrue();
});
+
+test('ledger dashboard report endpoints are registered', function () {
+ $routes = file_get_contents(__DIR__ . '/../src/routes.php');
+
+ expect($routes)
+ ->toContain('reports/dashboard/summary')
+ ->toContain('reports/dashboard/revenue-trend')
+ ->toContain('reports/dashboard/cash-flow-summary')
+ ->toContain('reports/dashboard/invoice-status')
+ ->toContain('reports/dashboard/ar-aging-summary')
+ ->toContain('reports/dashboard/wallet-balances')
+ ->toContain('reports/dashboard/activity');
+});
+
+test('order accounting observer preserves seed metadata on storefront sale journal entries', function () {
+ $observer = file_get_contents(__DIR__ . '/../src/Observers/OrderAccountingObserver.php');
+
+ expect($observer)
+ ->toContain("foreach (['seed', 'seed_id'] as \$seedMetaKey)")
+ ->toContain('$meta[$seedMetaKey] = $order->getMeta($seedMetaKey)')
+ ->toContain("'meta' => \$meta");
+});
+
+test('order accounting observer handles cancellation and reinstatement journal corrections', function () {
+ $observer = file_get_contents(__DIR__ . '/../src/Observers/OrderAccountingObserver.php');
+ $provider = file_get_contents(__DIR__ . '/../src/Providers/LedgerServiceProvider.php');
+
+ expect($provider)
+ ->toContain('Fleetbase\\\\FleetOps\\\\Models\\\\Order')
+ ->toContain('OrderAccountingObserver::class');
+
+ expect($observer)
+ ->toContain('storefront_sale_reversal')
+ ->toContain('storefront_sale_reinstatement')
+ ->toContain('revenue_recognition_reversal')
+ ->toContain('revenue_recognition_reinstatement')
+ ->toContain('reverses_journal_uuid')
+ ->toContain('reinstates_journal_uuid')
+ ->toContain('order_cancellation_previous_status');
+});
+
+test('profit and loss deduplication preserves reversal and reinstatement journals', function () {
+ $service = file_get_contents(__DIR__ . '/../src/Services/LedgerService.php');
+
+ expect($service)
+ ->toContain("str_ends_with((string) \$journal->type, '_reversal')")
+ ->toContain('journal-reversal')
+ ->toContain('reverses_journal_uuid')
+ ->toContain("str_ends_with((string) \$journal->type, '_reinstatement')")
+ ->toContain('journal-reinstatement')
+ ->toContain('reinstates_journal_uuid');
+});
diff --git a/tests/integration/components/ledger-dashboard/date-range-control-test.js b/tests/integration/components/ledger-dashboard/date-range-control-test.js
new file mode 100644
index 0000000..715e66a
--- /dev/null
+++ b/tests/integration/components/ledger-dashboard/date-range-control-test.js
@@ -0,0 +1,15 @@
+import { module, test } from 'qunit';
+import { setupRenderingTest } from 'fleetbase-ledger-engine/tests/helpers';
+import { render } from '@ember/test-helpers';
+import { hbs } from 'ember-cli-htmlbars';
+
+module('Integration | Component | ledger-dashboard/date-range-control', function (hooks) {
+ setupRenderingTest(hooks);
+
+ test('it renders the dashboard period DatePicker wrapper', async function (assert) {
+ await render(hbs``);
+
+ assert.dom('.ledger-dashboard-period-control').exists();
+ assert.dom('.ledger-dashboard-period-control .form-input').exists();
+ });
+});
diff --git a/tests/unit/extension-test.js b/tests/unit/extension-test.js
new file mode 100644
index 0000000..cf7fe35
--- /dev/null
+++ b/tests/unit/extension-test.js
@@ -0,0 +1,57 @@
+import { module, test } from 'qunit';
+import extension from '@fleetbase/ledger-engine/extension';
+
+module('Unit | extension', function () {
+ test('it registers invoice tabs for FleetOps and Storefront order details', function (assert) {
+ assert.expect(11);
+
+ const registrations = [];
+ const dashboards = [];
+ const widgetRegistrations = [];
+ const universe = {
+ getService(name) {
+ if (name === 'universe/menu-service') {
+ return {
+ registerHeaderMenuItem() {},
+ registerMenuItem(registry, menuItem) {
+ registrations.push({ registry, menuItem });
+ },
+ };
+ }
+
+ if (name === 'universe/widget-service') {
+ return {
+ registerDashboard(id) {
+ dashboards.push(id);
+ },
+ registerWidgets(id, widgets) {
+ widgetRegistrations.push({ id, widgets });
+ },
+ };
+ }
+ },
+ };
+
+ extension.setupExtension(null, universe);
+
+ const fleetOpsTab = registrations.find(({ registry, menuItem }) => registry === 'fleet-ops:component:order:details' && menuItem.slug === 'invoice');
+ const storefrontTab = registrations.find(({ registry, menuItem }) => registry === 'storefront:component:order:details' && menuItem.slug === 'invoice');
+
+ assert.ok(fleetOpsTab);
+ assert.strictEqual(fleetOpsTab.menuItem.route, 'operations.orders.index.details.virtual');
+ assert.strictEqual(fleetOpsTab.menuItem.icon, 'file-invoice-dollar');
+ assert.strictEqual(fleetOpsTab.menuItem.component.name, 'order-invoice');
+
+ assert.ok(storefrontTab);
+ assert.strictEqual(storefrontTab.menuItem.route, 'orders.index.view.virtual');
+ assert.strictEqual(storefrontTab.menuItem.icon, 'file-invoice-dollar');
+ assert.strictEqual(storefrontTab.menuItem.component.name, 'order-invoice');
+
+ assert.deepEqual(dashboards, ['ledger']);
+
+ const ledgerWidgets = widgetRegistrations.find((registration) => registration.id === 'ledger')?.widgets ?? [];
+ assert.ok(ledgerWidgets.find((widget) => widget.id === 'ledger-kpi-revenue'));
+ assert.ok(ledgerWidgets.find((widget) => widget.id === 'ledger-report-shortcuts'));
+ assert.notOk(ledgerWidgets.find((widget) => widget.id === 'ledger-overview')?.default);
+ });
+});
diff --git a/tests/unit/services/ledger-dashboard-test.js b/tests/unit/services/ledger-dashboard-test.js
new file mode 100644
index 0000000..72d20f7
--- /dev/null
+++ b/tests/unit/services/ledger-dashboard-test.js
@@ -0,0 +1,57 @@
+import { module, test } from 'qunit';
+import { setupTest } from 'fleetbase-ledger-engine/tests/helpers';
+
+function formatDate(date) {
+ const year = date.getFullYear();
+ const month = `${date.getMonth() + 1}`.padStart(2, '0');
+ const day = `${date.getDate()}`.padStart(2, '0');
+
+ return `${year}-${month}-${day}`;
+}
+
+module('Unit | Service | ledger-dashboard', function (hooks) {
+ setupTest(hooks);
+
+ test('it defaults to month-to-date params', function (assert) {
+ const service = this.owner.lookup('service:ledger-dashboard');
+ const today = new Date();
+ const start = new Date(today.getFullYear(), today.getMonth(), 1);
+
+ assert.deepEqual(service.dateRange, [formatDate(start), formatDate(today)]);
+ assert.deepEqual(service.periodParams, {
+ start_date: formatDate(start),
+ end_date: formatDate(today),
+ });
+ assert.deepEqual(service.walletPeriodParams, {
+ date_from: formatDate(start),
+ date_to: formatDate(today),
+ });
+ assert.deepEqual(service.asOfParams, {
+ as_of_date: formatDate(today),
+ });
+ });
+
+ test('it updates subscribers when the period changes', function (assert) {
+ assert.expect(4);
+
+ const service = this.owner.lookup('service:ledger-dashboard');
+ const unsubscribe = service.subscribe((dashboard) => {
+ assert.strictEqual(dashboard.startDate, '2026-05-01');
+ assert.strictEqual(dashboard.endDate, '2026-05-31');
+ });
+
+ service.setDateRange({ formattedDate: ['2026-05-01', '2026-05-31'] });
+
+ assert.deepEqual(service.periodParams, {
+ start_date: '2026-05-01',
+ end_date: '2026-05-31',
+ });
+
+ unsubscribe();
+ service.setDateRange({ formattedDate: ['2026-04-01', '2026-04-30'] });
+ assert.deepEqual(service.periodParams, {
+ start_date: '2026-04-01',
+ end_date: '2026-04-30',
+ });
+ });
+});