Merge branch 'nosolored-1.11.x_facturas' into 1.11.x

pull/2808/head
Yannick Warnier 7 years ago
commit 82dcee7b03
  1. 3
      main/inc/lib/CoursesAndSessionsCatalog.class.php
  2. 10
      plugin/buycourses/CHANGELOG.md
  3. 86
      plugin/buycourses/database.php
  4. 23
      plugin/buycourses/lang/english.php
  5. 39
      plugin/buycourses/lang/spanish.php
  6. 9
      plugin/buycourses/resources/css/style.css
  7. 594
      plugin/buycourses/src/buy_course_plugin.class.php
  8. 3
      plugin/buycourses/src/buycourses.ajax.php
  9. 9
      plugin/buycourses/src/configuration.php
  10. 17
      plugin/buycourses/src/configure_course.php
  11. 122
      plugin/buycourses/src/invoice.php
  12. 108
      plugin/buycourses/src/paymentsetup.php
  13. 52
      plugin/buycourses/src/process_confirm.php
  14. 4
      plugin/buycourses/src/sales_report.php
  15. 60
      plugin/buycourses/src/service_process_confirm.php
  16. 18
      plugin/buycourses/src/service_sales_report.php
  17. 9
      plugin/buycourses/src/services_add.php
  18. 8
      plugin/buycourses/src/services_edit.php
  19. 14
      plugin/buycourses/update.php
  20. 40
      plugin/buycourses/view/configuration.tpl
  21. 14
      plugin/buycourses/view/message_confirm.tpl
  22. 8
      plugin/buycourses/view/message_transfer.tpl
  23. 18
      plugin/buycourses/view/process.tpl
  24. 2
      plugin/buycourses/view/process_confirm.tpl
  25. 13
      plugin/buycourses/view/sales_report.tpl
  26. 10
      plugin/buycourses/view/service_information.tpl
  27. 36
      plugin/buycourses/view/service_message_transfer.tpl
  28. 21
      plugin/buycourses/view/service_process.tpl
  29. 13
      plugin/buycourses/view/service_sales_report.tpl

@ -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))

@ -1,3 +1,13 @@
v5.0 - 2019-02-06
====
This version includes two additional modules (taxes and invoices),
which can be enabled from the configuration.
The file update.php must be executed to update the structure of the tables
in the database.
v4.0 - 2017-04-25
====

@ -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,
@ -202,6 +222,7 @@ $saleTable->addColumn(
);
$saleTable->addColumn('status', \Doctrine\DBAL\Types\Type::INTEGER);
$saleTable->addColumn('payment_type', \Doctrine\DBAL\Types\Type::INTEGER);
$saleTable->addColumn('invoice', \Doctrine\DBAL\Types\Type::INTEGER);
$saleTable->setPrimaryKey(['id']);
$saleTable->addForeignKeyConstraint(
$currencyTable,
@ -250,6 +271,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);
@ -265,6 +301,7 @@ $servicesNodeTable->addColumn(
);
$servicesNodeTable->addColumn('status', \Doctrine\DBAL\Types\Type::INTEGER);
$servicesNodeTable->addColumn('payment_type', \Doctrine\DBAL\Types\Type::INTEGER);
$servicesNodeTable->addColumn('invoice', \Doctrine\DBAL\Types\Type::INTEGER);
$servicesNodeTable->setPrimaryKey(['id']);
$servicesNodeTable->addForeignKeyConstraint(
$servicesTable,
@ -291,8 +328,39 @@ $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->addColumn('seller_name', \Doctrine\DBAL\Types\Type::STRING);
$globalTable->addColumn('seller_id', \Doctrine\DBAL\Types\Type::STRING);
$globalTable->addColumn('seller_address', \Doctrine\DBAL\Types\Type::STRING);
$globalTable->addColumn('seller_email', \Doctrine\DBAL\Types\Type::STRING);
$globalTable->addColumn('next_number_invoice', \Doctrine\DBAL\Types\Type::INTEGER);
$globalTable->addColumn('invoice_series', \Doctrine\DBAL\Types\Type::STRING);
$globalTable->setPrimaryKey(['id']);
$invoiceTable = $pluginSchema->createTable(BuyCoursesPlugin::TABLE_INVOICE);
$invoiceTable->addColumn(
'id',
\Doctrine\DBAL\Types\Type::INTEGER,
['autoincrement' => true, 'unsigned' => true]
);
$invoiceTable->addColumn('sale_id', \Doctrine\DBAL\Types\Type::INTEGER);
$invoiceTable->addColumn('is_service', \Doctrine\DBAL\Types\Type::INTEGER);
$invoiceTable->addColumn(
'num_invoice',
\Doctrine\DBAL\Types\Type::INTEGER,
['unsigned' => true, 'notnull' => false]
);
$invoiceTable->addColumn(
'year',
\Doctrine\DBAL\Types\Type::INTEGER,
['unsigned' => true, 'notnull' => false]
);
$invoiceTable->addColumn('serie', \Doctrine\DBAL\Types\Type::STRING);
$invoiceTable->addColumn('date_invoice', \Doctrine\DBAL\Types\Type::DATETIME);
$invoiceTable->setPrimaryKey(['id']);
$queries = $pluginSchema->toSql($platform);
foreach ($queries as $query) {
@ -631,3 +699,21 @@ foreach ($currencies as $currency) {
]
);
}
$fieldlabel = 'buycourses_company';
$fieldtype = '1';
$fieldtitle = BuyCoursesPlugin::get_lang('Company');
$fielddefault = '';
$field_id = UserManager::create_extra_field($fieldlabel, $fieldtype, $fieldtitle, $fielddefault);
$fieldlabel = 'buycourses_vat';
$fieldtype = '1';
$fieldtitle = BuyCoursesPlugin::get_lang('VAT');
$fielddefault = '';
$field_id = UserManager::create_extra_field($fieldlabel, $fieldtype, $fieldtitle, $fielddefault);
$fieldlabel = 'buycourses_address';
$fieldtype = '1';
$fieldtitle = BuyCoursesPlugin::get_lang('Address');
$fielddefault = '';
$field_id = UserManager::create_extra_field($fieldlabel, $fieldtype, $fieldtitle, $fielddefault);

@ -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";
@ -160,3 +162,24 @@ $strings['BoughtBy'] = "BoughtBy";
$strings['PurchaserUser'] = "Purchaser user";
$strings['Pending'] = "Pending";
$strings['Names'] = "Names";
$strings['SellerName'] = "Seller name";
$strings['SellerId'] = "Seller id";
$strings['SellerAddress'] = "Seller address";
$strings['SellerEmail'] = "Seller e-mail";
$strings['NextNumberInvoice'] = "Next invoice number";
$strings['NextNumberInvoiceDescription'] = "Number of the following invoice";
$strings['InvoiceSeries'] = "Invoice series";
$strings['InvoiceSeriesDescription'] = "Optional parameter: Example invoice Id <series><year>/<number>";
$strings['InvoiceView'] = "View invoice";
$strings['NoInvoiceEnable'] = "No invoicing block enable";
$strings['Company'] = "Company";
$strings['VAT'] = "VAT";
$strings['Address'] = "Address";
$strings['InvoiceNumber'] = "Invoice number";
$strings['InvoiceDate'] = "Invoice date";
$strings['Invoice'] = "Invoice";
$strings['SaleEmail'] = "Sales e-mail";
$strings['PurchaseDetailsIntro'] = "Purchase details";
$strings['PurchaseDetailsEnd'] = "Regards";
$strings['ProductName'] = "Product name";
$strings['BankAccountIntro'] = "Bank Account Info";

