diff --git a/main/inc/lib/CoursesAndSessionsCatalog.class.php b/main/inc/lib/CoursesAndSessionsCatalog.class.php index c548a61757..ed3fdaf7a1 100644 --- a/main/inc/lib/CoursesAndSessionsCatalog.class.php +++ b/main/inc/lib/CoursesAndSessionsCatalog.class.php @@ -477,7 +477,7 @@ class CoursesAndSessionsCatalog { $em = Database::getManager(); $urlId = api_get_current_access_url_id(); - $date = Database::escape_string($date); + $sql = "SELECT s.id FROM session s "; $sql .= " INNER JOIN access_url_rel_session ars @@ -490,6 +490,7 @@ class CoursesAndSessionsCatalog "; if (!is_null($date)) { + $date = Database::escape_string($date); $sql .= " AND ( ('$date' BETWEEN DATE(s.access_start_date) AND DATE(s.access_end_date)) diff --git a/plugin/buycourses/database.php b/plugin/buycourses/database.php index fa270bda1b..ed9e68ed1a 100644 --- a/plugin/buycourses/database.php +++ b/plugin/buycourses/database.php @@ -90,6 +90,11 @@ $itemTable->addColumn( \Doctrine\DBAL\Types\Type::INTEGER, ['unsigned' => true] ); +$itemTable->addColumn( + 'tax_perc', + \Doctrine\DBAL\Types\Type::INTEGER, + ['unsigned' => true, 'notnull' => false] +); $itemTable->setPrimaryKey(['id']); $itemTable->addForeignKeyConstraint( $currencyTable, @@ -195,6 +200,21 @@ $saleTable->addColumn( \Doctrine\DBAL\Types\Type::DECIMAL, ['scale' => 2] ); +$saleTable->addColumn( + 'price_without_tax', + \Doctrine\DBAL\Types\Type::DECIMAL, + ['scale' => 2, 'notnull' => false] +); +$saleTable->addColumn( + 'tax_perc', + \Doctrine\DBAL\Types\Type::INTEGER, + ['unsigned' => true, 'notnull' => false] +); +$saleTable->addColumn( + 'tax_amount', + \Doctrine\DBAL\Types\Type::DECIMAL, + ['scale' => 2, 'notnull' => false] +); $saleTable->addColumn( 'currency_id', \Doctrine\DBAL\Types\Type::INTEGER, @@ -250,6 +270,21 @@ $servicesNodeTable->addColumn( \Doctrine\DBAL\Types\Type::DECIMAL, ['scale' => 2] ); +$servicesNodeTable->addColumn( + 'price_without_tax', + \Doctrine\DBAL\Types\Type::DECIMAL, + ['scale' => 2, 'notnull' => false] +); +$servicesNodeTable->addColumn( + 'tax_perc', + \Doctrine\DBAL\Types\Type::INTEGER, + ['unsigned' => true, 'notnull' => false] +); +$servicesNodeTable->addColumn( + 'tax_amount', + \Doctrine\DBAL\Types\Type::DECIMAL, + ['scale' => 2, 'notnull' => false] +); $servicesNodeTable->addColumn('node_type', \Doctrine\DBAL\Types\Type::INTEGER); $servicesNodeTable->addColumn('node_id', \Doctrine\DBAL\Types\Type::INTEGER); $servicesNodeTable->addColumn('buyer_id', \Doctrine\DBAL\Types\Type::INTEGER); @@ -291,6 +326,10 @@ $globalTable->addColumn( ['autoincrement' => true, 'unsigned' => true] ); $globalTable->addColumn('terms_and_conditions', \Doctrine\DBAL\Types\Type::TEXT); +$globalTable->addColumn('global_tax_perc', \Doctrine\DBAL\Types\Type::INTEGER); +$globalTable->addColumn('tax_applies_to', \Doctrine\DBAL\Types\Type::INTEGER); +$globalTable->addColumn('tax_name', \Doctrine\DBAL\Types\Type::STRING); + $globalTable->setPrimaryKey(['id']); $queries = $pluginSchema->toSql($platform); diff --git a/plugin/buycourses/lang/english.php b/plugin/buycourses/lang/english.php index 1a5ca76432..6fe970bc95 100644 --- a/plugin/buycourses/lang/english.php +++ b/plugin/buycourses/lang/english.php @@ -9,6 +9,8 @@ $strings['paypal_enable'] = "Enable PayPal"; $strings['commissions_enable'] = "Enable Commissions"; $strings['transfer_enable'] = "Enable bank transfer"; $strings['unregistered_users_enable'] = "Allow anonymous users"; +$strings['invoicing_enable'] = "Enable Invoicing"; +$strings['tax_enable'] = "Enable Taxation"; $strings['Free'] = "FREE"; $strings['PaypalPayoutCommissions'] = "Paypal Payout Commissions"; $strings['MyPayouts'] = "My payments"; diff --git a/plugin/buycourses/lang/spanish.php b/plugin/buycourses/lang/spanish.php index dddc5644bc..93b7e1722a 100644 --- a/plugin/buycourses/lang/spanish.php +++ b/plugin/buycourses/lang/spanish.php @@ -9,8 +9,9 @@ $strings['paypal_enable'] = "Habilitar PayPal"; $strings['commissions_enable'] = "Habilitar Comisiones"; $strings['transfer_enable'] = "Habilitar transferencia"; $strings['unregistered_users_enable'] = "Permitir usuarios sin registro en la plataforma"; +$strings['invoicing_enable'] = "Habilitar Facturación"; +$strings['tax_enable'] = "Habilitar Impuestos"; $strings['Free'] = "GRATIS"; - $strings['PaypalPayoutCommissions'] = "Pagar comisiones por Paypal"; $strings['MyPayouts'] = "Mis Pagos"; $strings['Commission'] = "Comisión"; @@ -173,3 +174,16 @@ $strings['DeleteThisService'] = 'Eliminar este servicio'; $strings['YourCoursesNeedAtLeastOneLearningPath'] = 'Los cursos en los que estás registrado necesitan tener al menos una lección que contenga un item de cerficado final'; $strings['NoPaymentOptionAvailable'] = 'No existen opciones de pago. Por favor reporte este problema al administrador.'; $strings['XIsOnlyPaymentMethodAvailable'] = '%s es el único método de pago disponible para esta compra.'; +$strings['GlobalTaxPerc'] = "Porcentaje del impuesto global"; +$strings['GlobalTaxPercDescription'] = "Porcentaje por defecto que se usará, excepto si existe un impuesto específico en el curso, sesión o servicio."; +$strings['TaxPerc'] = "Porcentaje del impuesto"; +$strings['TaxPercDescription'] = "Si se deja vacío se usará valor global por defecto."; +$strings['ByDefault'] = "por defecto (valor global)"; +$strings['OnlyCourses'] = "Solo Cursos"; +$strings['OnlySessions'] = "Solo Sesiones"; +$strings['OnlyServices'] = "Solo Servicios"; +$strings['TaxAppliesTo'] = "Impuestos aplicados a"; +$strings['AllCoursesSessionsAndServices'] = "Todos (Cursos, sesiones y servicios)"; +$strings['TaxNameCustom'] = "Nombre del impuesto"; +$strings['TaxNameExamples'] = "VAT, IVA, IGV, TVA, IV ..."; +$strings['ErrorUpdateFieldDB'] = "Error al actualizar los campos de la base de datos"; diff --git a/plugin/buycourses/resources/css/style.css b/plugin/buycourses/resources/css/style.css index ff9e395394..11317a086c 100644 --- a/plugin/buycourses/resources/css/style.css +++ b/plugin/buycourses/resources/css/style.css @@ -41,6 +41,15 @@ letter-spacing: -0.020em; } +.buy-info .price-details-tax, .service-buy .price-details-tax { + font-size: 18px; + line-height: 24px; + font-weight: bold; + padding-bottom: 0px; + padding-top: 10px; + letter-spacing: -0.020em; +} + .buy-info .buy-item .title { margin-top: 5px; font-weight: bold; diff --git a/plugin/buycourses/src/buy_course_plugin.class.php b/plugin/buycourses/src/buy_course_plugin.class.php index 5497ca4d7b..fb7e17c6c6 100644 --- a/plugin/buycourses/src/buy_course_plugin.class.php +++ b/plugin/buycourses/src/buy_course_plugin.class.php @@ -51,6 +51,10 @@ class BuyCoursesPlugin extends Plugin const SERVICE_TYPE_LP_FINAL_ITEM = 4; const CULQI_INTEGRATION_TYPE = 'INTEG'; const CULQI_PRODUCTION_TYPE = 'PRODUC'; + const TAX_APPLIES_TO_ALL = 1; + const TAX_APPLIES_TO_ONLY_COURSE = 2; + const TAX_APPLIES_TO_ONLY_SESSION = 3; + const TAX_APPLIES_TO_ONLY_SERVICES = 4; public $isAdminPlugin = true; @@ -81,6 +85,8 @@ class BuyCoursesPlugin extends Plugin 'commissions_enable' => 'boolean', 'unregistered_users_enable' => 'boolean', 'hide_free_text' => 'boolean', + 'invoicing_enable' => 'boolean', + 'tax_enable' => 'boolean', ] ); } @@ -163,6 +169,81 @@ class BuyCoursesPlugin extends Plugin } $this->manageTab(false); } + + public function update() + { + $table = self::TABLE_GLOBAL_CONFIG; + $sql = "SHOW COLUMNS FROM $table WHERE Field = 'global_tax_perc'"; + $res = Database::query($sql); + + if (Database::num_rows($res) === 0) { + $sql = "ALTER TABLE $table ADD ( + global_tax_perc int(11) unsigned NOT NULL, + tax_applies_to int(11) unsigned NOT NULL, + tax_name varchar(255) NOT NULL + )"; + $res = Database::query($sql); + if (!$res) { + echo Display::return_message($this->get_lang('ErrorUpdateFieldDB'), 'warning'); + } + } + + $table = self::TABLE_ITEM; + $sql = "SHOW COLUMNS FROM $table WHERE Field = 'tax_perc'"; + $res = Database::query($sql); + + if (Database::num_rows($res) === 0) { + $sql = "ALTER TABLE $table ADD tax_perc int(11) unsigned NULL"; + $res = Database::query($sql); + if (!$res) { + echo Display::return_message($this->get_lang('ErrorUpdateFieldDB'), 'warning'); + } + } + + $table = self::TABLE_SERVICES; + $sql = "SHOW COLUMNS FROM $table WHERE Field = 'tax_perc'"; + $res = Database::query($sql); + + if (Database::num_rows($res) === 0) { + $sql = "ALTER TABLE $table ADD tax_perc int(11) unsigned NULL"; + $res = Database::query($sql); + if (!$res) { + echo Display::return_message($this->get_lang('ErrorUpdateFieldDB'), 'warning'); + } + } + + $table = self::TABLE_SALE; + $sql = "SHOW COLUMNS FROM $table WHERE Field = 'tax_perc'"; + $res = Database::query($sql); + + if (Database::num_rows($res) === 0) { + $sql = "ALTER TABLE $table ADD ( + price_without_tax decimal(10,2) NULL, + tax_perc int(11) unsigned NULL, + tax_amount decimal(10,2) NULL + )"; + $res = Database::query($sql); + if (!$res) { + echo Display::return_message($this->get_lang('ErrorUpdateFieldDB'), 'warning'); + } + } + + $table = self::TABLE_SERVICES_SALE; + $sql = "SHOW COLUMNS FROM $table WHERE Field = 'tax_perc'"; + $res = Database::query($sql); + + if (Database::num_rows($res) === 0) { + $sql = "ALTER TABLE $table ADD ( + price_without_tax decimal(10,2) NULL, + tax_perc int(11) unsigned NULL, + tax_amount decimal(10,2) NULL + )"; + $res = Database::query($sql); + if (!$res) { + echo Display::return_message($this->get_lang('ErrorUpdateFieldDB'), 'warning'); + } + } + } /** * This function verify if the plugin is enable and return the price info for a course or session in the new grid @@ -525,12 +606,29 @@ class BuyCoursesPlugin extends Plugin continue; } + $price = $item['price']; + $taxPerc = null; + $priceWithoutTax = $item['price']; + + $taxEnable = $this->get('tax_enable') === 'true'; + $globalParameters = $this->getGlobalParameters(); + $taxAppliesTo = $globalParameters['tax_applies_to']; + if ($taxEnable && + ($taxAppliesTo == self::TAX_APPLIES_TO_ALL || $taxAppliesTo == self::TAX_APPLIES_TO_ONLY_COURSE) + ) { + $globalTaxPerc = $globalParameters['global_tax_perc']; + $precision = 2; + $taxPerc = is_null($item['tax_perc']) ? $globalTaxPerc : $item['tax_perc']; + $taxAmount = round($priceWithoutTax * $taxPerc / 100, $precision); + $price = $priceWithoutTax + $taxAmount; + } + $courseItem = [ 'id' => $course->getId(), 'title' => $course->getTitle(), 'code' => $course->getCode(), 'course_img' => null, - 'price' => $item['price'], + 'price' => $price, 'currency' => $item['iso_code'], 'teachers' => [], 'enrolled' => $this->getUserStatusForCourse(api_get_user_id(), $course), @@ -592,6 +690,24 @@ class BuyCoursesPlugin extends Plugin ] ); + $price = $item['price']; + $taxPerc = null; + $priceWithoutTax = $item['price']; + $precision = 2; + + $taxEnable = $this->get('tax_enable') === 'true'; + $globalParameters = $this->getGlobalParameters(); + $taxAppliesTo = $globalParameters['tax_applies_to']; + if ($taxEnable && + ($taxAppliesTo == self::TAX_APPLIES_TO_ALL || $taxAppliesTo == self::TAX_APPLIES_TO_ONLY_COURSE) + ) { + $globalTaxPerc = $globalParameters['global_tax_perc']; + $precision = 2; + $taxPerc = is_null($item['tax_perc']) ? $globalTaxPerc : $item['tax_perc']; + $taxAmount = round($priceWithoutTax * $taxPerc / 100, $precision); + $price = $priceWithoutTax + $taxAmount; + } + $courseInfo = [ 'id' => $course->getId(), 'title' => $course->getTitle(), @@ -599,7 +715,13 @@ class BuyCoursesPlugin extends Plugin 'code' => $course->getCode(), 'visual_code' => $course->getVisualCode(), 'teachers' => [], - 'price' => $item['price'], + 'price' => number_format($price, $precision), + 'price_without_tax' => number_format($priceWithoutTax, $precision), + 'tax_amount' => number_format($taxAmount, $precision), + 'tax_perc' => $taxPerc, + 'tax_name' => $globalParameters['tax_name'], + 'tax_enable' => $taxEnable && + ($taxAppliesTo == self::TAX_APPLIES_TO_ALL || $taxAppliesTo == self::TAX_APPLIES_TO_ONLY_COURSE), 'currency' => $item['iso_code'], 'course_img' => null, ]; @@ -658,13 +780,36 @@ class BuyCoursesPlugin extends Plugin 'coach_access_end_date' => $session->getCoachAccessEndDate(), ]); + $price = $item['price']; + $taxPerc = null; + $priceWithoutTax = $item['price']; + $precision = 2; + + $taxEnable = $this->get('tax_enable') === 'true'; + $globalParameters = $this->getGlobalParameters(); + $taxAppliesTo = $globalParameters['tax_applies_to']; + if ($taxEnable && + ($taxAppliesTo == self::TAX_APPLIES_TO_ALL || $taxAppliesTo == self::TAX_APPLIES_TO_ONLY_SESSION) + ) { + $globalTaxPerc = $globalParameters['global_tax_perc']; + $taxPerc = is_null($item['tax_perc']) ? $globalTaxPerc : $item['tax_perc']; + $taxAmount = round($priceWithoutTax * $taxPerc / 100, $precision); + $price = $priceWithoutTax + $taxAmount; + } + $sessionInfo = [ 'id' => $session->getId(), 'name' => $session->getName(), 'description' => $session->getDescription(), 'dates' => $sessionDates, 'courses' => [], - 'price' => $item['price'], + 'price' => number_format($price, $precision), + 'price_without_tax' => number_format($priceWithoutTax, $precision), + 'tax_amount' => number_format($taxAmount, $precision), + 'tax_perc' => $taxPerc, + 'tax_name' => $globalParameters['tax_name'], + 'tax_enable' => $taxEnable && + ($taxAppliesTo == self::TAX_APPLIES_TO_ALL || $taxAppliesTo == self::TAX_APPLIES_TO_ONLY_SESSION), 'currency' => $item['iso_code'], 'image' => null, 'nbrCourses' => $session->getNbrCourses(), @@ -771,6 +916,26 @@ class BuyCoursesPlugin extends Plugin $productName = $session->getName(); } + $price = $item['price']; + $priceWithoutTax = null; + $taxPerc = null; + + $taxEnable = $this->get('tax_enable') === 'true'; + $globalParameters = $this->getGlobalParameters(); + $taxAppliesTo = $globalParameters['tax_applies_to']; + if ($taxEnable && + ($taxAppliesTo == self::TAX_APPLIES_TO_ALL || + ($taxAppliesTo == TAX_APPLIES_TO_ONLY_COURSE && $item['product_type'] == self::PRODUCT_TYPE_COURSE) || + ($taxAppliesTo == TAX_APPLIES_TO_ONLY_SESSION && $item['product_type'] == self::PRODUCT_TYPE_SESSION)) + ) { + $priceWithoutTax = $item['price']; + $globalTaxPerc = $globalParameters['global_tax_perc']; + $precision = 2; + $taxPerc = is_null($item['tax_perc']) ? $globalTaxPerc : $item['tax_perc']; + $taxAmount = round($priceWithoutTax * $taxPerc / 100, $precision); + $price = $priceWithoutTax + $taxAmount; + } + $values = [ 'reference' => $this->generateReference( api_get_user_id(), @@ -783,7 +948,10 @@ class BuyCoursesPlugin extends Plugin 'product_type' => $item['product_type'], 'product_name' => $productName, 'product_id' => $item['product_id'], - 'price' => $item['price'], + 'price' => $price, + 'price_without_tax' => $priceWithoutTax, + 'tax_perc' => $taxPerc, + 'tax_amount' => $taxAmount, 'status' => self::SALE_STATUS_PENDING, 'payment_type' => intval($paymentType), ]; @@ -926,6 +1094,21 @@ class BuyCoursesPlugin extends Plugin ]; } + /** + * Get Tax's types + * + * @return array + */ + public function getTaxAppliesTo() + { + return [ + self::TAX_APPLIES_TO_ALL => $this->get_lang('AllCoursesSessionsAndServices'), + self::TAX_APPLIES_TO_ONLY_COURSE => $this->get_lang('OnlyCourses'), + self::TAX_APPLIES_TO_ONLY_SESSION => $this->get_lang('OnlySessions'), + self::TAX_APPLIES_TO_ONLY_SERVICES=> $this->get_lang('OnlyServices'), + ]; + } + /** * Get a list of sales by the status. * @@ -1155,6 +1338,7 @@ class BuyCoursesPlugin extends Plugin 'visible' => false, 'currency' => empty($defaultCurrency) ? null : $defaultCurrency['iso_code'], 'price' => 0.00, + 'tax_perc' => null, ]; $item = $this->getItemByProduct($course->getId(), self::PRODUCT_TYPE_COURSE); @@ -1164,6 +1348,7 @@ class BuyCoursesPlugin extends Plugin $courseItem['visible'] = true; $courseItem['currency'] = $item['iso_code']; $courseItem['price'] = $item['price']; + $courseItem['tax_perc'] = $item['tax_perc']; } return $courseItem; @@ -1197,6 +1382,7 @@ class BuyCoursesPlugin extends Plugin 'visible' => false, 'currency' => empty($defaultCurrency) ? null : $defaultCurrency['iso_code'], 'price' => 0.00, + 'tax_perc' => null, ]; $displayStartDate = $session->getDisplayStartDate(); @@ -1233,6 +1419,7 @@ class BuyCoursesPlugin extends Plugin $sessionItem['visible'] = true; $sessionItem['currency'] = $item['iso_code']; $sessionItem['price'] = $item['price']; + $sessionItem['tax_perc'] = $item['tax_perc']; } return $sessionItem; @@ -1604,6 +1791,7 @@ class BuyCoursesPlugin extends Plugin 'name' => Security::remove_XSS($service['name']), 'description' => Security::remove_XSS($service['description']), 'price' => $service['price'], + 'tax_perc' => $service['tax_perc'] != '' ? (int) $service['tax_perc'] : null, 'duration_days' => intval($service['duration_days']), 'applies_to' => intval($service['applies_to']), 'owner_id' => intval($service['owner_id']), @@ -1658,15 +1846,16 @@ class BuyCoursesPlugin extends Plugin 'name' => Security::remove_XSS($service['name']), 'description' => Security::remove_XSS($service['description']), 'price' => $service['price'], - 'duration_days' => intval($service['duration_days']), - 'applies_to' => intval($service['applies_to']), - 'owner_id' => intval($service['owner_id']), - 'visibility' => intval($service['visibility']), + 'tax_perc' => $service['tax_perc'] != '' ? (int) $service['tax_perc'] : null, + 'duration_days' => (int) $service['duration_days'], + 'applies_to' => (int) $service['applies_to'], + 'owner_id' => (int) $service['owner_id'], + 'visibility' => (int) $service['visibility'], 'image' => 'simg-'.$id.'.png', 'video_url' => $service['video_url'], 'service_information' => $service['service_information'], ], - ['id = ?' => intval($id)] + ['id = ?' => (int) $id] ); } @@ -1723,10 +1912,36 @@ class BuyCoursesPlugin extends Plugin $services = []; if ($id) { + $price = $return['price']; + $taxPerc = null; + $priceWithoutTax = $priceWithTax = $return['price']; + $precision = 2; + + $taxEnable = $this->get('tax_enable') === 'true'; + $globalParameters = $this->getGlobalParameters(); + $taxAppliesTo = $globalParameters['tax_applies_to']; + if ($taxEnable && + ($taxAppliesTo == self::TAX_APPLIES_TO_ALL || $taxAppliesTo == self::TAX_APPLIES_TO_ONLY_SERVICES) + ) { + $globalTaxPerc = $globalParameters['global_tax_perc']; + $precision = 2; + $taxPerc = is_null($return['tax_perc']) ? $globalTaxPerc : $return['tax_perc']; + $taxAmount = round($priceWithoutTax * $taxPerc / 100, $precision); + $priceWithTax = $priceWithoutTax + $taxAmount; + } + $services['id'] = $return['id']; $services['name'] = $return['name']; $services['description'] = $return['description']; - $services['price'] = $return['price']; + $services['price'] = $price; + $services['tax_perc'] = $return['tax_perc']; + $services['price_with_tax'] = number_format($priceWithTax, $precision); + $services['price_without_tax'] = number_format($priceWithoutTax, $precision); + $services['tax_amount'] = number_format($taxAmount, $precision); + $services['tax_perc_show'] = $taxPerc; + $services['tax_name'] = $globalParameters['tax_name']; + $services['tax_enable'] = $taxEnable && + ($taxAppliesTo == self::TAX_APPLIES_TO_ALL || $taxAppliesTo == self::TAX_APPLIES_TO_ONLY_SERVICES); $services['currency'] = $return['currency']; $services['duration_days'] = $return['duration_days']; $services['applies_to'] = $return['applies_to']; @@ -1747,6 +1962,7 @@ class BuyCoursesPlugin extends Plugin $services[$index]['name'] = $service['name']; $services[$index]['description'] = $service['description']; $services[$index]['price'] = $service['price']; + $services[$index]['tax_perc'] = $service['tax_perc']; $services[$index]['currency'] = $service['currency']; $services[$index]['duration_days'] = $service['duration_days']; $services[$index]['applies_to'] = $service['applies_to']; @@ -2022,10 +2238,27 @@ class BuyCoursesPlugin extends Plugin $services = []; foreach ($return as $index => $service) { + $price = $service['price']; + $taxPerc = null; + $priceWithoutTax = $service['price']; + + $taxEnable = $this->get('tax_enable') === 'true'; + $globalParameters = $this->getGlobalParameters(); + $taxAppliesTo = $globalParameters['tax_applies_to']; + if ($taxEnable && + ($taxAppliesTo == self::TAX_APPLIES_TO_ALL || $taxAppliesTo == self::TAX_APPLIES_TO_ONLY_SERVICES) + ) { + $globalTaxPerc = $globalParameters['global_tax_perc']; + $precision = 2; + $taxPerc = is_null($service['tax_perc']) ? $globalTaxPerc : $service['tax_perc']; + $taxAmount = round($priceWithoutTax * $taxPerc / 100, $precision); + $price = $priceWithoutTax + $taxAmount; + } + $services[$index]['id'] = $service['id']; $services[$index]['name'] = $service['name']; $services[$index]['description'] = $service['description']; - $services[$index]['price'] = $service['price']; + $services[$index]['price'] = number_format($price, $precision); $services[$index]['currency'] = $service['currency']; $services[$index]['duration_days'] = $service['duration_days']; $services[$index]['applies_to'] = $service['applies_to']; @@ -2070,7 +2303,24 @@ class BuyCoursesPlugin extends Plugin } $currency = $this->getSelectedCurrency(); - + $price = $service['price']; + $priceWithoutTax = null; + $taxPerc = null; + + $taxEnable = $this->get('tax_enable') === 'true'; + $globalParameters = $this->getGlobalParameters(); + $taxAppliesTo = $globalParameters['tax_applies_to']; + if ($taxEnable && + ($taxAppliesTo == self::TAX_APPLIES_TO_ALL || $taxAppliesTo == TAX_APPLIES_TO_ONLY_SERVICES) + ) { + $priceWithoutTax = $service['price']; + $globalTaxPerc = $globalParameters['global_tax_perc']; + $precision = 2; + $taxPerc = is_null($service['tax_perc']) ? $globalTaxPerc : $service['tax_perc']; + $taxAmount = round($priceWithoutTax * $taxPerc / 100, $precision); + $price = $priceWithoutTax + $taxAmount; + } + $values = [ 'service_id' => $serviceId, 'reference' => $this->generateReference( @@ -2079,7 +2329,10 @@ class BuyCoursesPlugin extends Plugin $infoSelect ), 'currency_id' => $currency['id'], - 'price' => $service['price'], + 'price' => $price, + 'price_without_tax' => $priceWithoutTax, + 'tax_perc' => $taxPerc, + 'tax_amount' => $taxAmount, 'node_type' => $service['applies_to'], 'node_id' => intval($infoSelect), 'buyer_id' => $userId, @@ -2145,11 +2398,19 @@ class BuyCoursesPlugin extends Plugin */ public function saveGlobalParameters($params) { + $sqlParams = [ + 'terms_and_conditions' => $params['terms_and_conditions'], + ]; + + if ($this->get('tax_enable') === 'true') { + $sqlParams['global_tax_perc'] = $params['global_tax_perc']; + $sqlParams['tax_applies_to'] = $params['tax_applies_to']; + $sqlParams['tax_name'] = $params['tax_name']; + } + return Database::update( Database::get_main_table(self::TABLE_GLOBAL_CONFIG), - [ - 'terms_and_conditions' => $params['terms_and_conditions'], - ], + $sqlParams, ['id = ?' => 1] ); } diff --git a/plugin/buycourses/src/configuration.php b/plugin/buycourses/src/configuration.php index 317b2ed964..65882893eb 100644 --- a/plugin/buycourses/src/configuration.php +++ b/plugin/buycourses/src/configuration.php @@ -12,6 +12,7 @@ require_once __DIR__.'/../../../main/inc/global.inc.php'; $plugin = BuyCoursesPlugin::create(); $includeSession = $plugin->get('include_sessions') === 'true'; $includeServices = $plugin->get('include_services') === 'true'; +$taxEnable = $plugin->get('tax_enable') === 'true'; api_protect_admin_script(true); @@ -39,6 +40,7 @@ $tpl->assign('product_type_session', BuyCoursesPlugin::PRODUCT_TYPE_SESSION); $tpl->assign('courses', $courses); $tpl->assign('sessions_are_included', $includeSession); $tpl->assign('services_are_included', $includeServices); +$tpl->assign('tax_enable', $taxEnable); if ($includeSession) { $sessions = $plugin->getSessionsForConfiguration(); @@ -50,6 +52,13 @@ if ($includeServices) { $tpl->assign('services', $services); } +if ($taxEnable) { + $globalParameters = $plugin->getGlobalParameters(); + $tpl->assign('global_tax_perc', $globalParameters['global_tax_perc']); + $tpl->assign('tax_applies_to', $globalParameters['tax_applies_to']); + $tpl->assign('tax_name', $globalParameters['tax_name']); +} + $content = $tpl->fetch('buycourses/view/configuration.tpl'); $tpl->assign('header', $templateName); diff --git a/plugin/buycourses/src/configure_course.php b/plugin/buycourses/src/configure_course.php index e9157ecfdb..1c5885b5ac 100644 --- a/plugin/buycourses/src/configure_course.php +++ b/plugin/buycourses/src/configure_course.php @@ -88,6 +88,7 @@ if ($editingCourse) { 'name' => $courseItem['course_title'], 'visible' => $courseItem['visible'], 'price' => $courseItem['price'], + 'tax_perc' => $courseItem['tax_perc'], 'beneficiaries' => $defaultBeneficiaries, ($commissionsEnable == "true") ? 'commissions' : '' => ($commissionsEnable == "true") ? $commissions : '', ]; @@ -154,6 +155,7 @@ if ($editingCourse) { 'name' => $sessionItem['session_name'], 'visible' => $sessionItem['visible'], 'price' => $sessionItem['price'], + 'tax_perc' => $sessionItem['tax_perc'], 'beneficiaries' => $defaultBeneficiaries, ($commissionsEnable == "true") ? 'commissions' : '' => ($commissionsEnable == "true") ? $commissions : '', ]; @@ -190,6 +192,8 @@ if ($commissionsEnable === 'true') { "; } +$globalSettingsParams = $plugin->getGlobalParameters(); + $form = new FormValidator('beneficiaries'); $form->addText('product_type', $plugin->get_lang('ProductType'), false); $form->addText('name', get_lang('Name'), false); @@ -204,6 +208,12 @@ $form->addElement( [$plugin->get_lang('Price'), null, $currencyIso], ['step' => 0.01] ); +$form->addElement( + 'number', + 'tax_perc', + [$plugin->get_lang('TaxPerc'), $plugin->get_lang('TaxPercDescription'), '%'], + ['step' => 1, 'placeholder' => $globalSettingsParams['global_tax_perc'].'% '.$plugin->get_lang('ByDefault')] +); $beneficiariesSelect = $form->addSelect( 'beneficiaries', $plugin->get_lang('Beneficiaries'), @@ -252,9 +262,13 @@ if ($form->validate()) { $productItem = $plugin->getItemByProduct($formValues['i'], $formValues['t']); if (isset($formValues['visible'])) { + $taxPerc = $formValues['tax_perc'] != '' ? (int) $formValues['tax_perc'] : null; if (!empty($productItem)) { $plugin->updateItem( - ['price' => floatval($formValues['price'])], + [ + 'price' => floatval($formValues['price']), + 'tax_perc' => $taxPerc, + ], $formValues['i'], $formValues['t'] ); @@ -264,6 +278,7 @@ if ($form->validate()) { 'product_type' => $formValues['t'], 'product_id' => intval($formValues['i']), 'price' => floatval($_POST['price']), + 'tax_perc' => $taxPerc, ]); $productItem['id'] = $itemId; } diff --git a/plugin/buycourses/src/paymentsetup.php b/plugin/buycourses/src/paymentsetup.php index 2b0477c27c..88664f9e8b 100644 --- a/plugin/buycourses/src/paymentsetup.php +++ b/plugin/buycourses/src/paymentsetup.php @@ -32,14 +32,14 @@ if (isset($_GET['action'], $_GET['id'])) { } } -$currencyForm = new FormValidator('currency'); +$globalSettingForm = new FormValidator('currency'); -if ($currencyForm->validate()) { - $currencyFormValues = $currencyForm->getSubmitValues(); +if ($globalSettingForm->validate()) { + $globalSettingFormValues = $globalSettingForm->getSubmitValues(); - $plugin->selectCurrency($currencyFormValues['currency']); - unset($currencyFormValues['currency']); - $plugin->saveGlobalParameters($currencyFormValues); + $plugin->selectCurrency($globalSettingFormValues['currency']); + unset($globalSettingFormValues['currency']); + $plugin->saveGlobalParameters($globalSettingFormValues); Display::addFlash( Display::return_message(get_lang('Saved'), 'success') @@ -51,7 +51,7 @@ if ($currencyForm->validate()) { $currencies = $plugin->getCurrencies(); -$currencySelect = $currencyForm->addSelect( +$currencySelect = $globalSettingForm->addSelect( 'currency', [ $plugin->get_lang('CurrencyType'), @@ -77,14 +77,47 @@ foreach ($currencies as $currency) { } } -$currencyForm->addTextarea( +$taxEnable = $plugin->get('tax_enable') === 'true'; + +if ($taxEnable) { + $globalSettingForm->addElement( + 'number', + 'global_tax_perc', + [$plugin->get_lang('GlobalTaxPerc'), $plugin->get_lang('GlobalTaxPercDescription'), '%'], + ['step' => 1] + ); + + $taxAppliesTo = $plugin->getTaxAppliesTo(); + + $taxTypeSelect = $globalSettingForm->addSelect( + 'tax_applies_to', + $plugin->get_lang('TaxAppliesTo'), + [get_lang('Select')] + ); + + foreach ($taxAppliesTo as $key => $value) { + $optionText = $value; + $optionyValue = $key; + + $taxTypeSelect->addOption($optionText, $optionyValue); + } + + $globalSettingForm->addElement( + 'text', + 'tax_name', + $plugin->get_lang('TaxNameCustom'), + ['placeholder' => $plugin->get_lang('TaxNameExamples')] + ); +} + +$globalSettingForm->addTextarea( 'terms_and_conditions', [get_lang('TermsAndConditions'), $plugin->get_lang('WriteHereTheTermsAndConditionsOfYourECommerce'), ], [] ); -$currencyForm->addButtonSave(get_lang('Save')); -$currencyForm->setDefaults($plugin->getGlobalParameters()); +$globalSettingForm->addButtonSave(get_lang('Save')); +$globalSettingForm->setDefaults($plugin->getGlobalParameters()); $termsAndConditionsForm = new FormValidator('termsconditions'); @@ -231,7 +264,7 @@ $interbreadcrumb[] = [ $templateName = $plugin->get_lang('PaymentsConfiguration'); $tpl = new Template($templateName); $tpl->assign('header', $templateName); -$tpl->assign('global_config_form', $currencyForm->returnForm()); +$tpl->assign('global_config_form', $globalSettingForm->returnForm()); $tpl->assign('paypal_form', $paypalForm->returnForm()); $tpl->assign('commission_form', $commissionForm->returnForm()); $tpl->assign('transfer_form', $transferForm->returnForm()); diff --git a/plugin/buycourses/src/service_sales_report.php b/plugin/buycourses/src/service_sales_report.php index b1eb36423f..2e2ba30bff 100644 --- a/plugin/buycourses/src/service_sales_report.php +++ b/plugin/buycourses/src/service_sales_report.php @@ -21,13 +21,25 @@ $includeServices = $plugin->get('include_services'); $saleStatuses = $plugin->getServiceSaleStatuses(); $paymentTypes = $plugin->getPaymentTypes(); +$selectedStatus = isset($_GET['status']) ? $_GET['status'] : BuyCoursesPlugin::SALE_STATUS_PENDING; +$searchTerm = ''; + $form = new FormValidator('search', 'get'); +if ($form->validate()) { + $selectedStatus = $form->getSubmitValue('status'); + $searchTerm = $form->getSubmitValue('user'); + + if ($selectedStatus === false) { + $selectedStatus = BuyCoursesPlugin::SALE_STATUS_PENDING; + } +} + $form->addSelect('status', $plugin->get_lang('OrderStatus'), $saleStatuses, ['cols-size' => [0, 0, 0]]); $form->addText('user', get_lang('User'), false, ['cols-size' => [0, 0, 0]]); $form->addButtonSearch(get_lang('Search'), 'search'); -$servicesSales = $plugin->getServiceSale(); +$servicesSales = $plugin->getServiceSale(null, null, $selectedStatus); $serviceSaleList = []; foreach ($servicesSales as $sale) { diff --git a/plugin/buycourses/src/services_add.php b/plugin/buycourses/src/services_add.php index 7baa13465e..5c45d740b2 100644 --- a/plugin/buycourses/src/services_add.php +++ b/plugin/buycourses/src/services_add.php @@ -32,8 +32,11 @@ $interbreadcrumb[] = [ 'name' => $plugin->get_lang('Configuration'), ]; +$globalSettingsParams = $plugin->getGlobalParameters(); + $formDefaultValues = [ 'price' => 0, + 'tax_perc' => $globalSettingsParams['global_tax_perc'], 'duration_days' => 0, 'applies_to' => 0, 'visibility' => true, @@ -48,6 +51,12 @@ $form->addElement( [$plugin->get_lang('Price'), null, $currency['iso_code']], ['step' => 0.01] ); +$form->addElement( + 'number', + 'tax_perc', + [$plugin->get_lang('TaxPerc'), $plugin->get_lang('TaxPercDescription'), '%'], + ['step' => 1, 'placeholder' => $globalSettingsParams['global_tax_perc'].'% '.$plugin->get_lang('ByDefault')] +); $form->addElement( 'number', 'duration_days', diff --git a/plugin/buycourses/src/services_edit.php b/plugin/buycourses/src/services_edit.php index 00b08884fa..f955918a88 100644 --- a/plugin/buycourses/src/services_edit.php +++ b/plugin/buycourses/src/services_edit.php @@ -37,12 +37,14 @@ $interbreadcrumb[] = [ 'name' => $plugin->get_lang('Configuration'), ]; +$globalSettingsParams = $plugin->getGlobalParameters(); $service = $plugin->getServices($serviceId); $formDefaultValues = [ 'name' => $service['name'], 'description' => $service['description'], 'price' => $service['price'], + 'tax_perc' => $service['tax_perc'], 'duration_days' => $service['duration_days'], 'owner_id' => intval($service['owner_id']), 'applies_to' => intval($service['applies_to']), @@ -63,6 +65,12 @@ $form->addElement( [$plugin->get_lang('Price'), null, $currency['iso_code']], ['step' => 0.01] ); +$form->addElement( + 'number', + 'tax_perc', + [$plugin->get_lang('TaxPerc'), $plugin->get_lang('TaxPercDescription'), '%'], + ['step' => 1, 'placeholder' => $globalSettingsParams['global_tax_perc'].'% '.$plugin->get_lang('ByDefault')] +); $form->addElement( 'number', 'duration_days', diff --git a/plugin/buycourses/update.php b/plugin/buycourses/update.php new file mode 100644 index 0000000000..8023695e14 --- /dev/null +++ b/plugin/buycourses/update.php @@ -0,0 +1,14 @@ +update(); diff --git a/plugin/buycourses/view/configuration.tpl b/plugin/buycourses/view/configuration.tpl index 0b4ba3ad70..3f4828ffcd 100644 --- a/plugin/buycourses/view/configuration.tpl +++ b/plugin/buycourses/view/configuration.tpl @@ -1,13 +1,15 @@ -{% if sessions_are_included %} +{% if sessions_are_included or services_are_included %}