<?php
require_once 'modules/admin/models/ServicePlugin.php';
require_once 'modules/billing/models/BillingType.php';
require_once 'modules/billing/models/Invoice_EventLog.php';
require_once 'modules/billing/models/BillingGateway.php';

/**
* @package Plugins
*/
class PluginInvoicegenerator extends ServicePlugin
{
    protected $featureSet = 'billing';

    function getVariables()
    {
        $variables = array(
            /*T*/'Plugin Name'/*/T*/   => array(
                'type'          => 'hidden',
                'description'   => /*T*/''/*/T*/,
                'value'         => /*T*/'Invoice Generator'/*/T*/,
            ),
            /*T*/'Enabled'/*/T*/       => array(
                'type'          => 'yesno',
                'description'   => /*T*/'When enabled, invoices will automatically be sent to your customers for non-autopayment gateways.'/*/T*/,
                'value'         => '0',
            ),
            /*T*/'Process Quantum Vault Autopayments'/*/T*/       => array(
                'type'          => 'yesno',
                'description'   => /*T*/'When enabled, will try to generate and process the Quantum Vault autopayments when possible. The Quantum Vault invoices will only be generated on the due date, to avoid charging them earlier.'/*/T*/,
                'value'         => '0',
            ),
            /*T*/'Run schedule - Minute'/*/T*/  => array(
                'type'          => 'text',
                'description'   => /*T*/'Enter number, range, list or steps'/*/T*/,
                'value'         => '30',
                'helpid'        => '8',
            ),
            /*T*/'Run schedule - Hour'/*/T*/  => array(
                'type'          => 'text',
                'description'   => /*T*/'Enter number, range, list or steps'/*/T*/,
                'value'         => '*',
            ),
            /*T*/'Run schedule - Day'/*/T*/  => array(
                'type'          => 'text',
                'description'   => /*T*/'Enter number, range, list or steps'/*/T*/,
                'value'         => '*',
            ),
            /*T*/'Run schedule - Month'/*/T*/  => array(
                'type'          => 'text',
                'description'   => /*T*/'Enter number, range, list or steps'/*/T*/,
                'value'         => '*',
            ),
            /*T*/'Run schedule - Day of the week'/*/T*/  => array(
                'type'          => 'text',
                'description'   => /*T*/'Enter number in range 0-6 (0 is Sunday) or a 3 letter shortcut (e.g. sun)'/*/T*/,
                'value'         => '*',
            ),
        );

        return $variables;
    }

