appointments.php
3 days ago
employees.php
3 days ago
index.html
3 days ago
packages.php
3 days ago
subscriptions.php
3 days ago
appointments.php
302 lines
| 1 | <?php |
| 2 | /** |
| 3 | * @package VikAppointments |
| 4 | * @subpackage core |
| 5 | * @author E4J s.r.l. |
| 6 | * @copyright Copyright (C) 2021 E4J s.r.l. All Rights Reserved. |
| 7 | * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL |
| 8 | * @link https://vikwp.com |
| 9 | */ |
| 10 | |
| 11 | // No direct access |
| 12 | defined('ABSPATH') or die('No script kiddies please!'); |
| 13 | |
| 14 | /** |
| 15 | * Class used to generate the invoices of the appointments. |
| 16 | * |
| 17 | * @since 1.6 |
| 18 | */ |
| 19 | class VAPInvoiceAppointments extends VAPInvoice |
| 20 | { |
| 21 | /** |
| 22 | * @override |
| 23 | * Returns the destination path of the invoice. |
| 24 | * |
| 25 | * @return string The invoice path. |
| 26 | */ |
| 27 | protected function getInvoicePath() |
| 28 | { |
| 29 | $parts = array( |
| 30 | $this->getInvoiceFolderPath(), |
| 31 | $this->order->id . '-' . $this->order->sid . '.pdf', |
| 32 | ); |
| 33 | |
| 34 | return implode(DIRECTORY_SEPARATOR, $parts); |
| 35 | } |
| 36 | |
| 37 | /** |
| 38 | * @override |
| 39 | * Returns the page template that will be used to |
| 40 | * generate the invoice. |
| 41 | * |
| 42 | * @return string The base HTML. |
| 43 | */ |
| 44 | protected function getPageTemplate() |
| 45 | { |
| 46 | $data = array( |
| 47 | 'order' => $this->order, |
| 48 | 'breakdown' => $this->getBreakdown(), |
| 49 | 'usetaxbd' => VAPFactory::getConfig()->getBool('usetaxbd', false), |
| 50 | ); |
| 51 | |
| 52 | // create layout file (always read from the site section of VikAppointments) |
| 53 | $layout = new JLayoutFile('templates.invoice.appointment', null, [ |
| 54 | 'component' => 'com_vikappointments', |
| 55 | 'client' => 'site', |
| 56 | ]); |
| 57 | |
| 58 | return $layout->render($data); |
| 59 | } |
| 60 | |
| 61 | /** |
| 62 | * @override |
| 63 | * Parses the given template to replace the placeholders |
| 64 | * with the values contained in the order details. |
| 65 | * |
| 66 | * @param string $tmpl The template to parse. |
| 67 | * @param array &$data An array data to fill. |
| 68 | * |
| 69 | * @return mixed The invoice page or an array of pages. |
| 70 | */ |
| 71 | protected function parseTemplate($tmpl, &$data) |
| 72 | { |
| 73 | $tmpl = parent::parseTemplate($tmpl, $data); |
| 74 | |
| 75 | // use default system timezone for dates |
| 76 | $tz = JFactory::getApplication()->get('offset', 'UTC'); |
| 77 | |
| 78 | if (empty($this->params->date)) |
| 79 | { |
| 80 | switch ($this->params->datetype) |
| 81 | { |
| 82 | case 2: |
| 83 | // booking date |
| 84 | $date = $this->order->createdon; |
| 85 | break; |
| 86 | |
| 87 | case 3: |
| 88 | if (!empty($this->order->appointments)) |
| 89 | { |
| 90 | // use check-in date of the first appointment |
| 91 | $date = $this->order->appointments[0]->checkin->utc; |
| 92 | } |
| 93 | else |
| 94 | { |
| 95 | // fallback to creation date |
| 96 | $date = $this->order->createdon; |
| 97 | } |
| 98 | break; |
| 99 | |
| 100 | default: |
| 101 | // current date |
| 102 | $date = 'now'; |
| 103 | } |
| 104 | } |
| 105 | else |
| 106 | { |
| 107 | // directly use the specified date (expressed in UTC) |
| 108 | $date = $this->params->date; |
| 109 | } |
| 110 | |
| 111 | // register date within invoice data |
| 112 | $data['inv_date'] = JFactory::getDate($date)->toSql(); |
| 113 | |
| 114 | // format date |
| 115 | $invoice_date = JHtml::fetch('date', $date, VAPFactory::getConfig()->get('dateformat'), $tz); |
| 116 | |
| 117 | $tmpl = str_replace('{invoice_date}', $invoice_date, $tmpl); |
| 118 | |
| 119 | // customer info |
| 120 | $custinfo = ""; |
| 121 | |
| 122 | if (!empty($this->order->displayFields)) |
| 123 | { |
| 124 | foreach ($this->order->displayFields as $k => $v) |
| 125 | { |
| 126 | // add colon as separator only in case the label doesn't |
| 127 | // end with a punctuation |
| 128 | if (preg_match("/[.,:;?!_\-]$/", $k)) |
| 129 | { |
| 130 | // ends with a punctuation, do not use separator |
| 131 | $sep = ''; |
| 132 | } |
| 133 | else |
| 134 | { |
| 135 | $sep = ':'; |
| 136 | } |
| 137 | |
| 138 | $custinfo .= $k . $sep . ' ' . $v . "<br/>\n"; |
| 139 | } |
| 140 | } |
| 141 | |
| 142 | $tmpl = str_replace('{customer_info}', $custinfo, $tmpl); |
| 143 | |
| 144 | // billing info |
| 145 | $billing_info = ""; |
| 146 | |
| 147 | if ($this->order->billing) |
| 148 | { |
| 149 | $parts = array(); |
| 150 | |
| 151 | if (empty($this->order->displayFields)) |
| 152 | { |
| 153 | // in case of empty custom fields, display the purchaser details |
| 154 | $parts[] = $this->order->billing->billing_name; |
| 155 | $parts[] = $this->order->billing->billing_mail; |
| 156 | $parts[] = $this->order->billing->billing_phone; |
| 157 | |
| 158 | // remove blank info |
| 159 | $parts = array_values(array_filter($parts)); |
| 160 | } |
| 161 | |
| 162 | // VAT and company name |
| 163 | $company_info = array(); |
| 164 | |
| 165 | if (!empty($this->order->billing->company)) |
| 166 | { |
| 167 | $company_info[] = $this->order->billing->company; |
| 168 | } |
| 169 | |
| 170 | if (!empty($this->order->billing->vatnum)) |
| 171 | { |
| 172 | $company_info[] = $this->order->billing->vatnum; |
| 173 | } |
| 174 | |
| 175 | if ($company_info) |
| 176 | { |
| 177 | $parts[] = implode(' ', $company_info); |
| 178 | } |
| 179 | |
| 180 | // Address information |
| 181 | $address_info = array(); |
| 182 | |
| 183 | if (!empty($this->order->billing->billing_address)) |
| 184 | { |
| 185 | $address_info[] = $this->order->billing->billing_address; |
| 186 | } |
| 187 | |
| 188 | if (!empty($this->order->billing->billing_address_2)) |
| 189 | { |
| 190 | $address_info[] = $this->order->billing->billing_address_2; |
| 191 | } |
| 192 | |
| 193 | if ($address_info) |
| 194 | { |
| 195 | $parts[] = implode(', ', $address_info); |
| 196 | } |
| 197 | |
| 198 | // City information |
| 199 | $city_info = array(); |
| 200 | |
| 201 | if (!empty($this->order->billing->billing_city)) |
| 202 | { |
| 203 | $city_info[] = $this->order->billing->billing_city; |
| 204 | } |
| 205 | |
| 206 | if (!empty($this->order->billing->billing_zip)) |
| 207 | { |
| 208 | $city_info[] = $this->order->billing->billing_zip; |
| 209 | } |
| 210 | |
| 211 | if (!empty($this->order->billing->billing_state)) |
| 212 | { |
| 213 | $city_info[] = $this->order->billing->billing_state; |
| 214 | } |
| 215 | |
| 216 | if ($city_info) |
| 217 | { |
| 218 | $parts[] = implode(', ', $city_info); |
| 219 | } |
| 220 | |
| 221 | // build details |
| 222 | $billing_info = implode("<br />\n", $parts); |
| 223 | } |
| 224 | |
| 225 | $tmpl = str_replace('{billing_info}', $billing_info, $tmpl); |
| 226 | |
| 227 | // totals |
| 228 | $currency = VAPFactory::getCurrency(); |
| 229 | |
| 230 | $tmpl = str_replace('{invoice_totalnet}' , $currency->format($this->order->totals->net) , $tmpl); |
| 231 | $tmpl = str_replace('{invoice_totaltax}' , $currency->format($this->order->totals->tax) , $tmpl); |
| 232 | $tmpl = str_replace('{invoice_grandtotal}', $currency->format($this->order->totals->gross) , $tmpl); |
| 233 | $tmpl = str_replace('{invoice_paycharge}' , $currency->format($this->order->totals->payCharge), $tmpl); |
| 234 | $tmpl = str_replace('{invoice_discount}' , $currency->format($this->order->totals->discount) , $tmpl); |
| 235 | |
| 236 | return $tmpl; |
| 237 | } |
| 238 | |
| 239 | /** |
| 240 | * @override |
| 241 | * Returns the e-mail address of the user that should |
| 242 | * receive the invoice via mail. |
| 243 | * |
| 244 | * @return string The customer e-mail. |
| 245 | */ |
| 246 | public function getRecipient() |
| 247 | { |
| 248 | return $this->order->purchaser_mail; |
| 249 | } |
| 250 | |
| 251 | /** |
| 252 | * Extracts an overall breakdown from the order. |
| 253 | * |
| 254 | * @return array |
| 255 | * |
| 256 | * @since 1.7 |
| 257 | */ |
| 258 | protected function getBreakdown() |
| 259 | { |
| 260 | $arr = array(); |
| 261 | |
| 262 | // group all breakdowns at the same level |
| 263 | foreach ($this->order->appointments as $app) |
| 264 | { |
| 265 | if ($app->totals->breakdown) |
| 266 | { |
| 267 | $arr = array_merge($arr, $app->totals->breakdown); |
| 268 | } |
| 269 | |
| 270 | foreach ($app->options as $opt) |
| 271 | { |
| 272 | if ($opt->totals->breakdown) |
| 273 | { |
| 274 | $arr = array_merge($arr, $opt->totals->breakdown); |
| 275 | } |
| 276 | } |
| 277 | } |
| 278 | |
| 279 | $breakdown = array(); |
| 280 | |
| 281 | // iterate breakdowns |
| 282 | foreach ($arr as $bd) |
| 283 | { |
| 284 | if (!isset($breakdown[$bd->name])) |
| 285 | { |
| 286 | $breakdown[$bd->name] = 0; |
| 287 | } |
| 288 | |
| 289 | $breakdown[$bd->name] += $bd->tax; |
| 290 | } |
| 291 | |
| 292 | // check if we have a tax for the payment |
| 293 | if ($this->order->totals->payTax > 0) |
| 294 | { |
| 295 | // manually register payment tax within the breakdown |
| 296 | $breakdown[JText::translate('VAPINVPAYTAX')] = $this->order->totals->payTax; |
| 297 | } |
| 298 | |
| 299 | return $breakdown; |
| 300 | } |
| 301 | } |
| 302 |