/**
  * Generate plot data using the specified type
  * @param $result
  * @param $graphtype
  * @return mixed
  */
 private function getGraph($result, $graphtype)
 {
     // validate input
     $jsonval = new JsonValidate($this->data, '{"stime":1, "etime":1, "interval":1}');
     if (($errors = $jsonval->validate()) !== true) {
         $result['error'] = $errors;
         return $result;
     }
     // Initialize the stats object
     $stats = new WposAdminStats(null);
     $graph = [];
     $serieslist = [];
     $interval = isset($this->data->interval) ? $this->data->interval : 86400000;
     // default interval is one day
     $curstime = isset($this->data->stime) ? $this->data->stime : strtotime('-1 week') * 1000;
     $curetime = intval($curstime) + intval($interval);
     $stopetime = isset($this->data->etime) ? $this->data->etime : time() * 1000;
     $tempstats = null;
     while ($curstime <= $stopetime) {
         $stats->setRange($curstime, $curetime);
         switch ($graphtype) {
             case 1:
                 $tempstats = $stats->getOverviewStats($result);
                 break;
             case 2:
                 $tempstats = $stats->getCountTakingsStats($result);
                 break;
             case 3:
                 $tempstats = $stats->getDeviceBreakdownStats($result);
                 break;
             case 4:
                 $tempstats = $stats->getDeviceBreakdownStats($result, 'location');
                 break;
         }
         if ($tempstats['error'] == "OK") {
             // put into series list
             foreach ($tempstats['data'] as $key => $value) {
                 $serieslist[$key] = $key;
             }
             // put into array
             $graph[$curstime] = $tempstats['data'];
         } else {
             $result['error'] .= $tempstats['error'];
             break;
         }
         // move to the next segment
         $curstime += $interval;
         $curetime += $interval;
     }
     // if it's not the general graph we need to loop through and fill in null data
     if ($graphtype != 1) {
         $defaultobj = new stdClass();
         $defaultobj->balance = 0;
         // loop through each series value and add 0 values for null data
         foreach ($graph as $ykey => $yvals) {
             //$result['error'].="\n".json_encode($yvals);
             foreach ($serieslist as $value) {
                 // use serieslist to spot null values
                 if ($yvals[$value] == null || empty($yvals)) {
                     // check if series key exists in current timeset
                     //$result['error'].="\nInserting default";
                     $yvals[$value] = $defaultobj;
                     $graph[$ykey] = $yvals;
                 }
             }
         }
     }
     $result['data'] = $graph;
     return $result;
 }
 private static function getXeroXml($stime, $etime)
 {
     $Wstat = new WposAdminStats();
     $Wstat->setRange($stime, $etime);
     $Wstat->setType('sale');
     $taxStats = $Wstat->getTaxStats([]);
     if (!$taxStats['data']) {
         return "Could not generate export item data: " . $taxStats['error'];
     }
     $payStats = $Wstat->getCountTakingsStats([]);
     if (!$payStats['data']) {
         return "Could not generate export payment data " . $taxStats['error'];
     }
     // get account map
     $accnmap = WposAdminSettings::getSettingsObject("accounting")->xeroaccnmap;
     if ($accnmap == '') {
         return "Xero integration setup not completed, please save account mappings first.";
     }
     // Setup invoice xml
     $invoice = new SimpleXMLElement("<Invoice/>");
     $date = date("Y-m-d", round($etime / 1000));
     $invoice->addChild("Type", "ACCREC");
     $invoice->addChild("Date", $date);
     $invoice->addChild("DueDate", $date);
     $invoice->addChild("InvoiceNumber", "POS-" . str_replace('-', '', $date));
     $invoice->addChild("Reference", "POS Sales");
     $invoice->addChild("LineAmountTypes", "Inclusive");
     $invoice->addChild("Status", "AUTHORISED");
     $contact = $invoice->addChild("Contact");
     $contact->addChild("Name", "POS Sales");
     // Setup refunds xml
     $cnote = new SimpleXMLElement("<CreditNote/>");
     $cnote->addChild("Type", "ACCRECCREDIT");
     $cnote->addChild("Date", $date);
     $cnote->addChild("CreditNoteNumber", "POSR-" . str_replace('-', '', $date));
     $cnote->addChild("Reference", "POS Refunds");
     $cnote->addChild("LineAmountTypes", "Inclusive");
     $cnote->addChild("Status", "AUTHORISED");
     $ccontact = $cnote->addChild("Contact");
     $ccontact->addChild("Name", "POS Sales");
     // Generate line items for each payment method and add types
     $lineItems = $invoice->addChild("LineItems");
     $clineItems = $cnote->addChild("LineItems");
     foreach ($taxStats['data'] as $key => $data) {
         if ($key != 0) {
             $taxType = isset($accnmap->{"tax-" . $key}) ? $accnmap->{"tax-" . $key} : '';
             // Add sales
             $accountCode = isset($accnmap->sales) ? $accnmap->sales : '';
             if ($data->saletotal > 0) {
                 $lineItem = $lineItems->addChild("LineItem");
                 $lineItem->addChild("Quantity", 1);
                 $lineItem->addChild("Description", $data->name . " Sales");
                 $lineItem->addChild("UnitAmount", str_replace(',', '', $data->saletotal + $data->saletax));
                 $lineItem->addChild("AccountCode", $accountCode);
                 $lineItem->addChild("TaxType", $taxType);
             }
             // Add refunds
             if ($data->refundtotal > 0) {
                 //$accountCode = (isset($accnmap->refunds)?$accnmap->refunds:'');
                 $clineItem = $clineItems->addChild("LineItem");
                 $clineItem->addChild("Quantity", 1);
                 $clineItem->addChild("Description", $data->name . " Refunds");
                 $clineItem->addChild("UnitAmount", str_replace(',', '', $data->refundtotal + $data->refundtax));
                 $clineItem->addChild("AccountCode", $accountCode);
                 $clineItem->addChild("TaxType", $taxType);
             }
         } else {
             if ($data->total != 0) {
                 // add cash rounding
                 $taxType = isset($accnmap->{"tax-" . $key}) ? $accnmap->{"tax-" . $key} : '';
                 $accountCode = isset($accnmap->sales) ? $accnmap->sales : '';
                 $clineItem = $lineItems->addChild("LineItem");
                 $clineItem->addChild("Quantity", 1);
                 $clineItem->addChild("Description", "Cash Rounding");
                 $clineItem->addChild("UnitAmount", str_replace(',', '', $data->total));
                 $clineItem->addChild("AccountCode", $accountCode);
                 $clineItem->addChild("TaxType", $taxType);
             }
         }
     }
     // Setup payments xml
     $payments = new SimpleXMLElement("<Payments/>");
     foreach ($payStats['data'] as $key => $data) {
         if ($key != 'Unaccounted') {
             if ($data->saletotal > 0) {
                 // Add Payment
                 $payment = $payments->addChild("Payment");
                 $payment->addChild("Date", $date);
                 $payment->addChild("Reference", ucfirst($key) . " POS Payments");
                 $payment->addChild("Amount", str_replace(',', '', $data->saletotal));
                 $pinv = $payment->addChild("Invoice");
                 $pinv->addChild("InvoiceNumber", "POS-" . str_replace('-', '', $date));
                 if ($key == "eftpos" || $key == "credit") {
                     $key = "card";
                 }
                 $accountCode = isset($accnmap->{"pay-" . $key}) ? $accnmap->{"pay-" . $key} : '';
                 $paccn = $payment->addChild("Account");
                 $paccn->addChild("Code", $accountCode);
             }
             if ($data->refundtotal > 0) {
                 // Add Payment
                 $payment = $payments->addChild("Payment");
                 $payment->addChild("Date", $date);
                 $payment->addChild("Reference", ucfirst($key) . " POS Refunds");
                 $payment->addChild("Amount", str_replace(',', '', $data->refundtotal));
                 $pinv = $payment->addChild("CreditNote");
                 $pinv->addChild("CreditNoteNumber", "POSR-" . str_replace('-', '', $date));
                 if ($key == "eftpos" || $key == "credit" || $key == "tyro") {
                     $key = "card";
                 }
                 $accountCode = isset($accnmap->{"pay-" . $key}) ? $accnmap->{"pay-" . $key} : '';
                 $paccn = $payment->addChild("Account");
                 $paccn->addChild("Code", $accountCode);
             }
         }
     }
     return ['invoice' => $invoice, 'creditnote' => $clineItems->count() > 0 ? $cnote : false, 'payments' => $payments];
 }