Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 8 additions & 11 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
> v0.0.11 ~ "Currencies that save, and ledger on the default dashboard"
> v0.0.12 ~ "Extensions can add columns, actions and buttons to ledger tables and panels"

---
## Highlights
Ledger's widgets take a planned place on the console's Default Dashboard, and the base and invoice currencies chosen in settings are saved.

---
## Improvements
- **Ledger on the Default Dashboard.** Revenue sits in the top KPI row beside Fleet-Ops' Radar, Active Orders and Drivers Online. Expenses, Net Income, Outstanding AR and Overdue AR form the row under it; Overdue AR is new on the default dashboard. Recent Financial Activity and Cash Flow Summary sit in the lower left, as tall as the Blog and GitHub cards beside them. Ledger's own dashboard keeps its full widget set. The layout needs `@fleetbase/ember-ui` v0.4.4; on older versions the widgets appear as before.
- **Resource view registries.** Extensions can add the following through `ledger:<resource>:table:<slot>` and `ledger:<resource>:details:<slot>`:
- columns, row actions, bulk actions and toolbar buttons on every ledger table;
- header buttons and "…" menu items on every details panel.

---
## Bug Fixes
- **The base and invoice currencies never saved** ([fleetbase/fleetbase#678](https://github.com/fleetbase/fleetbase/issues/678)). `CurrencySelect` passes the ISO code first, but the Accounting and Invoice settings read `.code` from it, so Save stored `null` and the page fell back to the default after a reload.
- **A wallet's currency couldn't be changed.** Editing a wallet failed with `Column 'balance' cannot be null`, because the console sent the whole record back. The serializer no longer sends `balance` or `formatted_balance`, and `WalletController::updateRecord` drops them, so a balance only moves through transactions.
Resources: `account`, `gateway`, `invoice`, `invoice-template`, `journal`, `transaction`, `wallet`. Built-in items carry stable ids, so registered items can be placed before or after them.

---
## Continuous Integration
- The release workflow accepts `release/v*` branches alongside `dev-v*`.
## Upgrading
Needs fleetbase/ember-core v0.3.25 and fleetbase/ember-ui v0.4.5.

---
## Need help?
- [GitHub Discussions](https://github.com/fleetbase/fleetbase/discussions)
- [Discord](https://discord.gg/HnTqQ6zAVn)
---
1 change: 1 addition & 0 deletions addon/components/gateway/hub.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
</div>
<div class="ledger-gateway-connections-actions flex min-w-0 flex-wrap items-center gap-2 lg:ml-auto lg:flex-nowrap lg:justify-end">
<Layout::Resource::TabularActions
@registry={{@registry}}
@title="Connected Gateways"
@searchQuery={{@searchQuery}}
@onSearch={{@onSearch}}
Expand Down
11 changes: 10 additions & 1 deletion addon/controllers/accounting/accounts/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export default class AccountingAccountsIndexController extends Controller {
@service tableContext;
@service intl;

@tracked queryParams = ['page', 'limit', 'sort', 'query', 'type', 'status', 'currency'];
@tracked queryParams = this.accountActions.queryParamsFor(['page', 'limit', 'sort', 'query', 'type', 'status', 'currency']);
@tracked page = 1;
@tracked limit = 30;
@tracked sort = 'code';
Expand All @@ -20,11 +20,13 @@ export default class AccountingAccountsIndexController extends Controller {
get actionButtons() {
return [
{
id: 'refresh',
icon: 'refresh',
onClick: this.accountActions.refresh,
helpText: this.intl.t('common.refresh'),
},
{
id: 'create',
text: this.intl.t('common.new'),
type: 'primary',
icon: 'plus',
Expand All @@ -37,6 +39,7 @@ export default class AccountingAccountsIndexController extends Controller {
const selected = this.tableContext.getSelectedRows();
return [
{
id: 'bulk-delete',
label: this.intl.t('common.delete-selected-count', { count: selected.length }),
class: 'text-red-500',
fn: this.accountActions.bulkDelete,
Expand All @@ -47,6 +50,7 @@ export default class AccountingAccountsIndexController extends Controller {
get columns() {
return [
{
id: 'name',
sticky: true,
label: this.intl.t('column.name'),
valuePath: 'name',
Expand All @@ -59,6 +63,7 @@ export default class AccountingAccountsIndexController extends Controller {
filterComponent: 'filter/string',
},
{
id: 'code',
label: this.intl.t('column.code'),
valuePath: 'code',
cellComponent: 'table/cell/anchor',
Expand All @@ -70,6 +75,7 @@ export default class AccountingAccountsIndexController extends Controller {
filterComponent: 'filter/string',
},
{
id: 'type',
label: this.intl.t('column.type'),
valuePath: 'type',
humanize: true,
Expand All @@ -89,6 +95,7 @@ export default class AccountingAccountsIndexController extends Controller {
],
},
{
id: 'currency',
label: this.intl.t('column.currency'),
valuePath: 'currency',
resizable: true,
Expand All @@ -98,13 +105,15 @@ export default class AccountingAccountsIndexController extends Controller {
filterComponent: 'filter/string',
},
{
id: 'balance',
label: this.intl.t('column.balance'),
cellComponent: 'table/cell/currency',
valuePath: 'balance',
resizable: true,
sortable: true,
},
{
id: 'status',
label: this.intl.t('column.status'),
valuePath: 'status',
cellComponent: 'table/cell/status',
Expand Down
14 changes: 13 additions & 1 deletion addon/controllers/accounting/journal/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export default class AccountingJournalIndexController extends Controller {
@service tableContext;
@service intl;

@tracked queryParams = ['page', 'limit', 'sort', 'query', 'type', 'status', 'currency'];
@tracked queryParams = this.journalActions.queryParamsFor(['page', 'limit', 'sort', 'query', 'type', 'status', 'currency']);
@tracked page = 1;
@tracked limit = 30;
@tracked sort = '-entry_date';
Expand All @@ -20,11 +20,13 @@ export default class AccountingJournalIndexController extends Controller {
get actionButtons() {
return [
{
id: 'refresh',
icon: 'refresh',
onClick: this.journalActions.refresh,
helpText: this.intl.t('common.refresh'),
},
{
id: 'create',
text: this.intl.t('common.new'),
type: 'primary',
icon: 'plus',
Expand All @@ -37,6 +39,7 @@ export default class AccountingJournalIndexController extends Controller {
const selected = this.tableContext.getSelectedRows();
return [
{
id: 'bulk-delete',
label: this.intl.t('common.delete-selected-count', { count: selected.length }),
class: 'text-red-500',
fn: this.journalActions.bulkDelete,
Expand All @@ -47,6 +50,7 @@ export default class AccountingJournalIndexController extends Controller {
get columns() {
return [
{
id: 'number',
sticky: true,
label: this.intl.t('column.number'),
valuePath: 'number',
Expand All @@ -56,13 +60,15 @@ export default class AccountingJournalIndexController extends Controller {
sortable: true,
},
{
id: 'entry-date',
label: this.intl.t('column.date'),
valuePath: 'entryDate',
filterParam: 'entry_date',
resizable: true,
sortable: true,
},
{
id: 'type',
label: this.intl.t('column.type'),
valuePath: 'type',
humanize: true,
Expand All @@ -84,6 +90,7 @@ export default class AccountingJournalIndexController extends Controller {
],
},
{
id: 'status',
label: this.intl.t('column.status'),
valuePath: 'status',
cellComponent: 'table/cell/status',
Expand All @@ -101,13 +108,15 @@ export default class AccountingJournalIndexController extends Controller {
],
},
{
id: 'amount',
label: this.intl.t('column.amount'),
valuePath: 'amount',
cellComponent: 'table/cell/currency',
resizable: true,
sortable: true,
},
{
id: 'debit-account-code',
label: this.intl.t('column.debit-account'),
valuePath: 'debit_account.code',
resizable: true,
Expand All @@ -116,6 +125,7 @@ export default class AccountingJournalIndexController extends Controller {
filterComponent: 'filter/string',
},
{
id: 'credit-account-code',
label: this.intl.t('column.credit-account'),
valuePath: 'credit_account.code',
resizable: true,
Expand All @@ -124,12 +134,14 @@ export default class AccountingJournalIndexController extends Controller {
filterComponent: 'filter/string',
},
{
id: 'reference',
label: this.intl.t('column.reference'),
valuePath: 'reference',
resizable: true,
hidden: true,
},
{
id: 'memo',
label: this.intl.t('column.memo'),
valuePath: 'memo',
resizable: true,
Expand Down
11 changes: 10 additions & 1 deletion addon/controllers/accounting/journal/index/details.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,16 @@ export default class AccountingJournalIndexDetailsController extends Controller
get actionButtons() {
const entry = this.model;
if (entry?.is_system_entry) return [];
return [{ label: 'Delete', icon: 'trash', type: 'danger', helpText: 'Permanently delete this journal entry. System entries cannot be deleted.', onClick: this.deleteEntry }];
return [
{
id: 'delete-entry',
label: 'Delete',
icon: 'trash',
type: 'danger',
helpText: 'Permanently delete this journal entry. System entries cannot be deleted.',
onClick: this.deleteEntry,
},
];
}

@action async deleteEntry() {
Expand Down
14 changes: 13 additions & 1 deletion addon/controllers/billing/invoice-templates/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export default class BillingInvoiceTemplatesIndexController extends Controller {
@service tableContext;
@service intl;

@tracked queryParams = ['page', 'limit', 'sort', 'query'];
@tracked queryParams = this.invoiceTemplateActions.queryParamsFor(['page', 'limit', 'sort', 'query']);
@tracked page = 1;
@tracked limit = 30;
@tracked sort = '-created_at';
Expand All @@ -17,11 +17,13 @@ export default class BillingInvoiceTemplatesIndexController extends Controller {
get actionButtons() {
return [
{
id: 'refresh',
icon: 'refresh',
onClick: this.invoiceTemplateActions.refresh,
helpText: this.intl.t('common.refresh'),
},
{
id: 'create',
text: this.intl.t('common.new'),
type: 'primary',
icon: 'plus',
Expand All @@ -34,6 +36,7 @@ export default class BillingInvoiceTemplatesIndexController extends Controller {
const selected = this.tableContext.getSelectedRows();
return [
{
id: 'bulk-delete',
label: this.intl.t('common.delete-selected-count', { count: selected.length }),
class: 'text-red-500',
fn: this.invoiceTemplateActions.bulkDelete,
Expand All @@ -44,6 +47,7 @@ export default class BillingInvoiceTemplatesIndexController extends Controller {
get columns() {
return [
{
id: 'name',
sticky: true,
label: this.intl.t('column.name'),
valuePath: 'name',
Expand All @@ -59,30 +63,35 @@ export default class BillingInvoiceTemplatesIndexController extends Controller {
filterComponent: 'filter/string',
},
{
id: 'description',
label: this.intl.t('column.description'),
valuePath: 'description',
resizable: true,
},
{
id: 'orientation',
label: this.intl.t('column.orientation'),
valuePath: 'orientation',
resizable: true,
sortable: true,
},
{
id: 'is-default',
label: this.intl.t('column.default'),
valuePath: 'is_default',
resizable: true,
sortable: true,
},
{
id: 'created-at',
label: this.intl.t('column.created-at'),
valuePath: 'createdAt',
resizable: true,
sortable: true,
},
// ── Row actions dropdown ─────────────────────────────────────────
{
id: 'row-actions',
label: '',
cellComponent: 'table/cell/dropdown',
ddButtonText: false,
Expand All @@ -99,18 +108,21 @@ export default class BillingInvoiceTemplatesIndexController extends Controller {
searchable: false,
actions: [
{
id: 'edit',
label: this.intl.t('common.edit-resource', { resource: this.intl.t('resource.invoice-template') }),
icon: 'pencil',
fn: this.invoiceTemplateActions.transition.edit,
permission: 'ledger update template',
},
{
id: 'preview',
label: this.intl.t('common.view-resource', { resource: this.intl.t('resource.invoice-template') }),
icon: 'eye',
fn: this.invoiceTemplateActions.preview,
permission: 'ledger view template',
},
{
id: 'delete',
label: this.intl.t('common.delete-resource', { resource: this.intl.t('resource.invoice-template') }),
icon: 'trash',
fn: this.invoiceTemplateActions.delete,
Expand Down
Loading
Loading