<?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*/'Autopayments'/*/T*/       => array(
                'type'          => 'yesno',
                'description'   => /*T*/'When enabled, will also include your customers with 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()
    {
        $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 "
            
            // Added to recognize domains
            ."LEFT JOIN package p ON d.Plan = p.id "
            ."LEFT JOIN promotion pr ON p.planid = pr.id "
            // Added to recognize domains
            
            ."WHERE c.groupid = 1 ";
        
        if(!$this->settings->get('plugin_invoicegenerator_Autopayments')){
            $query .= "AND c.autopayment = 0 ";
        }
        if($this->settings->get('plugin_invoicegenerator_Process Quantum Vault Autopayments')){
            $query .= "AND c.paymenttype != 'quantumvault' ";
        }
        
        $query .= "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 ";
        
        if($this->settings->get('Send Domain Invoice Offset')){
            $query .= "AND ((IFNULL(pr.type, 0) = 3 "
                ."AND (TO_DAYS(r.nextbilldate) - TO_DAYS(NOW()) <=".$this->settings->get('Send 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 "
                
                // Added to recognize domains
                ."LEFT JOIN package p ON d.Plan = p.id "
                ."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 "
            
            // Added to recognize domains
            ."LEFT JOIN package p ON d.Plan = p.id "
            ."LEFT JOIN promotion pr ON p.planid = pr.id "
            // Added to recognize domains
            
            ."WHERE c.groupid = 1 ";
        
        if(!$this->settings->get('plugin_invoicegenerator_Autopayments')){
            $query .= "AND c.autopayment = 0 ";
        }
        
        $query .= "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 ";
        
        if($this->settings->get('Send Domain Invoice Offset')){
            $query .= "AND ((IFNULL(pr.type, 0) = 3 "
                ."AND (TO_DAYS(r.nextbilldate) - TO_DAYS(NOW()) <=".$this->settings->get('Send 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 "
            
            // Added to recognize domains
            ."LEFT JOIN package p ON d.Plan = p.id "
            ."LEFT JOIN promotion pr ON p.planid = pr.id "
            // Added to recognize domains
            
            ."WHERE c.groupid = 1 ";
        
        if(!$this->settings->get('plugin_invoicegenerator_Autopayments')){
            $query .= "AND c.autopayment = 0 ";
        }
        
        $query .= "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 ";
        
        if($this->settings->get('Send Domain Invoice Offset')){
            $query .= "AND ((IFNULL(pr.type, 0) = 3 "
                ."AND (TO_DAYS(r.nextbilldate) - TO_DAYS(NOW()) <=".$this->settings->get('Send 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']);
    }
}
?>