@ -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";
@ -40,7 +41,7 @@ $strings['Buyer'] = "Comprador";
$strings['BankTransfer'] = "Transferencia Bancaria";
$strings['SaleInfo'] = "Información de la venta";
$strings['SaleStatusPending'] = "Venta pendiente";
$strings['SaleStatusCancelled'] = "Venta cancelada";
$strings['SaleStatusCanceled'] = "Venta cancelada";
$strings['SaleStatusCompleted'] = "Venta completada";
$strings['PayoutStatusPending'] = "Pago pendiente";
$strings['PayoutStatusCanceled'] = "Pago cancelado";
@ -173,3 +174,37 @@ $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";
$strings['SellerName'] = "Nombre vendedor";
$strings['SellerId'] = "Identificador vendedor";
$strings['SellerAddress'] = "Dirección vendedor";
$strings['SellerEmail'] = "E-mail vendedor";
$strings['NextNumberInvoice'] = "Número siguiente factura";
$strings['NextNumberInvoiceDescription'] = "Número de la siguiente factura asignado de forma manual";
$strings['InvoiceSeries'] = "Serie factura";
$strings['InvoiceSeriesDescription'] = "Parámetro opcional: Ejemplo de numeración factura <serie><año>/<número>";
$strings['InvoiceView'] = "Ver factura";
$strings['NoInvoiceEnable'] = "No está habilitado el bloque de facturación";
$strings['Company'] = "Empresa";
$strings['VAT'] = "CIF";
$strings['Address'] = "Dirección";
$strings['InvoiceNumber'] = "Num. factura";
$strings['InvoiceDate'] = "Fecha de emisión";
$strings['Invoice'] = "Factura";
$strings['SaleEmail'] = "E-mail de ventas";
$strings['PurchaseDetailsIntro'] = "Detalles de la comprar";
$strings['PurchaseDetailsEnd'] = "Atentamente";
$strings['ProductName'] = "Nombre producto";
$strings['BankAccountIntro'] = "Información cuentas bancarias";

@ -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;

