Der Router validiert nur die Route und delegiert. Besonders wichtig: Auch der eingebettete [modul=myInvoices]-Aufruf geht durch dieselbe run()-Methode. Es existiert kein Sonderzugriff auf die Positions-DD.
Der vollständige Quelltext wird direkt eingebunden. Er ist damit die verbindliche Referenz für aktive FD-Meldungen, Spaltenlabels, Confirmtexte, Callback-Defaults, Summen und Transaktionen:
<?php
class myInvoicesService
{
private const INVOICE_DD = 'myInvoices|invoice';
private const ITEM_DD = 'myInvoices|invoiceItem';
private const FORM_FD = 'myInvoices|invoice-form';
private const REPORT_FD = 'myInvoices|rpt-invoice-selection';
private int $invoicePageTotalCents = 0;
private int $itemTotalCents = 0;
private function euro(int $cents): string
{
return number_format($cents / 100, 2, ',', '.') . ' EUR';
}
private function url(string $run, array $params = array()): string
{
$url =
'?dbx_modul=myInvoices&dbx_run1=' . rawurlencode($run);
foreach ($params as $key =>
$value)
{
$url .=
'&' . rawurlencode((
string)$key)
.
'=' . rawurlencode((
string)
$value);
}
}
public function form(): string
{
$ridValue =
dbx()->get_modul_var(
'rid',
'new',
'parameter|max=24'
);
$rid = $ridValue === 'new' ? 0 : (int)$ridValue;
$isNew = $rid <= 0;
$form =
dbx()->get_system_obj(
'dbxForm');
$form->init(
'invoice-form',
'myInvoices|invoice-form');
$form->_dd = self::INVOICE_DD;
$form->_fd = self::FORM_FD;
$form->load_fd_messages();
$data = $isNew
? array('status' => 'draft')
:
dbx()->get_system_obj(
'dbxDB')->select1(
self::INVOICE_DD,
array('id' => $rid)
);
if (!$isNew && (int)($data['id'] ?? 0) <= 0) {
return dbx()->get_system_obj(
'dbxTPL')->get_tpl(
'dbx|alert-warning',
array(
'msg' =>
$form->get_fd_message(
'not_found'))
);
}
$form->_data = is_array($data) ? $data : array();
$form->_action = $this->url(
'form', array(
'rid' => $isNew ? 'new' : $rid,
));
$form->_msg_info =
$form->get_fd_message(
'form_info');
'form_title',
$isNew ? 'form_title_new' : 'form_title_edit'
)
);
'bar_title',
$form->get_fd_message(
'help_title')
);
$form->add_rep(
'list_url', $this->url(
'report'));
self::INVOICE_DD,
$isNew ? 'new' : $rid
);
$savedRid = (int)
$form->_rid;
if ($ok && $isNew && $savedRid > 0) {
$form->_action = $this->url(
'form',
array('rid' => $savedRid)
);
'form_title',
$form->get_fd_message(
'form_title_edit')
);
}
} else {
'validation_error'
);
}
}
}
{
if (!is_array($record)) {
return $record;
}
$id = (int)($record['id'] ?? 0);
$totalCents = (int)round(
(float)($record['total_gross'] ?? 0) * 100
);
$this->invoicePageTotalCents += $totalCents;
'invoice_report_total',
$this->euro($this->invoicePageTotalCents)
);
$record
['action'] =
dbx()->get_system_obj(
'dbxTPL')->get_tpl(
'myInvoices|invoice-row-action',
array(
'edit_url' => $this->url('form', array('rid' => $id)),
$this->url('delete', array('rid' => $id))
),
'delete_title' =>
$report->get_fd_message(
'delete_title'
),
'delete_question' =>
$report->format_fd_message(
'delete_question',
array('id' => $id)
),
'delete_hint' =>
$report->get_fd_message(
'delete_hint'
),
)
);
$status = (string)($record['status'] ?? '');
if ($status !== '') {
$record
['status'] =
$report->get_fd_message(
'status_' . $status,
$status
);
}
$record['total_gross'] = $this->euro($totalCents);
$record['positions_call'] =
'[modul=myInvoices]dbx_run1=positions&invoice_id='
. $id
. '[/modul]';
return $record;
}
string $success = '',
string $error = ''
): string {
$db =
dbx()->get_system_obj(
'dbxDB');
'invoice-report',
'myInvoices|invoice-report'
);
$report->_action = $this->url(
'report');
$report->_create_row_select =
false;
$report->_create_row_delete =
false;
$report->add_rep(
'install_url', $this->url(
'install'));
$report->create_selection_fields(self::REPORT_FD);
'bar_title',
$report->get_fd_message(
'report_title')
);
$report->_msg_success = $success ===
''
? ''
:
$report->get_fd_message($success, $success);
$report->_msg_error = $error ===
''
? ''
:
$report->get_fd_message($error, $error);
$this->invoicePageTotalCents = 0;
}
$search = trim((
string)
$report->get_fld_val(
'dbx_rwhere',
'',
'sqlsearch|max=64'
));
$status = (string)
$report->get_fld_val(
'dbx_rstatus',
'all',
'parameter|max=24'
);
$pageSize = max(10, min(50, (
int)
$report->get_fld_val(
'dbx_rrows',
20,
'int'
)));
$position = max(0, (
int)
$report->get_fld_val(
'dbx_rpos',
0,
'int'
));
$sort = (string)
$report->get_fld_val(
'dbx_rsort',
'invoice_date',
'parameter'
);
$direction = strtoupper((
string)
$report->get_fld_val(
'dbx_rdesc',
'DESC',
'parameter'
));
$allowedSort = array(
'invoice_no',
'invoice_date',
'customer',
'status',
'total_gross',
);
if (!in_array($sort, $allowedSort, true)) {
$sort = 'invoice_date';
}
if (!in_array($direction, array('ASC', 'DESC'), true)) {
$direction = 'DESC';
}
$where = array();
if (in_array($status, array('draft', 'open', 'paid'), true)) {
$where['status'] = $status;
}
if ($search !== '') {
$where['search'] = array(
'value' => $search,
'like' => array('invoice_no', 'customer'),
'mode' => 'contains',
);
}
$columns = array(
'id',
'invoice_no',
'invoice_date',
'customer',
'status',
'total_gross',
);
self::INVOICE_DD,
$where,
$columns,
$sort,
$direction,
'',
$pageSize,
$position
);
return dbx()->get_system_obj(
'dbxTPL')->get_tpl(
'myInvoices|install-required',
array('install_url' => $this->url('install'))
);
}
'invoice_no' =>
$report->get_fd_message(
'column_invoice_no'),
'invoice_date' =>
$report->get_fd_message(
'column_invoice_date'
),
'customer' =>
$report->get_fd_message(
'column_customer'),
'status' =>
$report->get_fd_message(
'column_status'),
'action' =>
$report->get_fd_message(
'column_action'),
'total_gross' =>
$report->get_fd_message(
'column_total'),
);
'invoice_date' => 'php-date-usr',
'action' => 'html',
);
$report->_count_all =
$db->count(self::INVOICE_DD);
$report->_rcount =
$db->count(self::INVOICE_DD, $where);
}
public function invoice_items_report_next_record(
$report, $record)
{
if (!is_array($record)) {
return $record;
}
$quantity = (float)($record['quantity'] ?? 0);
$unitPrice = (float)($record['unit_price'] ?? 0);
$sumCents = (int)round($quantity * $unitPrice * 100);
$this->itemTotalCents += $sumCents;
'report_total',
$this->euro($this->itemTotalCents)
);
$record['quantity'] = number_format($quantity, 2, ',', '.');
$record['unit_price'] = $this->euro(
(int)round($unitPrice * 100)
);
$record['sum'] = $this->euro($sumCents);
return $record;
}
public function positions(): string
{
$invoiceId = (int)
dbx()->get_modul_var(
'invoice_id',
0,
'int'
);
if ($invoiceId <= 0) {
return '';
}
$db =
dbx()->get_system_obj(
'dbxDB');
self::INVOICE_DD,
array('id' => $invoiceId),
array('id', 'invoice_no')
);
if ((int)($invoice['id'] ?? 0) <= 0) {
return '';
}
self::ITEM_DD,
array('invoice_id' => $invoiceId),
array(
'position_no',
'article_no',
'description',
'quantity',
'unit_price',
),
'position_no',
'ASC'
);
'invoice-items-report',
'myInvoices|invoice-items-report'
);
$report->_create_row_select =
false;
$report->_create_row_delete =
false;
'invoice_no',
(string)$invoice['invoice_no']
);
$this->itemTotalCents = 0;
'position_no' =>
$report->get_fd_message(
'column_position_no'
),
'article_no' =>
$report->get_fd_message(
'column_article_no'
),
'description' =>
$report->get_fd_message(
'column_article'),
'quantity' =>
$report->get_fd_message(
'column_quantity'),
'unit_price' =>
$report->get_fd_message(
'column_unit_price'
),
'sum' =>
$report->get_fd_message(
'column_total'),
);
}
public function delete(): string
{
$rid = (int)
dbx()->get_modul_var(
'rid', 0,
'int');
if ($rid <= 0) {
return $this->report(
'',
'delete_invalid'
);
}
$db =
dbx()->get_system_obj(
'dbxDB');
if (
$db->begin(self::INVOICE_DD) !== 1)
{
return $this->report(
'',
'transaction_error'
);
}
$itemsDeleted =
$db->delete(
self::ITEM_DD,
array('invoice_id' => $rid)
);
$invoiceDeleted = in_array($itemsDeleted, array(0, 1), true)
?
$db->delete(self::INVOICE_DD, array(
'id' => $rid))
: -2;
if ($invoiceDeleted !== 1
||
$db->commit(self::INVOICE_DD) !== 1
) {
$db->rollback(self::INVOICE_DD);
return $this->report(
'',
'delete_error'
);
}
return $this->report('delete_success');
}
public function installation(): string
{
$form =
dbx()->get_system_obj(
'dbxForm');
'myInvoices-install',
'myInvoices|invoice-install'
);
$form->_fd =
'myInvoices|invoice-install';
$form->load_fd_messages();
'bar_title',
$form->get_fd_message(
'bar_title')
);
return dbx()->get_system_obj(
'dbxTPL')->get_tpl(
'dbx|alert-warning',
array(
'msg' =>
$form->get_fd_message(
'admin_required'))
);
}
$form->_action = $this->url(
'install');
$form->_msg_info =
$form->get_fd_message(
'install_info');
$form->_data = array_merge(
array('install_demo' => 1)
);
$form->add_rep(
'report_url', $this->url(
'report'));
'install_demo',
'dbx|hidden',
rules: 'int',
dd: ''
);
'install_invalid'
);
} else {
'myInvoicesFixtures',
'myInvoices'
);
if ((
int)(
$result['ok'] ?? 0) === 1)
{
'install_success',
array(
'invoices' => (
int)
$result['created_invoices'],
'items' => (
int)
$result['created_items'],
'existing' => (
int)
$result['existing_invoices'],
)
);
} else {
'error',
'myInvoices',
'install',
'Installation failed',
);
'install_failed'
);
}
}
}
}
}
?>
invoice_report_next_record($report, $record)
Bereitet eine Rechnungszeile unmittelbar vor dem Rendern auf.
report(string $success='', string $error='')
Rendert den paginierten Rechnungsreport.
form()
Rendert und verarbeitet das Rechnungskopfformular.
if((string)($formActionPolicy['action'] ?? '') !=='dbxAction.save'||!dbx() ->check_action_token((string)($formActionPolicy['scope'] ?? ''),(string)($formActionRoute['params']['dbx_token'] ?? ''))) $report
action_url(string $url, string $action='', array $bindings=array())
Tokenisiert eine automatisch erkannte zustandsaendernde Route.
dbx()
Liefert die zentrale dbxapp-API als Singleton.
can($access_groups='', $user_groups='')
Prueft Gruppenrechte gegen den aktuellen oder uebergebenen Benutzer.
Die Callbackmethoden sind echte Aufbereitungslogik. Sie sind ausdrücklich keine Modulmethoden, die nur dbx()-Funktionen weiterreichen.