phpaga gives you the ability to write your own custom billing plugins which decide how totals and subtotals are calculated when you generate PDF bills to send to your clients. phpaga comes pre-installed with a few user-contributed plugins to calculate taxes for various countries, and a very simple plugin, which returns the total, not including any taxes. You can use these files as a reference implementation of what a billing plugin should look like. If you happen to write your own generalized plugin feel free to contribute it back.
Billing methods can be created as plugins. The plugin file can be freely named and must be installed under the directory plugins/billing/ The plugin consists of a class that extends the base class BillingDetails. It defines the static member $plugin_info and implements at least the two abstract functions get_filename() and calculate().
The member $plugin_info is an array that contains the following information about the plugin: Autor name and email, a short description, and the country code where this plugin is applicable.
public static $plugin_info = array(
'author' => 'Florian Lanthaler <florian@phpaga.net>',
'description' => 'Liberi professionisti / ditte individuali',
'country' => 'IT'
);
The function get_filename() must be implemented as follows:
public static function get_filename() { return basename(__FILE__); }
The function calculate() is the core of the plugin and handles the calculation of the bill’s details (for both invoices and quotations). It can count on the availability of the following class members:
float $this->startsum # The startsum from which to calculate the bill
int $this->curr_id # ID of the currency to be used
string $this->curr_name # Name of the currency to be used
float $this->expensesum # Amount of expenses (optional)
float $this->paymentsum # Sum of payments (optional)
float $this->feesum # Sum of late fees (optional); developed for notaxes
# plugin, so may require new code to account for taxes
# that accrue in total amount due i.e. endsum
The following members should be calculated or populated within this function:
float $this->endsum # The full sum that is to be paid
float $this->balance_due # The balance due
array $this->details # Array containing the full calculation with
# description and amounts
Details are added to the member details with the methods add_detail(), add_fee_detail(), and add_payment_detail(). The method add_separator() adds a separator (line).
Please refer to the sample files shipped with phpaga (to be found under plugins/billing/); you can use one of them as a base for your personalized billing method.
This should provide a standard interface with which users can create their own plugins that create their bills exactly the way they (or their legislation) needs them.
As of phpaga 0.3, billing method plugins can be installed/uninstalled from within phpaga. The files are not physically installed or removed, but the database entries can be managed from within the administrator’s interface.
After upgrading from earlier releases to phpaga 0.6 - and, generally speaking, each time a new billing plugin is installed - you must open the billing plugin management interface at Administration, Billing plugins. This will try to automatically recognize the migrated billing plugins, and allow to you manage all available billing plugins.
The following is an example of a billing plugin:
class ItaLiberoprofEuro extends BillingDetails {
public static $plugin_info = array(
'author' => 'Florian Lanthaler <florian@phpaga.net>',
'description' => 'Liberi professionisti / ditte individuali',
'country' => 'IT'
);
public static function get_filename() { return basename(__FILE__); }
public function calculate() {
$inps = 0;
$imponibile = 0;
$iva = 0;
$irpef = 0;
/* 4% INPS/NISF (National health care) */
$inps = sprintf("%.2f", $this->startsum * 0.04);
/* Imponibile (Taxable base) */
$imponibile = sprintf("%.2f", $this->startsum + $inps);
/* IVA 20 % (VAT) */
$iva = sprintf("%.2f", $imponibile * 0.2);
/* IRPEF 20 % (Regional tax) */
$irpef = sprintf("%.2f", $imponibile * 0.2);
/* End sum without expenses*/
$preendsum = sprintf("%.2f", $imponibile + $iva - $irpef);
/* End sum */
$this->endsum = $preendsum + $this->expensesum;
$this->add_detail("Competenze", $this->startsum);
$this->add_detail("Rivalsa contributo INPS 4% Art. 4 DL 28.3.96 n 166", $inps);
$this->add_separator();
$this->add_detail("Totale imponibile", $imponibile);
$this->add_detail("IVA 20%", $iva);
$this->add_separator();
$this->add_detail("Totale fattura", sprintf("%.2f", $imponibile + $iva));
$this->add_detail("- Ritenuta d'acconto IRPEF 20%", $irpef * -1);
$this->add_separator();
if (is_numeric($this->expensesum) && ($this->expensesum > 0)) {
$this->add_detail("Somma parziale", $preendsum);
$this->add_detail("+ Spese rimborsabili", $this->expensesum);
$this->add_separator();
}
$sep = false;
/* Late fees */
if (is_numeric($this->feesum) &&($this->feesum > 0)) {
$sep = true;
$this->add_fee_detail(_("+ Mora"), $this->feesum);
}
/* Payments */
if (is_numeric($this->paymentsum) &&($this->paymentsum > 0)) {
$sep = true;
$this->add_payment_detail(_("- Pagamenti"), $this->paymentsum);
}
if ($sep)
$this->add_separator();
/* Balance due */
$this->balance_due = $this->endsum - $this->paymentsum + $this->feesum;
$this->add_detail("Netto a pagare", $this->balance_due);
}
}