@ -31,6 +31,7 @@ class BuyCoursesPlugin extends Plugin
const TABLE_SERVICES_SALE = 'plugin_buycourses_service_sale';
const TABLE_CULQI = 'plugin_buycourses_culqi';
const TABLE_GLOBAL_CONFIG = 'plugin_buycourses_global_config';
const TABLE_INVOICE = 'plugin_buycourses_invoices';
const PRODUCT_TYPE_COURSE = 1;
const PRODUCT_TYPE_SESSION = 2;
const PAYMENT_TYPE_PAYPAL = 1;
@ -51,6 +52,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;
@ -60,7 +65,7 @@ class BuyCoursesPlugin extends Plugin
public function __construct()
{
parent::__construct(
'1.0',
'5.0',
"
Jose Angel Ruiz - NoSoloRed (original author) <br/>
Francis Gonzales and Yannick Warnier - BeezNest (integration) <br/>
@ -81,6 +86,8 @@ class BuyCoursesPlugin extends Plugin
'commissions_enable' => 'boolean',
'unregistered_users_enable' => 'boolean',
'hide_free_text' => 'boolean',
'invoicing_enable' => 'boolean',
'tax_enable' => 'boolean',
]
);
}
@ -164,6 +171,131 @@ 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 (
sale_email varchar(255) NOT NULL,
global_tax_perc int unsigned NOT NULL,
tax_applies_to int unsigned NOT NULL,
tax_name varchar(255) NOT NULL,
seller_name varchar(255) NOT NULL,
seller_id varchar(255) NOT NULL,
seller_address varchar(255) NOT NULL,
seller_email varchar(255) NOT NULL,
next_number_invoice int unsigned NOT NULL,
invoice_series 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 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 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 unsigned NULL,
tax_amount decimal(10,2) NULL,
invoice int unsigned 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 unsigned NULL,
tax_amount decimal(10,2) NULL,
invoice int unsigned NULL
)";
$res = Database::query($sql);
if (!$res) {
echo Display::return_message($this->get_lang('ErrorUpdateFieldDB'), 'warning');
}
}
$table = self::TABLE_INVOICE;
$sql = "CREATE TABLE IF NOT EXISTS $table (
id int unsigned NOT NULL AUTO_INCREMENT,
sale_id int unsigned NOT NULL,
is_service int unsigned NOT NULL,
num_invoice int unsigned NOT NULL,
year int(4) unsigned NOT NULL,
serie varchar(255) NOT NULL,
date_invoice datetime NOT NULL,
PRIMARY KEY (id)
)";
$res = Database::query($sql);
Display::addFlash(
Display::return_message(
$this->get_lang('Updated'),
'info',
false
)
);
$fieldlabel = 'buycourses_company';
$fieldtype = '1';
$fieldtitle = $this->get_lang('Company');
$fielddefault = '';
$field_id = UserManager::create_extra_field($fieldlabel, $fieldtype, $fieldtitle, $fielddefault);
$fieldlabel = 'buycourses_vat';
$fieldtype = '1';
$fieldtitle = $this->get_lang('VAT');
$fielddefault = '';
$field_id = UserManager::create_extra_field($fieldlabel, $fieldtype, $fieldtitle, $fielddefault);
$fieldlabel = 'buycourses_address';
$fieldtype = '1';
$fieldtitle = $this->get_lang('Address');
$fielddefault = '';
$field_id = UserManager::create_extra_field($fieldlabel, $fieldtype, $fieldtitle, $fielddefault);
header('Location: '.api_get_path(WEB_PLUGIN_PATH).'buycourses');
}
/**
* This function verify if the plugin is enable and return the price info for a course or session in the new grid
* catalog for 1.11.x , the main purpose is to show if a course or session is in sale it shows in the main platform
@ -212,7 +344,8 @@ class BuyCoursesPlugin extends Plugin
*/
public function returnBuyCourseButton($productId, $productType)
{
$url = api_get_path(WEB_PLUGIN_PATH).'buycourses/src/process.php?i='.intval($productId).'&t='.$productType;
$productId = (int) $productId;
$url = api_get_path(WEB_PLUGIN_PATH).'buycourses/src/process.php?i='.$productId.'&t='.Security::remove_XSS($productType);
$html = '<a class="btn btn-success btn-sm" title="'.$this->get_lang('Buy').'" href="'.$url.'">'.
Display::returnFontAwesomeIcon('shopping-cart').'</a>';
@ -267,7 +400,7 @@ class BuyCoursesPlugin extends Plugin
Database::update(
$currencyTable,
['status' => 1],
['id = ?' => intval($selectedId)]
['id = ?' => (int) $selectedId]
);
}
@ -350,7 +483,7 @@ class BuyCoursesPlugin extends Plugin
{
return Database::delete(
Database::get_main_table(self::TABLE_TRANSFER),
['id = ?' => intval($id)]
['id = ?' => (int) $id]
);
}
@ -379,8 +512,8 @@ class BuyCoursesPlugin extends Plugin
[
'where' => [
'i.product_id = ? AND i.product_type = ?' => [
intval($productId),
intval($itemType),
(int) $productId,
(int) $itemType,
],
],
],
@ -525,12 +658,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 +742,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 +767,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 +832,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(),
@ -722,7 +919,7 @@ class BuyCoursesPlugin extends Plugin
'*',
Database::get_main_table(self::TABLE_ITEM),
[
'where' => ['id = ?' => intval($itemId)],
'where' => ['id = ?' => (int) $itemId],
],
'first'
);
@ -771,6 +968,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,9 +1000,12 @@ 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),
'payment_type' => (int) $paymentType,
];
return Database::insert(self::TABLE_SALE, $values);
@ -804,7 +1024,7 @@ class BuyCoursesPlugin extends Plugin
'*',
Database::get_main_table(self::TABLE_SALE),
[
'where' => ['id = ?' => intval($saleId)],
'where' => ['id = ?' => (int) $saleId],
],
'first'
);
@ -834,7 +1054,7 @@ class BuyCoursesPlugin extends Plugin
[
'where' => [
's.payment_type = ? AND s.status = ?' => [
intval($paymentType),
(int) $paymentType,
self::SALE_STATUS_COMPLETED,
],
],
@ -843,6 +1063,87 @@ class BuyCoursesPlugin extends Plugin
);
}
/**
* Get data of sales.
*
* @param int $saleId The sale id
* @param int $isService Check if a service
*
* @return array The sale data
*/
public function getDataSaleInvoice($saleId, $isService)
{
$data = [];
if ($isService) {
$sale = $this->getServiceSale($saleId);
$data['reference'] = $sale['reference'];
$data['product_name'] = $sale['service']['name'];
$data['payment_type'] = $sale['payment_type'];
$data['user_id'] = $sale['buyer']['id'];
$data['price'] = $sale['price'];
$data['price_without_tax'] = $sale['price_without_tax'];
$data['tax_perc'] = $sale['tax_perc'];
$data['tax_amount'] = $sale['tax_amount'];
$data['currency_id'] = $sale['currency_id'];
$data['date'] = $sale['buy_date'];
} else {
$sale = $this->getSale($saleId);
$data['reference'] = $sale['reference'];
$data['product_name'] = $sale['product_name'];
$data['payment_type'] = $sale['payment_type'];
$data['user_id'] = $sale['user_id'];
$data['price'] = $sale['price'];
$data['price_without_tax'] = $sale['price_without_tax'];
$data['tax_perc'] = $sale['tax_perc'];
$data['tax_amount'] = $sale['tax_amount'];
$data['currency_id'] = $sale['currency_id'];
$data['date'] = $sale['date'];
}
return $data;
}
/**
* Get data of invoice.
*
* @param int $saleId The sale id
* @param int $isService Check if a service
*
* @return array The invoice data
*/
public function getDataInvoice($saleId, $isService)
{
return Database::select(
'*',
Database::get_main_table(self::TABLE_INVOICE),
[
'where' => [
'sale_id = ? AND ' => (int) $saleId,
'is_service = ?' => (int) $isService,
],
],
'first'
);
}
/**
* Get invoice numbering
*
* @param int $saleId The sale id
* @param int $isService Check if a service
*
* @return array The invoice numbers
*/
public function getNumInvoice($saleId, $isService)
{
$dataInvoice = $this->getDataInvoice($saleId, $isService);
if (empty($dataInvoice)) {
return '-';
}
return $dataInvoice['serie'].$dataInvoice['year'].'/'.$dataInvoice['num_invoice'];
}
/**
* Get currency data by ID.
*
@ -856,7 +1157,7 @@ class BuyCoursesPlugin extends Plugin
'*',
Database::get_main_table(self::TABLE_CURRENCY),
[
'where' => ['id = ?' => intval($currencyId)],
'where' => ['id = ?' => (int) $currencyId],
],
'first'
);
@ -897,6 +1198,9 @@ class BuyCoursesPlugin extends Plugin
if ($saleIsCompleted) {
$this->updateSaleStatus($sale['id'], self::SALE_STATUS_COMPLETED);
if ($this->get('invoicing_enable') === 'true') {
$this->setInvoice($sale['id']);
}
}
return $saleIsCompleted;
@ -926,6 +1230,82 @@ class BuyCoursesPlugin extends Plugin
];
}
/**
* Register a invoice.
*
* @param int $saleId The sale ID
* @param int $isService The service type to filter (default : 0)
*/
public function setInvoice($saleId, $isService = 0)
{
$invoiceTable = Database::get_main_table(self::TABLE_INVOICE);
$year = date('Y');
$globalParameters = $this->getGlobalParameters();
$numInvoice = $globalParameters['next_number_invoice'];
$serie = $globalParameters['invoice_series'];
if (empty($numInvoice)) {
$item = Database::select(
['MAX(num_invoice) AS num_invoice'],
$invoiceTable,
[
'where' => ['year = ?' => $year],
],
'first'
);
$numInvoice = 1;
if ($item !== false) {
$numInvoice = (int) ($item['num_invoice'] + 1);
}
} else {
Database::update(
Database::get_main_table(self::TABLE_GLOBAL_CONFIG),
['next_number_invoice' => 0],
['id = ?' => 1]
);
}
Database::insert(
$invoiceTable,
[
'sale_id' => $saleId,
'is_service' => $isService,
'num_invoice' => $numInvoice,
'year' => $year,
'serie' => $serie,
'date_invoice' => api_get_utc_datetime(),
]
);
// Record invoice in the sales table
$table = Database::get_main_table(self::TABLE_SALE);
if (empty($isService)) {
$table = Database::get_main_table(self::TABLE_SERVICES_SALE);
}
Database::update(
$table,
['invoice' => 1],
['id = ?' => $saleId]
);
}
/**
* 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.
*
@ -948,7 +1328,7 @@ class BuyCoursesPlugin extends Plugin
['c.iso_code', 'u.firstname', 'u.lastname', 's.*'],
"$saleTable s $innerJoins",
[
'where' => ['s.status = ?' => intval($status)],
'where' => ['s.status = ?' => (int) $status],
'order' => 'id DESC',
]
);
@ -1127,7 +1507,7 @@ class BuyCoursesPlugin extends Plugin
"$saleTable s $innerJoins",
[
'where' => [
'u.id = ? AND s.status = ?' => [intval($id), self::SALE_STATUS_COMPLETED],
'u.id = ? AND s.status = ?' => [(int) $id, self::SALE_STATUS_COMPLETED],
],
'order' => 'id DESC',
]
@ -1155,6 +1535,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 +1545,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 +1579,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 +1616,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;
@ -1254,7 +1638,7 @@ class BuyCoursesPlugin extends Plugin
$beneficiaryTable,
[
'where' => [
'item_id = ?' => intval($itemId),
'item_id = ?' => (int) $itemId,
],
]
);
@ -1272,7 +1656,7 @@ class BuyCoursesPlugin extends Plugin
$itemTable = Database::get_main_table(self::TABLE_ITEM);
$affectedRows = Database::delete(
$itemTable,
['id = ?' => intval($itemId)]
['id = ?' => (int) $itemId]
);
if (!$affectedRows) {
@ -1313,7 +1697,7 @@ class BuyCoursesPlugin extends Plugin
$itemTable,
$itemData,
[
'product_id = ? AND ' => intval($productId),
'product_id = ? AND ' => (int) $productId,
'product_type' => $productType,
]
);
@ -1332,7 +1716,7 @@ class BuyCoursesPlugin extends Plugin
return Database::delete(
$beneficiaryTable,
['item_id = ?' => intval($itemId)]
['item_id = ?' => (int) $itemId]
);
}
@ -1352,9 +1736,9 @@ class BuyCoursesPlugin extends Plugin
Database::insert(
$beneficiaryTable,
[
'item_id' => intval($itemId),
'user_id' => intval($userId),
'commissions' => intval($commissions),
'item_id' => (int) $itemId,
'user_id' => (int) $userId,
'commissions' => (int) $commissions,
]
);
}
@ -1410,8 +1794,8 @@ class BuyCoursesPlugin extends Plugin
$payoutId = false,
$userId = false
) {
$condition = ($payoutId) ? 'AND p.id = '.intval($payoutId) : '';
$condition2 = ($userId) ? ' AND p.user_id = '.intval($userId) : '';
$condition = ($payoutId) ? 'AND p.id = '.((int) $payoutId) : '';
$condition2 = ($userId) ? ' AND p.user_id = '.((int) $userId) : '';
$typeResult = ($condition) ? 'first' : 'all';
$payoutsTable = Database::get_main_table(self::TABLE_PAYPAL_PAYOUTS);
$saleTable = Database::get_main_table(self::TABLE_SALE);
@ -1438,7 +1822,7 @@ class BuyCoursesPlugin extends Plugin
INNER JOIN $saleTable s ON s.id = p.sale_id
INNER JOIN $currencyTable c ON s.currency_id = c.id
LEFT JOIN $extraFieldValues efv ON p.user_id = efv.item_id
AND field_id = ".intval($paypalExtraField['id'])."
AND field_id = ".((int) $paypalExtraField['id'])."
";
$payouts = Database::select(
@ -1483,7 +1867,7 @@ class BuyCoursesPlugin extends Plugin
"value",
$extraFieldValues,
[
'where' => ['field_id = ? AND item_id = ?' => [intval($paypalFieldId), intval($userId)]],
'where' => ['field_id = ? AND item_id = ?' => [(int) $paypalFieldId, (int) $userId]],
],
'first'
);
@ -1512,22 +1896,24 @@ class BuyCoursesPlugin extends Plugin
$platformCommission = $this->getPlatformCommission();
$sale = $this->getSale($saleId);
$commission = (int) $platformCommission['commission'];
$teachersCommission = number_format(
(floatval($sale['price']) * intval($platformCommission['commission'])) / 100,
(floatval($sale['price']) * $commission) / 100,
2
);
$beneficiaries = $this->getBeneficiariesBySale($saleId);
foreach ($beneficiaries as $beneficiary) {
$beneficiaryCommission = (int) $beneficiary['commissions'];
Database::insert(
$payoutsTable,
[
'date' => $sale['date'],
'payout_date' => getdate(),
'sale_id' => intval($saleId),
'sale_id' => (int) $saleId,
'user_id' => $beneficiary['user_id'],
'commission' => number_format(
(floatval($teachersCommission) * intval($beneficiary['commissions'])) / 100,
(floatval($teachersCommission) * $beneficiaryCommission) / 100,
2
),
'status' => self::PAYOUT_STATUS_PENDING,
@ -1550,8 +1936,8 @@ class BuyCoursesPlugin extends Plugin
Database::update(
$payoutsTable,
['status' => intval($status)],
['id = ?' => intval($payoutId)]
['status' => (int) $status],
['id = ?' => (int) $payoutId]
);
}
@ -1583,7 +1969,7 @@ class BuyCoursesPlugin extends Plugin
return Database::update(
$commissionTable,
['commission' => intval($params['commission'])]
['commission' => (int) $params['commission']]
);
}
@ -1604,10 +1990,11 @@ 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' => '',
'video_url' => $service['video_url'],
'service_information' => $service['service_information'],
@ -1626,7 +2013,7 @@ class BuyCoursesPlugin extends Plugin
Database::update(
$servicesTable,
['image' => 'simg-'.$return.'.png'],
['id = ?' => intval($return)]
['id = ?' => (int) $return]
);
}
@ -1658,15 +2045,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]
);
}
@ -1681,12 +2069,12 @@ class BuyCoursesPlugin extends Plugin
{
Database::delete(
Database::get_main_table(self::TABLE_SERVICES_SALE),
['service_id = ?' => intval($id)]
['service_id = ?' => (int) $id]
);
return Database::delete(
Database::get_main_table(self::TABLE_SERVICES),
['id = ?' => intval($id)]
['id = ?' => (int) $id]
);
}
@ -1723,10 +2111,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 +2161,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'];
@ -1818,7 +2233,7 @@ class BuyCoursesPlugin extends Plugin
$conditions = ['WHERE' => ['ss.buyer_id = ?' => $buyerId], 'ORDER' => 'id ASC'];
}
if (is_numeric($status)) {
if (is_numeric($status) && empty($id)) {
$conditions = ['WHERE' => ['ss.status = ?' => $status], 'ORDER' => 'id ASC'];
}
@ -1862,7 +2277,6 @@ class BuyCoursesPlugin extends Plugin
$conditions,
$showData
);
$servicesSale = [];
if ($id) {
@ -1885,6 +2299,9 @@ class BuyCoursesPlugin extends Plugin
$servicesSale['currency_id'] = $return['currency_id'];
$servicesSale['currency'] = $return['currency'];
$servicesSale['price'] = $return['price'];
$servicesSale['price_without_tax'] = $return['price_without_tax'];
$servicesSale['tax_perc'] = $return['tax_perc'];
$servicesSale['tax_amount'] = $return['tax_amount'];
$servicesSale['node_type'] = $return['node_type'];
$servicesSale['node_id'] = $return['node_id'];
$servicesSale['buyer']['id'] = $buyer['user_id'];
@ -1895,6 +2312,7 @@ class BuyCoursesPlugin extends Plugin
$servicesSale['date_end'] = $return['date_end'];
$servicesSale['status'] = $return['status'];
$servicesSale['payment_type'] = $return['payment_type'];
$servicesSale['invoice'] = $return['invoice'];
return $servicesSale;
}
@ -1931,6 +2349,7 @@ class BuyCoursesPlugin extends Plugin
$servicesSale[$index]['date_end'] = $service['date_end'];
$servicesSale[$index]['status'] = $service['status'];
$servicesSale[$index]['payment_type'] = $service['payment_type'];
$servicesSale[$index]['invoice'] = $service['invoice'];
}
return $servicesSale;
@ -1972,6 +2391,10 @@ class BuyCoursesPlugin extends Plugin
self::SERVICE_STATUS_COMPLETED
);
if ($this->get('invoicing_enable') === 'true') {
$this->setInvoice($serviceSaleId, 1);
}
return true;
}
@ -2022,10 +2445,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,6 +2510,23 @@ 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,
@ -2079,9 +2536,12 @@ 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),
'node_id' => (int) $infoSelect,
'buyer_id' => $userId,
'buy_date' => api_get_utc_datetime(),
'date_start' => api_get_utc_datetime(),
@ -2093,7 +2553,7 @@ class BuyCoursesPlugin extends Plugin
'Y-m-d H:i:s'
),
'status' => self::SERVICE_STATUS_PENDING,
'payment_type' => intval($paymentType),
'payment_type' => (int) $paymentType,
];
$returnedServiceSaleId = Database::insert(self::TABLE_SERVICES_SALE, $values);
@ -2145,11 +2605,29 @@ class BuyCoursesPlugin extends Plugin
*/
public function saveGlobalParameters($params)
{
$sqlParams = [
'terms_and_conditions' => $params['terms_and_conditions'],
'sale_email' => $params['sale_email'],
];
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'];
}
if ($this->get('invoicing_enable') === 'true') {
$sqlParams['seller_name'] = $params['seller_name'];
$sqlParams['seller_id'] = $params['seller_id'];
$sqlParams['seller_address'] = $params['seller_address'];
$sqlParams['seller_email'] = $params['seller_email'];
$sqlParams['next_number_invoice'] = $params['next_number_invoice'];
$sqlParams['invoice_series'] = $params['invoice_series'];
}
return Database::update(
Database::get_main_table(self::TABLE_GLOBAL_CONFIG),
[
'terms_and_conditions' => $params['terms_and_conditions'],
],
$sqlParams,
['id = ?' => 1]
);
}
@ -2422,8 +2900,8 @@ class BuyCoursesPlugin extends Plugin
return Database::update(
$saleTable,
['status' => intval($newStatus)],
['id = ?' => intval($saleId)]
['status' => (int) $newStatus],
['id = ?' => (int) $saleId]
);
}