    function execute()
    {

        parent::execute();

        $messages = array();
        $numCustomers = 0;

        $billingGateway = new BillingGateway($this->user);

        $query = "SELECT DISTINCT (c.id), c.paymenttype, c.autopayment "
            ."FROM users c, recurringfee r "
            ."LEFT JOIN domains d ON r.appliestoid = d.id "
            ."LEFT JOIN package p ON d.Plan = p.id "            // Added to recognize domains
            ."LEFT JOIN promotion pr ON p.planid = pr.id "      // Added to recognize domains
            ."WHERE c.groupid = 1 "
            ."AND c.status = 1 "
            ."AND r.disablegenerate <> 2 "
            ."AND r.customerid = c.id "
            ."AND r.paymentterm != 0 "
            ."AND (r.appliestoid = 0 "
            ."OR (r.appliestoid <> 0 "
            ."AND d.status IN (".PACKAGE_STATUS_PENDING.", ".PACKAGE_STATUS_ACTIVE.") "
            ."AND (r.billingtypeid NOT IN (".BILLINGTYPE_PACKAGE.", ".BILLINGTYPE_COUPON_DISCOUNT.") "
            ."OR (r.billingtypeid = ".BILLINGTYPE_PACKAGE." "
            ."AND r.recurring = 1)))) "
            ."AND r.paymentterm != 0 "
            ."AND c.autopayment = 0 ";

        if($this->settings->get('plugin_invoicegenerator_Process Quantum Vault Autopayments')){
            $query .= "AND c.paymenttype != 'quantumvault' ";
        }

        if($this->settings->get('Charge Domain Invoice Offset') && $this->settings->get('Charge Domain Invoice Offset') > $this->settings->get('Send Invoice Offset')){
            $query .= "AND ((IFNULL(pr.type, 0) = 3 "
                ."AND (TO_DAYS(r.nextbilldate) - TO_DAYS(NOW()) <=".$this->settings->get('Charge Domain Invoice Offset').")) "
                ."OR( IFNULL(pr.type, 0) != 3 "
                ."AND (TO_DAYS(r.nextbilldate) - TO_DAYS(NOW()) <=".$this->settings->get('Send Invoice Offset')."))) ";
        }else{
            $query .= "AND (TO_DAYS(r.nextbilldate) - TO_DAYS(NOW()) <=".$this->settings->get('Send Invoice Offset').") ";
        }

        $result = $this->db->query($query);

        $chargeAutopayment = false;

        while(list($customerid,$paymenttype,$userautopayment) = $result->fetch()) {

            $returnArray = $billingGateway->processCustomerBilling($customerid, $userautopayment, 0, 0, 0, $userautopayment, $chargeAutopayment);

            if (!isset($returnArray['invoiceIDs'])) {
                $returnArray['invoiceIDs'] = array();
            }

            $numCustomers++;
        }

        if($this->settings->get('plugin_invoicegenerator_Process Quantum Vault Autopayments')){
            $query2 = "SELECT DISTINCT (c.id), c.paymenttype, c.autopayment "
                ."FROM users c, recurringfee r "
                ."LEFT JOIN domains d ON r.appliestoid = d.id "
                ."LEFT JOIN package p ON d.Plan = p.id "            // Added to recognize domains
                ."LEFT JOIN promotion pr ON p.planid = pr.id "      // Added to recognize domains
                ."WHERE c.groupid = 1 "
                ."AND c.paymenttype = 'quantumvault' "
                ."AND c.status = 1 "
                ."AND r.disablegenerate <> 2 "
                ."AND r.customerid = c.id "
                ."AND r.paymentterm != 0 "
                ."AND (r.appliestoid = 0 "
                ."OR (r.appliestoid <> 0 "
                ."AND d.status IN (".PACKAGE_STATUS_PENDING.", ".PACKAGE_STATUS_ACTIVE.") "
                ."AND (r.billingtypeid NOT IN (".BILLINGTYPE_PACKAGE.", ".BILLINGTYPE_COUPON_DISCOUNT.") "
                ."OR (r.billingtypeid = ".BILLINGTYPE_PACKAGE." "
                ."AND r.recurring = 1)))) "
                ."AND r.paymentterm != 0 "
                ."AND (TO_DAYS(r.nextbilldate) - TO_DAYS(NOW()) <= 0 ) ";

            $result2 = $this->db->query($query2);

            $chargeAutopayment = true;

            while(list($customerid,$paymenttype,$userautopayment) = $result2->fetch()) {

                $returnArray = $billingGateway->processCustomerBilling($customerid, $userautopayment, 0, 0, 0, $userautopayment, $chargeAutopayment);

                if (!isset($returnArray['invoiceIDs'])) {
                    $returnArray['invoiceIDs'] = array();
                }

                $numCustomers++;
            }
        }

        $billingGateway->reportInvalidRecurringFees();

        $this->settings->updateSetting("LastDateGenerateInvoices", mktime());

        array_unshift($messages, "$numCustomers customer(s) were invoiced");
        return $messages;
    }

