Billing plugins
===============

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.

Mini HOWTO
----------

Billing methods can be created as plugins. The plugin file can be freely named
and must be installed under the directory :file:`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
:file:`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. 

Sample implementation
---------------------

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);
        }
    }