@ -235,6 +235,9 @@ switch ($action) {
$payout['id'],
BuyCoursesPlugin::PAYOUT_STATUS_COMPLETED
);
if ($plugin->get('invoicing_enable') === 'true') {
$plugin->setInvoice($payout['id']);
}
}
echo Display::return_message(

@ -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);

@ -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;
}

@ -0,0 +1,122 @@
<?php
/* For license terms, see /license.txt */
use Chamilo\CoreBundle\Component\Utils\ChamiloApi;
/**
* Print invoice of the Buy Courses plugin.
*
* @package chamilo.plugin.buycourses
*/
$cidReset = true;
require_once '../config.php';
api_protect_admin_script();
$plugin = BuyCoursesPlugin::create();
$invoicingEnable = $plugin->get('invoicing_enable') === 'true';
if (!$invoicingEnable) {
api_not_allowed(true, $plugin->get_lang('NoInvoiceEnable'));
}
$saleId = isset($_GET['invoice']) ? (int) $_GET['invoice'] : 0;
$isService = isset($_GET['is_service']) ? (int) $_GET['is_service'] : 0;
$globalParameters = $plugin->getGlobalParameters();
$infoSale = $plugin->getDataSaleInvoice($saleId, $isService);
$buyer = api_get_user_info($infoSale['user_id']);
$extraUserInfoData = UserManager::get_extra_user_data($infoSale['user_id']);
$infoInvoice = $plugin->getDataInvoice($saleId, $isService);
$htmlText = '<html>';
$htmlText .= '<link rel="stylesheet" type="text/css" href="plugin.css">';
$htmlText .= '<link rel="stylesheet" type="text/css" href="'.api_get_path(WEB_CSS_PATH).'base.css">';
$htmlText .= '<body>';
$organization = ChamiloApi::getPlatformLogo('', [], true);
// Use custom logo image.
$pdfLogo = api_get_setting('pdf_logo_header');
if ($pdfLogo === 'true') {
$visualTheme = api_get_visual_theme();
$img = api_get_path(SYS_CSS_PATH).'themes/'.$visualTheme.'/images/pdf_logo_header.png';
if (file_exists($img)) {
$organization = "<img src='$img'>";
}
}
$htmlText .= $organization;
// Seller and customer info
$htmlText .= '<table width="100%">';
$htmlText .= '<tr>';
$htmlText .= '<td>';
$htmlText .= '<b>'.$globalParameters['seller_name'].'</b><br/>';
$htmlText .= $globalParameters['seller_id'].'<br/>';
$htmlText .= $globalParameters['seller_address'].'<br/>';
$htmlText .= $globalParameters['seller_email'].'<br/>';
$htmlText .= '</td>';
$htmlText .= '<td style="text-align:right;">';
$htmlText .= '<b>'.$buyer['complete_name'].'</b><br/>';
$htmlText .= ($extraUserInfoData['buycourses_company'] ? $extraUserInfoData['buycourses_company'].'<br>' : '');
$htmlText .= ($extraUserInfoData['buycourses_vat'] ? $extraUserInfoData['buycourses_vat'].'<br>' : '');
$htmlText .= ($extraUserInfoData['buycourses_address'] ? $extraUserInfoData['buycourses_address'].'<br/>' : '');
$htmlText .= ($buyer['phone'] ? $buyer['phone'].'<br/>' : '');
$htmlText .= ($buyer['email'] ? $buyer['email'].'<br>' : '');
$htmlText .= '</td>';
$htmlText .= '</tr>';
$htmlText .= '</table>';
$htmlText .= '<br><br>';
$htmlText .= '<p>';
$htmlText .= $plugin->get_lang('InvoiceDate').': <span style="font-weight:bold;">'.api_format_date($infoInvoice['date_invoice'], DATE_TIME_FORMAT_LONG_24H).'</span><br>';
$htmlText .= $plugin->get_lang('InvoiceNumber').': <span style="font-weight:bold;">'.$infoInvoice['serie'].$infoInvoice['year'].'/'.$infoInvoice['num_invoice'].'</span><br>';
$htmlText .= '</p><br><br>';
$header = [
$plugin->get_lang('OrderReference'),
$plugin->get_lang('ProductType'),
$plugin->get_lang('Price'),
$globalParameters['tax_name'],
$plugin->get_lang('TotalPayout'),
];
$data = [];
$row = [
$infoSale['reference'],
$infoSale['product_name'],
$plugin->getCurrency($infoSale['currency_id'])['iso_code'].
' '.$infoSale['price_without_tax'],
$plugin->getCurrency($infoSale['currency_id'])['iso_code'].
' '.$infoSale['tax_amount'].
' ('.(int) $infoSale['tax_perc'].'%)',
$plugin->getCurrency($infoSale['currency_id'])['iso_code'].
' '.$infoSale['price'],
];
$data[] = $row;
$row = [
'',
'',
'',
$plugin->get_lang('TotalPayout'),
$plugin->getCurrency($infoSale['currency_id'])['iso_code'].' '.$infoSale['price'],
];
$data[] = $row;
$attr = [];
$attr['class'] = "table data_table";
$attr['width'] = "100%";
$htmlText .= Display::table($header, $data, $attr);
$htmlText .= '</body></html>';
$fileName = $infoInvoice['serie'].$infoInvoice['year'].'-'.$infoInvoice['num_invoice'];
$fileName = api_replace_dangerous_char($fileName);
$params = [
'filename' => $fileName,
'pdf_title' => $plugin->get_lang('Invoice'),
'pdf_description' => '',
'format' => 'A4',
'orientation' => 'P',
];
$pdf = new PDF($params['format'], $params['orientation'], $params);
$pdf->content_to_pdf($htmlText, '', $fileName, null, 'D', false, null, false, false, false);
exit;