    /*
    To show the prices for the pendingItems it is almost to do all the process required to generate the invoices.
    We have many things to take in count like if domain or package prices, if override, if univoiced items tied to next invoices, taxes, etc.
    It is basically doing all what the functions processCustomerBilling, generateOutstandingBillableWork and _addNonRecurringCharges from BillingGateway class,
    and recalculateInvoice from Invoice class do, but requiring to not generate anything in the database.
    That is really something useless.
    */
    function pendingItems()
    {
        include_once 'modules/clients/models/user.php';

        $returnArray = array();
        $returnArray['data'] = array();
        // Select all customers that have an invoice that needs generation
        $query = "SELECT DISTINCT c.id, UNIX_TIMESTAMP(r.nextbilldate) "
            ."FROM users c, recurringfee r "
            ."LEFT JOIN domains d ON r.appliestoid = d.id "
            ."LEFT JOIN package p ON d.Plan = p.id "            // Added to recognize domains
            ."LEFT JOIN promotion pr ON p.planid = pr.id "      // Added to recognize domains
            ."WHERE c.groupid = 1 "
            ."AND c.status = 1 "
            ."AND r.disablegenerate <> 2 "
            ."AND r.customerid = c.id "
            ."AND r.paymentterm != 0 "
            ."AND (r.appliestoid = 0 "
            ."OR (r.appliestoid <> 0 "
            ."AND d.status IN (".PACKAGE_STATUS_PENDING.", ".PACKAGE_STATUS_ACTIVE.") "
            ."AND (r.billingtypeid NOT IN (".BILLINGTYPE_PACKAGE.", ".BILLINGTYPE_COUPON_DISCOUNT.") "
            ."OR (r.billingtypeid = ".BILLINGTYPE_PACKAGE." "
            ."AND r.recurring = 1)))) "
            ."AND r.paymentterm != 0 "
            ."AND c.autopayment = 0 ";

        if($this->settings->get('Charge Domain Invoice Offset') && $this->settings->get('Charge Domain Invoice Offset') > $this->settings->get('Send Invoice Offset')){
            $query .= "AND ((IFNULL(pr.type, 0) = 3 "
                ."AND (TO_DAYS(r.nextbilldate) - TO_DAYS(NOW()) <=".$this->settings->get('Charge Domain Invoice Offset').")) "
                ."OR( IFNULL(pr.type, 0) != 3 "
                ."AND (TO_DAYS(r.nextbilldate) - TO_DAYS(NOW()) <=".$this->settings->get('Send Invoice Offset')."))) ";
        }else{
            $query .= "AND (TO_DAYS(r.nextbilldate) - TO_DAYS(NOW()) <=".$this->settings->get('Send Invoice Offset').") ";
        }

        $query .= "ORDER BY UNIX_TIMESTAMP(r.nextbilldate) ASC ";

        $result = $this->db->query($query);

        // Loop through the customers
        while ($row = $result->fetch()) {
            $user = new User($row['id']);

            $tmpInfo = array();
            $tmpInfo['customerid'] = $row['id'];
            $tmpInfo['customer'] = $user->getFullName();
            $tmpInfo['due'] = date($this->settings->get('Date Format'),$row['UNIX_TIMESTAMP(r.nextbilldate)']);
            $returnArray['data'][] = $tmpInfo;
        }

        $returnArray['totalcount'] = count($returnArray['data']);
        return $returnArray;
    }

    function output() { }

    function dashboard()
    {
        $query = "SELECT COUNT(DISTINCT (c.id))  AS customers "
            ."FROM users c, recurringfee r "
            ."LEFT JOIN domains d ON r.appliestoid = d.id "
            ."LEFT JOIN package p ON d.Plan = p.id "            // Added to recognize domains
            ."LEFT JOIN promotion pr ON p.planid = pr.id "      // Added to recognize domains
            ."WHERE c.groupid = 1 "
            ."AND c.status = 1 "
            ."AND r.disablegenerate <> 2 "
            ."AND r.customerid = c.id "
            ."AND r.paymentterm != 0 "
            ."AND (r.appliestoid = 0 "
            ."OR (r.appliestoid <> 0 "
            ."AND d.status IN (".PACKAGE_STATUS_PENDING.", ".PACKAGE_STATUS_ACTIVE.") "
            ."AND (r.billingtypeid NOT IN (".BILLINGTYPE_PACKAGE.", ".BILLINGTYPE_COUPON_DISCOUNT.") "
            ."OR (r.billingtypeid = ".BILLINGTYPE_PACKAGE." "
            ."AND r.recurring = 1)))) "
            ."AND r.paymentterm != 0 "
            ."AND c.autopayment = 0 ";

        if($this->settings->get('Charge Domain Invoice Offset') && $this->settings->get('Charge Domain Invoice Offset') > $this->settings->get('Send Invoice Offset')){
            $query .= "AND ((IFNULL(pr.type, 0) = 3 "
                ."AND (TO_DAYS(r.nextbilldate) - TO_DAYS(NOW()) <=".$this->settings->get('Charge Domain Invoice Offset').")) "
                ."OR( IFNULL(pr.type, 0) != 3 "
                ."AND (TO_DAYS(r.nextbilldate) - TO_DAYS(NOW()) <=".$this->settings->get('Send Invoice Offset')."))) ";
        }else{
            $query .= "AND (TO_DAYS(r.nextbilldate) - TO_DAYS(NOW()) <=".$this->settings->get('Send Invoice Offset').") ";
        }

        $result = $this->db->query($query);
        $row = $result->fetch();
        if (!$row) {
            $row['customers'] = 0;
        }
        return $this->user->lang('Number of customers to be billed: %d', $row['customers']);
    }
}
?>