@ -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,98 @@ foreach ($currencies as $currency) {
}
}
$currencyForm->addTextarea(
$globalSettingForm->addTextarea(
'terms_and_conditions',
[get_lang('TermsAndConditions'),
$plugin->get_lang('WriteHereTheTermsAndConditionsOfYourECommerce'), ],
$plugin->get_lang('WriteHereTheTermsAndConditionsOfYourECommerce'), ],
[]
);
$currencyForm->addButtonSave(get_lang('Save'));
$currencyForm->setDefaults($plugin->getGlobalParameters());
$globalSettingForm->addElement(
'text',
'sale_email',
$plugin->get_lang('SaleEmail')
);
$taxEnable = $plugin->get('tax_enable') === 'true';
$invoicingEnable = $plugin->get('invoicing_enable') === 'true';
if ($taxEnable) {
$globalSettingForm->addHtml('<hr/>');
$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')]
);
}
if ($invoicingEnable) {
$globalSettingForm->addHtml('<hr/>');
$globalSettingForm->addElement(
'text',
'seller_name',
$plugin->get_lang('SellerName')
);
$globalSettingForm->addElement(
'text',
'seller_id',
$plugin->get_lang('SellerId')
);
$globalSettingForm->addElement(
'text',
'seller_address',
$plugin->get_lang('SellerAddress')
);
$globalSettingForm->addElement(
'text',
'seller_email',
$plugin->get_lang('SellerEmail')
);
$globalSettingForm->addElement(
'number',
'next_number_invoice',
[$plugin->get_lang('NextNumberInvoice'), $plugin->get_lang('NextNumberInvoiceDescription')],
['step' => 1]
);
$globalSettingForm->addElement(
'text',
'invoice_series',
[$plugin->get_lang('InvoiceSeries'), $plugin->get_lang('InvoiceSeriesDescription')]
);
}
$globalSettingForm->addButtonSave(get_lang('Save'));
$globalSettingForm->setDefaults($plugin->getGlobalParameters());
$termsAndConditionsForm = new FormValidator('termsconditions');
@ -231,7 +315,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());

@ -25,7 +25,7 @@ if (empty($sale)) {
}
$currency = $plugin->getCurrency($sale['currency_id']);
$terms = $plugin->getGlobalParameters();
$globalParameters = $plugin->getGlobalParameters();
switch ($sale['payment_type']) {
case BuyCoursesPlugin::PAYMENT_TYPE_PAYPAL:
@ -64,6 +64,28 @@ switch ($sale['payment_type']) {
exit;
}
if (!empty($globalParameters['sale_email'])) {
$messageConfirmTemplate = new Template();
$messageConfirmTemplate->assign('user', $userInfo);
$messageConfirmTemplate->assign(
'sale',
[
'date' => $sale['date'],
'product' => $sale['product_name'],
'currency' => $currency['iso_code'],
'price' => $sale['price'],
'reference' => $sale['reference'],
]
);
api_mail_html(
'',
$globalParameters['sale_email'],
$plugin->get_lang('bc_subject'),
$messageConfirmTemplate->fetch('buycourses/view/message_confirm.tpl')
);
}
RedirectToPayPal($expressCheckout["TOKEN"]);
break;
case BuyCoursesPlugin::PAYMENT_TYPE_TRANSFER:
@ -109,7 +131,7 @@ switch ($sale['payment_type']) {
$messageTemplate->assign(
'sale',
[
'date' => api_format_date($sale['date'], DATE_FORMAT_LONG_NO_DAY),
'date' => $sale['date'],
'product' => $sale['product_name'],
'currency' => $currency['iso_code'],
'price' => $sale['price'],
@ -125,6 +147,28 @@ switch ($sale['payment_type']) {
$messageTemplate->fetch('buycourses/view/message_transfer.tpl')
);
if (!empty($globalParameters['sale_email'])) {
$messageConfirmTemplate = new Template();
$messageConfirmTemplate->assign('user', $userInfo);
$messageConfirmTemplate->assign(
'sale',
[
'date' => $sale['date'],
'product' => $sale['product_name'],
'currency' => $currency['iso_code'],
'price' => $sale['price'],
'reference' => $sale['reference'],
]
);
api_mail_html(
'',
$globalParameters['sale_email'],
$plugin->get_lang('bc_subject'),
$messageConfirmTemplate->fetch('buycourses/view/message_confirm.tpl')
);
}
Display::addFlash(
Display::return_message(
sprintf(
@ -162,7 +206,7 @@ switch ($sale['payment_type']) {
$template->assign('buying_course', $buyingCourse);
$template->assign('buying_session', $buyingSession);
$template->assign('terms', $terms['terms_and_conditions']);
$template->assign('terms', $globalParameters['terms_and_conditions']);
$template->assign('title', $sale['product_name']);
$template->assign('price', $sale['price']);
$template->assign('currency', $sale['currency_id']);
@ -253,7 +297,7 @@ switch ($sale['payment_type']) {
$template->assign('buying_course', $buyingCourse);
$template->assign('buying_session', $buyingSession);
$template->assign('terms', $terms['terms_and_conditions']);
$template->assign('terms', $globalParameters['terms_and_conditions']);
$template->assign('title', $sale['product_name']);
$template->assign('price', floatval($sale['price']));
$template->assign('currency', $plugin->getSelectedCurrency());

@ -18,6 +18,7 @@ $plugin = BuyCoursesPlugin::create();
$paypalEnable = $plugin->get('paypal_enable');
$commissionsEnable = $plugin->get('commissions_enable');
$includeServices = $plugin->get('include_services');
$invoicingEnable = $plugin->get('invoicing_enable') === 'true';
if (isset($_GET['order'])) {
$sale = $plugin->getSale($_GET['order']);
@ -127,6 +128,8 @@ foreach ($sales as $sale) {
'product_type' => $productTypes[$sale['product_type']],
'complete_user_name' => api_get_person_name($sale['firstname'], $sale['lastname']),
'payment_type' => $paymentTypes[$sale['payment_type']],
'invoice' => $sale['invoice'],
'num_invoice' => $plugin->getNumInvoice($sale['id'], 0),
];
}
@ -176,6 +179,7 @@ $template->assign('sale_list', $saleList);
$template->assign('sale_status_canceled', BuyCoursesPlugin::SALE_STATUS_CANCELED);
$template->assign('sale_status_pending', BuyCoursesPlugin::SALE_STATUS_PENDING);
$template->assign('sale_status_completed', BuyCoursesPlugin::SALE_STATUS_COMPLETED);
$template->assign('invoicing_enable', $invoicingEnable);
$content = $template->fetch('buycourses/view/sales_report.tpl');

@ -25,7 +25,7 @@ if (empty($serviceSale)) {
}
$currency = $plugin->getCurrency($serviceSale['currency_id']);
$terms = $plugin->getGlobalParameters();
$globalParameters = $plugin->getGlobalParameters();
switch ($serviceSale['payment_type']) {
case BuyCoursesPlugin::PAYMENT_TYPE_PAYPAL:
@ -78,6 +78,28 @@ switch ($serviceSale['payment_type']) {
exit;
}
if (!empty($globalParameters['sale_email'])) {
$messageConfirmTemplate = new Template();
$messageConfirmTemplate->assign('user', $userInfo);
$messageConfirmTemplate->assign(
'sale',
[
'date' => $serviceSale['buy_date'],
'product' => $serviceSale['service']['name'],
'currency' => $currency['iso_code'],
'price' => $serviceSale['price'],
'reference' => $serviceSale['reference'],
]
);
api_mail_html(
'',
$globalParameters['sale_email'],
$plugin->get_lang('bc_subject'),
$messageConfirmTemplate->fetch('buycourses/view/message_confirm.tpl')
);
}
RedirectToPayPal($expressCheckout['TOKEN']);
break;
case BuyCoursesPlugin::PAYMENT_TYPE_TRANSFER:
@ -112,10 +134,10 @@ switch ($serviceSale['payment_type']) {
[
'name' => $serviceSale['service']['name'],
'buyer' => $serviceSale['buyer']['name'],
'buy_date' => api_format_date($serviceSale['buy_date'], DATE_TIME_FORMAT_LONG_24H),
'start_date' => api_format_date($serviceSale['start_date'], DATE_TIME_FORMAT_LONG_24H),
'end_date' => api_format_date($serviceSale['end_date'], DATE_TIME_FORMAT_LONG_24H),
'currency' => $currency['currency'],
'buy_date' => $serviceSale['buy_date'],
'start_date' => $serviceSale['start_date'],
'end_date' => $serviceSale['end_date'],
'currency' => $currency['iso_code'],
'price' => $serviceSale['price'],
'reference' => $serviceSale['reference'],
]
@ -126,9 +148,31 @@ switch ($serviceSale['payment_type']) {
$buyer['complete_name'],
$buyer['email'],
$plugin->get_lang('bc_subject'),
$messageTemplate->fetch('buycourses/view/message_transfer.tpl')
$messageTemplate->fetch('buycourses/view/service_message_transfer.tpl')
);
if (!empty($globalParameters['sale_email'])) {
$messageConfirmTemplate = new Template();
$messageConfirmTemplate->assign('user', $userInfo);
$messageConfirmTemplate->assign(
'sale',
[
'date' => $serviceSale['buy_date'],
'product' => $serviceSale['service']['name'],
'currency' => $currency['iso_code'],
'price' => $serviceSale['price'],
'reference' => $serviceSale['reference'],
]
);
api_mail_html(
'',
$globalParameters['sale_email'],
$plugin->get_lang('bc_subject'),
$messageConfirmTemplate->fetch('buycourses/view/message_confirm.tpl')
);
}
Display::addFlash(
Display::return_message(
sprintf(
@ -166,7 +210,7 @@ switch ($serviceSale['payment_type']) {
$template = new Template();
$template->assign('terms', $terms['terms_and_conditions']);
$template->assign('terms', $globalParameters['terms_and_conditions']);
$template->assign('title', $serviceSale['service']['name']);
$template->assign('price', $serviceSale['price']);
$template->assign('currency', $serviceSale['currency_id']);
@ -235,7 +279,7 @@ switch ($serviceSale['payment_type']) {
);
$template = new Template();
$template->assign('terms', $terms['terms_and_conditions']);
$template->assign('terms', $globalParameters['terms_and_conditions']);
$template->assign('title', $serviceSale['service']['name']);
$template->assign('price', floatval($serviceSale['price']));
$template->assign('currency', $plugin->getSelectedCurrency());

@ -17,17 +17,30 @@ $plugin = BuyCoursesPlugin::create();
$paypalEnable = $plugin->get('paypal_enable');
$commissionsEnable = $plugin->get('commissions_enable');
$includeServices = $plugin->get('include_services');
$invoicingEnable = $plugin->get('invoicing_enable') === 'true';
$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) {
@ -41,6 +54,8 @@ foreach ($servicesSales as $sale) {
'service_type' => $sale['service']['applies_to'],
'service_name' => $sale['service']['name'],
'complete_user_name' => $sale['buyer']['name'],
'invoice' => $sale['invoice'],
'num_invoice' => $plugin->getNumInvoice($sale['id'], 1),
];
}
@ -87,6 +102,7 @@ $template->assign('sale_list', $serviceSaleList);
$template->assign('sale_status_cancelled', BuyCoursesPlugin::SERVICE_STATUS_CANCELLED);
$template->assign('sale_status_pending', BuyCoursesPlugin::SERVICE_STATUS_PENDING);
$template->assign('sale_status_completed', BuyCoursesPlugin::SERVICE_STATUS_COMPLETED);
$template->assign('invoicing_enable', $invoicingEnable);
$content = $template->fetch('buycourses/view/service_sales_report.tpl');
$template->assign('content', $content);
$template->display_one_col_template();

@ -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',

@ -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',

@ -0,0 +1,14 @@
<?php
/* For licensing terms, see /license.txt */
/**
* Update the plugin.
*
* @package chamilo.plugin.buycourses
*/
require_once __DIR__.'/config.php';
if (!api_is_platform_admin()) {
die('You must have admin permissions to install plugins');
}
BuyCoursesPlugin::create()->update();

@ -1,13 +1,15 @@
<link rel="stylesheet" type="text/css" href="../resources/css/style.css"/>
{% if sessions_are_included %}
{% if sessions_are_included or services_are_included %}
<ul class="nav nav-tabs buy-courses-tabs" role="tablist">
<li role="presentation" class="active">
<a href="#courses" aria-controls="courses" role="tab" data-toggle="tab">{{ 'Courses'|get_lang }}</a>
</li>
{% if sessions_are_included %}
<li role="presentation">
<a href="#sessions" aria-controls="sessions" role="tab" data-toggle="tab">{{ 'Sessions'|get_lang }}</a>
</li>
{% endif %}
{% if services_are_included %}
<li role="presentation">
<a href="#services" aria-controls="services" role="tab"
@ -27,6 +29,9 @@
<th class="text-center">{{ 'OfficialCode'|get_lang }}</th>
<th class="text-center">{{ 'VisibleInCatalog'|get_plugin_lang('BuyCoursesPlugin') }}</th>
<th class="text-right" width="200">{{ 'Price'|get_plugin_lang('BuyCoursesPlugin') }}</th>
{% if tax_enable and (tax_applies_to == 1 or tax_applies_to == 2) %}
<th class="text-center" width="100">{{ tax_name }}</th>
{% endif %}
<th class="text-right">{{ 'Options'|get_lang }}</th>
</tr>
</thead>
@ -70,6 +75,15 @@
<td width="200" class="text-right">
{{ "#{item.price} #{tem.currency ?: item.currency}" }}
</td>
{% if tax_enable and (tax_applies_to == 1 or tax_applies_to == 2) %}
<td class="text-center">
{% if item.tax_perc is null %}
{{ global_tax_perc }} %
{% else %}
{{ item.tax_perc }} %
{% endif %}
</td>
{% endif %}
<td class="text-right">
<a href="{{ _p.web_plugin ~ 'buycourses/src/configure_course.php?' ~ {'i': item.course_id, 't':product_type_course}|url_encode() }}"
class="btn btn-info btn-sm">
@ -94,6 +108,9 @@
<th class="text-center">{{ 'EndDate'|get_lang }}</th>
<th class="text-center">{{ 'VisibleInCatalog'|get_plugin_lang('BuyCoursesPlugin') }}</th>
<th class="text-right">{{ 'Price'|get_plugin_lang('BuyCoursesPlugin') }}</th>
{% if tax_enable and (tax_applies_to == 1 or tax_applies_to == 3) %}
<th class="text-center" width="100">{{ tax_name }}</th>
{% endif %}
<th class="text-right">{{ 'Options'|get_lang }}</th>
</tr>
</thead>
@ -119,6 +136,15 @@
<td class="text-right" width="200">
{{ "#{item.price} #{tem.currency ?: item.currency}" }}
</td>
{% if tax_enable and (tax_applies_to == 1 or tax_applies_to == 3) %}
<td class="text-center">
{% if item.tax_perc is null %}
{{ global_tax_perc }} %
{% else %}
{{ item.tax_perc }} %
{% endif %}
</td>
{% endif %}
<td class="text-right">
<a href="{{ _p.web_plugin ~ 'buycourses/src/configure_course.php?' ~ {'i': item.session_id, 't': product_type_session}|url_encode() }}"
class="btn btn-info btn-sm">
@ -149,6 +175,9 @@
<th class="text-center">{{ 'VisibleInCatalog'|get_plugin_lang('BuyCoursesPlugin') }}</th>
<th class="text-center">{{ 'Owner'|get_lang }}</th>
<th class="text-right">{{ 'Price'|get_plugin_lang('BuyCoursesPlugin') }}</th>
{% if tax_enable and (tax_applies_to == 1 or tax_applies_to == 4) %}
<th class="text-center" width="100">{{ tax_name }}</th>
{% endif %}
<th class="text-right">{{ 'Options'|get_lang }}</th>
</tr>
</thead>
@ -181,6 +210,15 @@
<td class="text-right" width="200">
{{ "#{item.price} #{tem.currency ?: item.currency}" }}
</td>
{% if tax_enable and (tax_applies_to == 1 or tax_applies_to == 4) %}
<td class="text-center">
{% if item.tax_perc is null %}
{{ global_tax_perc }} %
{% else %}
{{ item.tax_perc }} %
{% endif %}
</td>
{% endif %}
<td class="text-right">
<a href="{{ _p.web_plugin ~ 'buycourses/src/services_edit.php?' ~ {'id': item.id}|url_encode() }}"
class="btn btn-info btn-sm">

@ -0,0 +1,14 @@
<div>
<dl>
<dt>{{ 'OrderDate'|get_plugin_lang('BuyCoursesPlugin') }}</dt>
<dd>{{ sale.date|api_convert_and_format_date(constant('DATE_TIME_FORMAT_LONG_24H')) }}</dd>
<dt>{{ 'OrderReference'|get_plugin_lang('BuyCoursesPlugin') }}</dt>
<dd>{{ sale.reference }}</dd>
<dt>{{ 'UserName'|get_lang }}</dt>
<dd>{{ user.complete_name }}</dd>
<dt>{{ 'Course'|get_lang }}</dt>
<dd>{{ sale.product }}</dd>
<dt>{{ 'SalePrice'|get_plugin_lang('BuyCoursesPlugin') }}</dt>
<dd>{{ sale.currency ~ ' ' ~ sale.price }}</dd>
</dl>
</div>

@ -3,14 +3,14 @@
<p>{{ 'PurchaseDetailsIntro'|get_plugin_lang('BuyCoursesPlugin') }}</p>
<dl>
<dt>{{ 'OrderDate'|get_plugin_lang('BuyCoursesPlugin') }}</dt>
<dd>{{ sale.date }}</dd>
<dd>{{ sale.date|api_convert_and_format_date(constant('DATE_TIME_FORMAT_LONG_24H')) }}</dd>
<dt>{{ 'OrderReference'|get_plugin_lang('BuyCoursesPlugin') }}</dt>
<dd>sale.reference</dd>
<dd>{{ sale.reference }}</dd>
<dt>{{ 'UserName'|get_lang }}</dt>
<dd>{{ user.complete_name }}</dd>
<dt>{{ 'Course'|get_lang }}</dt>
<dd>{{ sale.product }}</dd>
<dt>{{ 'ProductName'|get_plugin_lang('BuyCoursesPlugin') }}</dt>
<dd>{{ sale.product }}</dd>
<dt>{{ 'SalePrice'|get_plugin_lang('BuyCoursesPlugin') }}</dt>
<dd>{{ sale.currency ~ ' ' ~ sale.price }}</dd>
</dl>
<p>{{ 'BankAccountIntro'|get_plugin_lang('BuyCoursesPlugin')|format(sale.product) }}</p>

@ -20,6 +20,15 @@
<img alt="{{ course.title }}" class="img-rounded img-responsive"
src="{{ course.course_img ? course.course_img : 'session_default.png'|icon() }}">
</a>
{% if course.tax_enable %}
<div class="price-details-tax">
{{ 'Price'|get_plugin_lang('BuyCoursesPlugin')}} :
{{ course.currency == 'BRL' ? 'R$' : course.currency }} {{ course.price_without_tax }}
<br>
{{ course.tax_name }} ({{ course.tax_perc }}%):
{{ course.currency == 'BRL' ? 'R$' : course.currency }} {{ course.tax_amount }}
</div>
{% endif %}
<div class="price">
{{ 'Total'|get_plugin_lang('BuyCoursesPlugin')}} :
{{ course.currency == 'BRL' ? 'R$' : course.currency }} {{ course.price }}
@ -56,6 +65,15 @@
<div class="col-md-3">
<img alt="{{ session.name }}" class="img-rounded img-responsive""
src="{{ session.image ? session.image : 'session_default.png'|icon() }}">
{% if session.tax_enable %}
<div class="price-details-tax">
{{ 'Price'|get_plugin_lang('BuyCoursesPlugin')}} :
{{ session.currency == 'BRL' ? 'R$' : session.currency }} {{ session.price_without_tax }}
<br>
{{ session.tax_name }} ({{ session.tax_perc }}%):
{{ session.currency == 'BRL' ? 'R$' : session.currency }} {{ session.tax_amount }}
</div>
{% endif %}
<div class="price">
{{ 'Total'|get_plugin_lang('BuyCoursesPlugin')}} :
{{ session.currency == 'BRL' ? 'R$' : session.currency }} {{ session.price }}

@ -22,7 +22,7 @@
</h3>
<ul class="list-unstyled">
{% for teacher in course.teachers %}
<li><em class="fa fa-user"></em> {{ teacher }}</li>
<li><em class="fa fa-user"></em> {{ teacher.name }}</li>
{% endfor %}
</ul>
<p id="n-price" class="lead text-right" style="color: white;">

@ -27,6 +27,9 @@
<th class="text-center">{{ 'ProductType'|get_plugin_lang('BuyCoursesPlugin') }}</th>
<th>{{ 'Name'|get_lang }}</th>
<th>{{ 'UserName'|get_lang }}</th>
{% if invoicing_enable %}
<th class="text-center">{{ 'Invoice'|get_plugin_lang('BuyCoursesPlugin') }}</th>
{% endif %}
<th class="text-center">{{ 'Options'|get_lang }}</th>
</tr>
</thead>
@ -49,6 +52,16 @@
<td class="text-center">{{ sale.product_type }}</td>
<td>{{ sale.product_name }}</td>
<td>{{ sale.complete_user_name }}</td>
{% if invoicing_enable %}
<td class="text-center">
{% if sale.invoice == 1 %}
<a href="{{ _p.web_plugin ~ 'buycourses/src/invoice.php?' ~ {'invoice': sale.id, 'is_service': 0}|url_encode() }}" title="{{ 'InvoiceView'|get_plugin_lang('BuyCoursesPlugin') }}" >
<img src="{{ _p.web_img }}/icons/32/default.png" alt="{{ 'InvoiceView'|get_plugin_lang('BuyCoursesPlugin') }}" />
<br/>{{ sale.num_invoice }}
</a>
{% endif %}
</td>
{% endif %}
<td class="text-center">
{% if sale.status == sale_status_pending %}
<a href="{{ _p.web_self ~ '?' ~ {'order': sale.id, 'action': 'confirm'}|url_encode() }}"

@ -68,14 +68,22 @@
{% endif %}
</p>
<p><em class="fa fa-money"></em> <b>{{ 'Price'|get_plugin_lang('BuyCoursesPlugin') }}</b>
{% if service.tax_enable %}
: {{ service.currency == 'BRL' ? 'R$' : service.currency }} {{ service.price_with_tax }}
{% else %}
: {{ service.currency == 'BRL' ? 'R$' : service.currency }} {{ service.price }}</p>
{% endif %}
</div>
<div class="service-buy">
<div class="row">
<div class="col-sm-6">
<div class="price">
{{ 'Total'|get_lang }}
: {{ service.currency == 'BRL' ? 'R$' : service.currency }} {{ service.price }}
{% if service.tax_enable %}
: {{ service.currency == 'BRL' ? 'R$' : service.currency }} {{ service.price_with_tax }}
{% else %}
: {{ service.currency == 'BRL' ? 'R$' : service.currency }} {{ service.price }}
{% endif %}
</div>
</div>
<div class="col-sm-6">

@ -0,0 +1,36 @@
<div>
<p>{{ 'DearUser'|get_lang }}</p>
<p>{{ 'PurchaseDetailsIntro'|get_plugin_lang('BuyCoursesPlugin') }}</p>
<dl>
<dt>{{ 'OrderDate'|get_plugin_lang('BuyCoursesPlugin') }}</dt>
<dd>{{ service_sale.buy_date|api_convert_and_format_date(constant('DATE_TIME_FORMAT_LONG_24H')) }}</dd>
<dt>{{ 'OrderReference'|get_plugin_lang('BuyCoursesPlugin') }}</dt>
<dd>{{ service_sale.reference }}</dd>
<dt>{{ 'UserName'|get_lang }}</dt>
<dd>{{ service_sale.buyer }}</dd>
<dt>{{ 'Service'|get_plugin_lang('BuyCoursesPlugin') }}</dt>
<dd>{{ service_sale.name }}</dd>
<dt>{{ 'SalePrice'|get_plugin_lang('BuyCoursesPlugin') }}</dt>
<dd>{{ service_sale.currency ~ ' ' ~ service_sale.price }}</dd>
</dl>
<p>{{ 'BankAccountIntro'|get_plugin_lang('BuyCoursesPlugin')|format(service_sale.name) }}</p>
<table>
<thead>
<tr>
<th>{{ 'Name'|get_lang }}</th>
<th>{{ 'BankAccount'|get_plugin_lang('BuyCoursesPlugin') }}</th>
<th>{{ 'SWIFT'|get_plugin_lang('BuyCoursesPlugin') }}</th>
</tr>
</thead>
<tbody>
{% for account in transfer_accounts %}
<tr>
<td>{{ account.name }}</td>
<td>{{ account.account }}</td>
<td>{{ account.swift }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<p>{{ 'PurchaseDetailsEnd'|get_plugin_lang('BuyCoursesPlugin') }}</p>
</div>

@ -19,10 +19,25 @@
<img alt="{{ service.name }}" class="img-rounded img-responsive"
src="{{ service.image ? service.image : 'session_default.png'|icon() }}">
</a>
{% if service.tax_enable %}
<div class="price-details-tax">
{{ 'Price'|get_plugin_lang('BuyCoursesPlugin')}} :
{{ service.currency == 'BRL' ? 'R$' : service.currency }} {{ service.price_without_tax }}
<br>
{{ service.tax_name }} ({{ service.tax_perc_show }}%):
{{ service.currency == 'BRL' ? 'R$' : service.currency }} {{ service.tax_amount }}
</div>
<div class="price">
{{ 'Total'|get_plugin_lang('BuyCoursesPlugin')}} :
{{ service.currency == 'BRL' ? 'R$' : service.currency }} {{ service.price_with_tax }}
</div>
{% else %}
<div class="price">
{{ 'Total'|get_plugin_lang('BuyCoursesPlugin')}} :
{{ service.currency == 'BRL' ? 'R$' : service.currency }} {{ service.price }}
</div>
{% endif %}
</div>
<div class="col-md-9">
<div class="buy-item">
@ -54,7 +69,11 @@
<li>
<em class="fa-li fa fa-money" aria-hidden="true"></em>
{{ 'Price'|get_plugin_lang('BuyCoursesPlugin') }}
: {{ service.currency == 'BRL' ? 'R$' : service.currency }} {{ service.price }}
{% if service.tax_enable %}
: {{ service.currency == 'BRL' ? 'R$' : service.currency }} {{ service.price_with_tax }}
{% else %}
: {{ service.currency == 'BRL' ? 'R$' : service.currency }} {{ service.price }}
{% endif %}
/ {{ service.duration_days == 0 ? 'NoLimit'|get_lang : service.duration_days ~ ' ' ~ 'Days'|get_lang }}
</li>
<li><em class="fa-li fa fa-user" aria-hidden="true"></em> {{ service.owner_name }}</li>

@ -28,6 +28,9 @@
<th class="text-center">{{ 'OrderStatus'|get_plugin_lang('BuyCoursesPlugin') }}</th>
<th class="text-center">{{ 'OrderDate'|get_plugin_lang('BuyCoursesPlugin') }}</th>
<th class="text-right">{{ 'Price'|get_plugin_lang('BuyCoursesPlugin') }}</th>
{% if sale.invoice == 1 and invoicing_enable %}
<th class="text-right">{{ 'Invoice'|get_plugin_lang('BuyCoursesPlugin') }}</th>
{% endif %}
<th class="text-center">{{ 'ServiceSaleInfo'|get_plugin_lang('BuyCoursesPlugin') }}</th>
</tr>
</thead>
@ -47,6 +50,16 @@
</td>
<td class="text-center">{{ sale.date }}</td>
<td class="text-right">{{ sale.currency ~ ' ' ~ sale.price }}</td>
{% if invoicing_enable %}
<td class="text-center">
{% if sale.invoice == 1 %}
<a href="{{ _p.web_plugin ~ 'buycourses/src/invoice.php?' ~ {'invoice': sale.id, 'is_service': 1}|url_encode() }}" title="{{ 'InvoiceView'|get_plugin_lang('BuyCoursesPlugin') }}" >
<img src="{{ _p.web_img }}/icons/32/default.png" alt="{{ 'InvoiceView'|get_plugin_lang('BuyCoursesPlugin') }}" />
<br>{{ sale.num_invoice }}
</a>
{% endif %}
</td>
{% endif %}
<td class="text-center">
<a id="service_sale_info" tag="{{ sale.id }}" name="s_{{ sale.id }}"
class="btn btn-info btn-sm">{{ 'Info'|get_lang }}</a>

Loading…
Cancel
Save