diff --git a/plugin/buycourses/database.php b/plugin/buycourses/database.php
index 9ade71564b..310da3a609 100644
--- a/plugin/buycourses/database.php
+++ b/plugin/buycourses/database.php
@@ -209,6 +209,69 @@ $saleTable->addForeignKeyConstraint(
['onDelete' => 'CASCADE']
);
+$servicesTable = $pluginSchema->createTable(BuyCoursesPlugin::TABLE_SERVICES);
+$servicesTable->addColumn(
+ 'id',
+ \Doctrine\DBAL\Types\Type::INTEGER,
+ ['autoincrement' => true, 'unsigned' => true]
+);
+$servicesTable->addColumn('name', \Doctrine\DBAL\Types\Type::STRING);
+$servicesTable->addColumn('description', \Doctrine\DBAL\Types\Type::TEXT);
+$servicesTable->addColumn(
+ 'price',
+ \Doctrine\DBAL\Types\Type::DECIMAL,
+ ['scale' => 2]
+);
+$servicesTable->addColumn('duration_days', \Doctrine\DBAL\Types\Type::INTEGER);
+$servicesTable->addColumn('applies_to', \Doctrine\DBAL\Types\Type::INTEGER);
+$servicesTable->addColumn('owner_id', \Doctrine\DBAL\Types\Type::INTEGER);
+$servicesTable->addColumn('visibility', \Doctrine\DBAL\Types\Type::INTEGER);
+$servicesTable->addColumn('video_url', \Doctrine\DBAL\Types\Type::STRING);
+$servicesTable->addColumn('image', \Doctrine\DBAL\Types\Type::STRING);
+$servicesTable->addColumn('service_information', \Doctrine\DBAL\Types\Type::TEXT);
+$servicesTable->setPrimaryKey(['id']);
+
+$servicesNodeTable = $pluginSchema->createTable(BuyCoursesPlugin::TABLE_SERVICES_SALE);
+$servicesNodeTable->addColumn(
+ 'id',
+ \Doctrine\DBAL\Types\Type::INTEGER,
+ ['autoincrement' => true, 'unsigned' => true]
+);
+$servicesNodeTable->addColumn(
+ 'service_id',
+ \Doctrine\DBAL\Types\Type::INTEGER,
+ ['unsigned' => true]
+);
+$servicesNodeTable->addColumn('reference', \Doctrine\DBAL\Types\Type::STRING);
+$servicesNodeTable->addColumn('currency_id', \Doctrine\DBAL\Types\Type::INTEGER);
+$servicesNodeTable->addColumn(
+ 'price',
+ \Doctrine\DBAL\Types\Type::DECIMAL,
+ ['scale' => 2]
+);
+$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);
+$servicesNodeTable->addColumn('buy_date', \Doctrine\DBAL\Types\Type::DATETIME);
+$servicesNodeTable->addColumn(
+ 'date_start',
+ \Doctrine\DBAL\Types\Type::DATETIME,
+ ['notnull' => false]
+);
+$servicesNodeTable->addColumn(
+ 'date_end',
+ \Doctrine\DBAL\Types\Type::DATETIME
+);
+$servicesNodeTable->addColumn('status', \Doctrine\DBAL\Types\Type::INTEGER);
+$servicesNodeTable->addColumn('payment_type', \Doctrine\DBAL\Types\Type::INTEGER);
+$servicesNodeTable->setPrimaryKey(['id']);
+$servicesNodeTable->addForeignKeyConstraint(
+ $servicesTable,
+ ['service_id'],
+ ['id'],
+ ['onDelete' => 'CASCADE']
+);
+
$queries = $pluginSchema->toSql($platform);
foreach ($queries as $query) {
diff --git a/plugin/buycourses/lang/spanish.php b/plugin/buycourses/lang/spanish.php
index dd8ea0ea72..3680754ebb 100644
--- a/plugin/buycourses/lang/spanish.php
+++ b/plugin/buycourses/lang/spanish.php
@@ -133,3 +133,13 @@ $strings['ByUser'] = "Por usuario";
$strings['PaymentMethod'] = "Método de pago";
$strings['SWIFT'] = "Código SWIFT";
$strings['SWIFT_help'] = "Formato estándar de los Códigos de Identificación Bancaria (BIC) que sirve como identificador único para un banco o institución financiera.";
+$strings['include_services'] = "Incluir Servicios";
+$strings['Services'] = "Servicios";
+$strings['Service'] = "Servicio";
+$strings['NewService'] = "Nuevo servicio";
+$strings['ServiceName'] = "Nombre de servicio";
+$strings['AppliesTo'] = "Aplicado a";
+$strings['ServiceInformation'] = "Información del servicio";
+$strings['EditService'] = "Editar servicio";
+$strings['ServiceAdded'] = "Servicio agregado";
+$strings['ServiceEdited'] = "Servicio editado";
diff --git a/plugin/buycourses/src/buy_course_plugin.class.php b/plugin/buycourses/src/buy_course_plugin.class.php
index 281edb8143..85b1bdb4fc 100644
--- a/plugin/buycourses/src/buy_course_plugin.class.php
+++ b/plugin/buycourses/src/buy_course_plugin.class.php
@@ -23,6 +23,8 @@ class BuyCoursesPlugin extends Plugin
const TABLE_TRANSFER = 'plugin_buycourses_transfer';
const TABLE_COMMISSION = 'plugin_buycourses_commission';
const TABLE_PAYPAL_PAYOUTS = 'plugin_buycourses_paypal_payouts';
+ const TABLE_SERVICES = 'plugin_buycourses_services';
+ const TABLE_SERVICES_SALE = 'plugin_buycourses_service_sale';
const PRODUCT_TYPE_COURSE = 1;
const PRODUCT_TYPE_SESSION = 2;
const PAYMENT_TYPE_PAYPAL = 1;
@@ -33,6 +35,9 @@ class BuyCoursesPlugin extends Plugin
const SALE_STATUS_CANCELED = -1;
const SALE_STATUS_PENDING = 0;
const SALE_STATUS_COMPLETED = 1;
+ const SERVICE_STATUS_PENDING = 0;
+ const SERVICE_STATUS_COMPLETED = 1;
+ const SERVICE_STATUS_CANCELLED = -1;
/**
*
@@ -54,11 +59,12 @@ class BuyCoursesPlugin extends Plugin
Alex Aragón - BeezNest (Design icons and css styles)
Imanol Losada - BeezNest (introduction of sessions purchase)
Angel Fernando Quiroz Campos - BeezNest (cleanup and new reports)
- José Loguercio Silva - BeezNest (pay teachers and commissions)
+ José Loguercio Silva - BeezNest (Payouts and buy Services)
",
array(
'show_main_menu_tab' => 'boolean',
'include_sessions' => 'boolean',
+ 'include_services' => 'boolean',
'paypal_enable' => 'boolean',
'transfer_enable' => 'boolean',
'commissions_enable' => 'boolean',
@@ -80,7 +86,9 @@ class BuyCoursesPlugin extends Plugin
self::TABLE_SALE,
self::TABLE_CURRENCY,
self::TABLE_COMMISSION,
- self::TABLE_PAYPAL_PAYOUTS
+ self::TABLE_PAYPAL_PAYOUTS,
+ self::TABLE_SERVICES,
+ self::TABLE_SERVICES_SALE
);
$em = Database::getManager();
$cn = $em->getConnection();
@@ -107,7 +115,9 @@ class BuyCoursesPlugin extends Plugin
self::TABLE_SALE,
self::TABLE_CURRENCY,
self::TABLE_COMMISSION,
- self::TABLE_PAYPAL_PAYOUTS
+ self::TABLE_PAYPAL_PAYOUTS,
+ self::TABLE_SERVICES_SALE,
+ self::TABLE_SERVICES
);
foreach ($tablesToBeDeleted as $tableToBeDeleted) {
@@ -1663,4 +1673,333 @@ class BuyCoursesPlugin extends Plugin
);
}
+ /**
+ * Register addicional service
+ * @param array params $service
+ * @return mixed response
+ */
+ public function storeService($service)
+ {
+ $servicesTable = Database::get_main_table(BuyCoursesPlugin::TABLE_SERVICES);
+
+ $return = Database::insert(
+ $servicesTable,
+ [
+ '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']),
+ 'image' => 'simg.png',
+ 'video_url' => $service['video_url'],
+ 'service_information' => $service['service_information']
+ ]
+ );
+
+ if ($return) {
+ $img = str_replace('data:image/png;base64,', '', $service['cropResult']);
+ $img = str_replace(' ', '+', $img);
+ $data = base64_decode($img);
+ $file = api_get_path(SYS_PLUGIN_PATH).'buycourses/uploads/services/images/simg-'.$return.'.png';
+ file_put_contents($file, $data);
+
+ Database::update(
+ $servicesTable,
+ ['image' => 'simg-'.$return.'.png'],
+ ['id = ?' => intval($return)]
+ );
+ return $return;
+ }
+
+ return false;
+ }
+
+ /**
+ * update a service
+ * @param array $service
+ * @param integer $id
+ * @return mixed response
+ */
+ public function updateService($service, $id)
+ {
+ $servicesTable = Database::get_main_table(BuyCoursesPlugin::TABLE_SERVICES);
+
+ if (!empty($service['cropResult'])) {
+ $img = str_replace('data:image/png;base64,', '', $service['cropResult']);
+ $img = str_replace(' ', '+', $img);
+ $data = base64_decode($img);
+ $file = api_get_path(SYS_PLUGIN_PATH).'buycourses/uploads/services/images/simg-'.$id.'.png';
+ file_put_contents($file, $data);
+ }
+
+ return Database::update(
+ $servicesTable,
+ [
+ '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']),
+ 'image' => 'simg-'.$id.'.png',
+ 'video_url' => $service['video_url'],
+ 'service_information' => $service['service_information']
+ ],
+ ['id = ?' => intval($id)]
+ );
+ }
+
+ /**
+ * Remove a service
+ * @param int $id The transfer account ID
+ * @return int Rows affected. Otherwise return false
+ */
+ public function deleteService($id)
+ {
+ return Database::delete(
+ Database::get_main_table(self::TABLE_SERVICES),
+ ['id = ?' => intval($id)]
+ );
+ }
+
+ /**
+ * List adicional services
+ * @param integer $id service id
+ * @return array
+ */
+ public function getServices($id = null)
+ {
+ $servicesTable = Database::get_main_table(BuyCoursesPlugin::TABLE_SERVICES);
+ $userTable = Database::get_main_table(TABLE_MAIN_USER);
+
+ $conditions = null;
+ $showData = "all";
+
+ if ($id) {
+ $conditions = ['WHERE' => ['s.id = ?' => $id]];
+ $showData = "first";
+ }
+
+ $innerJoins = "INNER JOIN $userTable u ON s.owner_id = u.id";
+ $currency = $this->getSelectedCurrency();
+ $isoCode = $currency['iso_code'];
+ $return = Database::select(
+ "s.*, '$isoCode' as currency, u.firstname, u.lastname",
+ "$servicesTable s $innerJoins",
+ $conditions,
+ $showData
+ );
+
+ $services = [];
+
+ if ($id) {
+ $services['id'] = $return['id'];
+ $services['name'] = $return['name'];
+ $services['description'] = $return['description'];
+ $services['price'] = $return['price'];
+ $services['currency'] = $return['currency'];
+ $services['duration_days'] = $return['duration_days'];
+ $services['applies_to'] = $return['applies_to'];
+ $services['owner_id'] = $return['owner_id'];
+ $services['owner_name'] = api_get_person_name($return['firstname'], $return['lastname']);
+ $services['visibility'] = $return['visibility'];
+ $services['image'] = $return['image'];
+ $services['video_url'] = $return['video_url'];
+ $services['service_information'] = $return['service_information'];
+
+ return $services;
+ }
+
+ foreach ($return as $index => $service) {
+ $services[$index]['id'] = $service['id'];
+ $services[$index]['name'] = $service['name'];
+ $services[$index]['description'] = $service['description'];
+ $services[$index]['price'] = $service['price'];
+ $services[$index]['currency'] = $service['currency'];
+ $services[$index]['duration_days'] = $service['duration_days'];
+ $services[$index]['applies_to'] = $service['applies_to'];
+ $services[$index]['owner_id'] = $service['owner_id'];
+ $services[$index]['owner_name'] = api_get_person_name($service['firstname'], $service['lastname']);
+ $services[$index]['visibility'] = $service['visibility'];
+ $services[$index]['image'] = $service['image'];
+ $services[$index]['video_url'] = $service['video_url'];
+ $services[$index]['service_information'] = $service['service_information'];
+ }
+
+ return $services;
+ }
+
+ /**
+ * Get the statuses for sales
+ * @return array
+ */
+ public function getServiceSaleStatuses()
+ {
+ return [
+ self::SERVICE_STATUS_CANCELLED => $this->get_lang('SaleStatusCancelled'),
+ self::SERVICE_STATUS_PENDING => $this->get_lang('SaleStatusPending'),
+ self::SERVICE_STATUS_COMPLETED => $this->get_lang('SaleStatusCompleted')
+ ];
+ }
+
+ /**
+ * List services sales
+ * @param integer $id service id
+ * @param integer $buyerId buyer id
+ * @param integer $status status
+ * @param integer $nodeType The node Type ( User = 1 , Course = 2 , Session = 3 )
+ * @param integer $nodeId the nodeId
+ * @param boolean $hot enable hot services
+ * @return array
+ */
+ public function getServiceSale($id = null, $buyerId = null, $status = null, $nodeType = null, $nodeId = null, $hot = false)
+ {
+ $servicesTable = Database::get_main_table(BuyCoursesPlugin::TABLE_SERVICES);
+ $servicesSaleTable = Database::get_main_table(BuyCoursesPlugin::TABLE_SERVICES_SALE);
+
+ $conditions = null;
+ $showData = "all";
+ $groupBy = "";
+
+ if ($id) {
+ $conditions = ['WHERE' => ['ss.id = ?' => $id]];
+ $showData = "first";
+ }
+
+ if ($buyerId) {
+ $conditions = ['WHERE' => ['ss.buyer_id = ?' => $buyerId], 'ORDER' => 'id ASC'];
+ }
+
+ if (is_numeric($status)) {
+ $conditions = ['WHERE' => ['ss.status = ?' => $status], 'ORDER' => 'id ASC'];
+ }
+
+ if ($id && $buyerId) {
+ $conditions = ['WHERE' => ['ss.id = ? AND ss.buyer_id = ?' => [$id, $buyerId]], 'ORDER' => 'id ASC'];
+ }
+
+ if ($nodeType && $nodeId) {
+ $conditions = ['WHERE' => ['ss.node_type = ? AND ss.node_id = ?' => [$nodeType, $nodeId]], 'ORDER' => 'id ASC'];
+ }
+
+ if ($hot) {
+ $hot = "count(ss.service_id) as hot, ";
+ $conditions = ['ORDER' => 'hot DESC', 'LIMIT' => '6'];
+ $groupBy = "GROUP BY ss.service_id";
+ }
+
+ $innerJoins = "INNER JOIN $servicesTable s ON ss.service_id = s.id $groupBy";
+ $currency = $this->getSelectedCurrency();
+ $isoCode = $currency['iso_code'];
+ $return = Database::select(
+ "ss.*, s.name, s.description, s.price as service_price, s.duration_days, s.applies_to, s.owner_id, s.visibility, s.image, $hot '$isoCode' as currency",
+ "$servicesSaleTable ss $innerJoins",
+ $conditions,
+ $showData
+ );
+
+ $servicesSale = [];
+
+ if ($id) {
+
+ $owner = api_get_user_info($return['owner_id']);
+ $buyer = api_get_user_info($return['buyer_id']);
+
+ $servicesSale['id'] = $return['id'];
+ $servicesSale['service']['id'] = $return['service_id'];
+ $servicesSale['service']['name'] = $return['name'];
+ $servicesSale['service']['description'] = $return['description'];
+ $servicesSale['service']['price'] = $return['service_price'];
+ $servicesSale['service']['duration_days'] = $return['duration_days'];
+ $servicesSale['service']['applies_to'] = $return['applies_to'];
+ $servicesSale['service']['owner']['id'] = $return['owner_id'];
+ $servicesSale['service']['owner']['name'] = api_get_person_name($owner['firstname'], $owner['lastname']);
+ $servicesSale['service']['visibility'] = $return['visibility'];
+ $servicesSale['service']['image'] = $return['image'];
+ $servicesSale['reference'] = $return['reference'];
+ $servicesSale['currency_id'] = $return['currency_id'];
+ $servicesSale['currency'] = $return['currency'];
+ $servicesSale['price'] = $return['price'];
+ $servicesSale['node_type'] = $return['node_type'];
+ $servicesSale['node_id'] = $return['node_id'];
+ $servicesSale['buyer']['id'] = $buyer['user_id'];
+ $servicesSale['buyer']['name'] = api_get_person_name($buyer['firstname'], $buyer['lastname']);
+ $servicesSale['buyer']['username'] = $buyer['username'];
+ $servicesSale['buy_date'] = $return['buy_date'];
+ $servicesSale['date_start'] = $return['date_start'];
+ $servicesSale['date_end'] = $return['date_end'];
+ $servicesSale['status'] = $return['status'];
+ $servicesSale['payment_type'] = $return['payment_type'];
+
+ return $servicesSale;
+ }
+
+
+ foreach ($return as $index => $service) {
+
+ $owner = api_get_user_info($service['owner_id']);
+ $buyer = api_get_user_info($service['buyer_id']);
+
+ $servicesSale[$index]['id'] = $service['id'];
+ $servicesSale[$index]['service']['id'] = $service['service_id'];
+ $servicesSale[$index]['service']['name'] = $service['name'];
+ $servicesSale[$index]['service']['description'] = $service['description'];
+ $servicesSale[$index]['service']['price'] = $service['service_price'];
+ $servicesSale[$index]['service']['duration_days'] = $service['duration_days'];
+ $servicesSale[$index]['service']['applies_to'] = $service['applies_to'];
+ $servicesSale[$index]['service']['owner']['id'] = $service['owner_id'];
+ $servicesSale[$index]['service']['owner']['name'] = api_get_person_name($owner['firstname'], $owner['lastname']);
+ $servicesSale[$index]['service']['visibility'] = $service['visibility'];
+ $servicesSale[$index]['service']['image'] = $service['image'];
+ $servicesSale[$index]['reference'] = $service['reference'];
+ $servicesSale[$index]['currency_id'] = $service['currency_id'];
+ $servicesSale[$index]['currency'] = $service['currency'];
+ $servicesSale[$index]['price'] = $service['price'];
+ $servicesSale[$index]['node_type'] = $service['node_type'];
+ $servicesSale[$index]['node_id'] = $service['node_id'];
+ $servicesSale[$index]['buyer']['id'] = $service['buyer_id'];
+ $servicesSale[$index]['buyer']['name'] = api_get_person_name($buyer['firstname'], $buyer['lastname']);
+ $servicesSale[$index]['buyer']['username'] = $buyer['username'];
+ $servicesSale[$index]['buy_date'] = $service['buy_date'];
+ $servicesSale[$index]['date_start'] = $service['date_start'];
+ $servicesSale[$index]['date_end'] = $service['date_end'];
+ $servicesSale[$index]['status'] = $service['status'];
+ $servicesSale[$index]['payment_type'] = $service['payment_type'];
+ }
+
+ return $servicesSale;
+ }
+
+ /**
+ * Update service sale status to cancelled
+ * @param int $serviceSaleId The sale ID
+ * @return boolean
+ */
+ public function cancelServiceSale($serviceSaleId)
+ {
+ $this->updateServiceSaleStatus($serviceSaleId, self::SERVICE_STATUS_CANCELLED);
+ return true;
+ }
+
+ /**
+ * Complete service sale process. Update service sale status to completed
+ * @param int $serviceSaleId The service sale ID
+ * @return boolean
+ */
+ public function completeServiceSale($serviceSaleId)
+ {
+ $serviceSale = $this->getServiceSale($serviceSaleId);
+
+ if ($serviceSale['status'] == self::SERVICE_STATUS_COMPLETED) {
+ return true;
+ }
+
+ $this->updateServiceSaleStatus($serviceSaleId, self::SERVICE_STATUS_COMPLETED);
+
+ return true;
+ }
+
}
diff --git a/plugin/buycourses/src/configuration.php b/plugin/buycourses/src/configuration.php
index 392b462867..6068261f30 100644
--- a/plugin/buycourses/src/configuration.php
+++ b/plugin/buycourses/src/configuration.php
@@ -13,6 +13,7 @@ require_once __DIR__.'/../../../main/inc/global.inc.php';
$plugin = BuyCoursesPlugin::create();
$includeSession = $plugin->get('include_sessions') === 'true';
+$includeServices = $plugin->get('include_services') === 'true';
api_protect_admin_script(true);
@@ -20,22 +21,21 @@ Display::addFlash(Display::return_message(get_lang('Info').' - '.$plugin->get_la
$courses = $plugin->getCoursesForConfiguration();
-//view
+// breadcrumbs
$interbreadcrumb[] = [
- 'url' => 'course_catalog.php',
- 'name' => $plugin->get_lang('CourseListOnSale')
-];
-$interbreadcrumb[] = [
- 'url' => 'paymentsetup.php',
- 'name' => get_lang('Configuration')
+ 'url' => api_get_path(WEB_PLUGIN_PATH) . 'buycourses/index.php',
+ 'name' => $plugin->get_lang('Home')
];
$templateName = $plugin->get_lang('AvailableCourses');
+
$tpl = new Template($templateName);
+
$tpl->assign('product_type_course', BuyCoursesPlugin::PRODUCT_TYPE_COURSE);
$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);
if ($includeSession) {
$sessions = $plugin->getSessionsForConfiguration();
@@ -43,6 +43,12 @@ if ($includeSession) {
$tpl->assign('sessions', $sessions);
}
+if ($includeServices) {
+ $services = $plugin->getServices();
+
+ $tpl->assign('services', $services);
+}
+
$content = $tpl->fetch('buycourses/view/configuration.tpl');
$tpl->assign('header', $templateName);
diff --git a/plugin/buycourses/src/sales_report.php b/plugin/buycourses/src/sales_report.php
index 235355c4d0..a40dd14f22 100644
--- a/plugin/buycourses/src/sales_report.php
+++ b/plugin/buycourses/src/sales_report.php
@@ -16,6 +16,7 @@ $plugin = BuyCoursesPlugin::create();
$paypalEnable = $plugin->get('paypal_enable');
$commissionsEnable = $plugin->get('commissions_enable');
+$includeServices = $plugin->get('include_services');
if (isset($_GET['order'])) {
$sale = $plugin->getSale($_GET['order']);
@@ -170,6 +171,7 @@ if ($commissionsEnable == "true") {
$template->assign('form', $form->returnForm());
$template->assign('selected_sale', $selectedSale);
$template->assign('selected_status', $selectedStatus);
+$template->assign('services_are_included', $includeServices);
$template->assign('sale_list', $saleList);
$template->assign('sale_status_canceled', BuyCoursesPlugin::SALE_STATUS_CANCELED);
$template->assign('sale_status_pending', BuyCoursesPlugin::SALE_STATUS_PENDING);
diff --git a/plugin/buycourses/src/service_error.php b/plugin/buycourses/src/service_error.php
new file mode 100644
index 0000000000..45dff79adf
--- /dev/null
+++ b/plugin/buycourses/src/service_error.php
@@ -0,0 +1,35 @@
+getServiceSale($serviceSaleId);
+
+ $plugin->cancelServiceSale(intval($serviceSaleId));
+ Display::addFlash(
+ Display::return_message($plugin->get_lang('OrderCancelled'), 'error', false)
+ );
+
+ header('Location: '. api_get_path(WEB_PLUGIN_PATH) . 'buycourses/src/service_catalog.php');
+ exit;
+}
+
+Display::addFlash(
+ Display::return_message($plugin->get_lang('ErrorOccurred'), 'error', false)
+);
+
+header('Location: '. api_get_path(WEB_PLUGIN_PATH) . 'buycourses/src/service_catalog.php');
+
+exit;
diff --git a/plugin/buycourses/src/service_sales_report.php b/plugin/buycourses/src/service_sales_report.php
new file mode 100644
index 0000000000..244cb8f92e
--- /dev/null
+++ b/plugin/buycourses/src/service_sales_report.php
@@ -0,0 +1,99 @@
+get('paypal_enable');
+$commissionsEnable = $plugin->get('commissions_enable');
+$includeServices = $plugin->get('include_services');
+$servicesOnly = $plugin->get('show_services_only');
+
+$saleStatuses = $plugin->getServiceSaleStatuses();
+$paymentTypes = $plugin->getPaymentTypes();
+
+$form = new FormValidator('search', 'get');
+
+$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();
+$serviceSaleList = [];
+
+foreach ($servicesSales as $sale) {
+ $serviceSaleList[] = [
+ 'id' => $sale['id'],
+ 'reference' => $sale['reference'],
+ 'status' => $sale['status'],
+ 'date' => api_format_date($sale['buy_date'], DATE_TIME_FORMAT_LONG_24H),
+ 'currency' => $sale['currency'],
+ 'price' => $sale['price'],
+ 'service_type' => $sale['service']['applies_to'],
+ 'service_name' => $sale['service']['name'],
+ 'complete_user_name' => $sale['buyer']['name'],
+ 'recurring_payment' => $sale['recurring_payment'],
+ 'payment_type' => $paymentTypes[$sale['payment_type']]
+ ];
+}
+
+//View
+$interbreadcrumb[] = ['url' => '../index.php', 'name' => $plugin->get_lang('plugin_title')];
+
+$templateName = $plugin->get_lang('SalesReport');
+
+$template = new Template($templateName);
+
+$toolbar = '';
+
+if ($paypalEnable == 'true' && $commissionsEnable == 'true') {
+
+ $toolbar .= Display::toolbarButton(
+ $plugin->get_lang('PaypalPayoutCommissions'),
+ api_get_path(WEB_PLUGIN_PATH) . 'buycourses/src/paypal_payout.php',
+ 'paypal',
+ 'primary',
+ ['title' => $plugin->get_lang('PaypalPayoutCommissions')]
+ );
+
+ $template->assign('actions', $toolbar);
+
+}
+
+if ($commissionsEnable == 'true') {
+
+ $toolbar .= Display::toolbarButton(
+ $plugin->get_lang('PayoutReport'),
+ api_get_path(WEB_PLUGIN_PATH) . 'buycourses/src/payout_report.php',
+ 'money',
+ 'info',
+ ['title' => $plugin->get_lang('PayoutReport')]
+ );
+
+ $template->assign('actions', $toolbar);
+
+}
+$template->assign('form', $form->returnForm());
+$template->assign('showing_services', true);
+$template->assign('show_services_only', $servicesOnly);
+$template->assign('services_are_included', $includeServices);
+$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);
+
+$content = $template->fetch('buycourses/view/service_sales_report.tpl');
+
+
+$template->assign('content', $content);
+$template->display_one_col_template();
diff --git a/plugin/buycourses/src/services_add.php b/plugin/buycourses/src/services_add.php
new file mode 100644
index 0000000000..9bba2722e2
--- /dev/null
+++ b/plugin/buycourses/src/services_add.php
@@ -0,0 +1,123 @@
+getSelectedCurrency();
+$em = Database::getManager();
+$users = $em->getRepository('ChamiloUserBundle:User')->findAll();
+$userOptions = [];
+if (!empty($users)) {
+ foreach ($users as $user) {
+ $userOptions[$user->getId()] = $user->getCompleteNameWithUsername();
+ }
+}
+
+api_protect_admin_script(true);
+
+$htmlHeadXtra[] = api_get_css_asset('cropper/dist/cropper.min.css');
+$htmlHeadXtra[] = api_get_asset('cropper/dist/cropper.min.js');
+
+//view
+$interbreadcrumb[] = [
+ 'url' => 'configuration.php',
+ 'name' => $plugin->get_lang('Configuration')
+];
+
+$formDefaultValues = [
+ 'price' => 0,
+ 'duration_days' => 0,
+ 'applies_to' => 0,
+ 'visibility' => true
+];
+
+$form = new FormValidator('Services');
+$form->addText('name', $plugin->get_lang('ServiceName'));
+$form->addTextarea('description', $plugin->get_lang('Description'));
+$form->addElement(
+ 'number',
+ 'price',
+ [$plugin->get_lang('Price'), null, $currency['iso_code']],
+ ['step' => 0.01]
+);
+$form->addElement(
+ 'number',
+ 'duration_days',
+ [$plugin->get_lang('Duration'), null, get_lang('Days')],
+ ['step' => 1]
+);
+$form->addElement(
+ 'radio',
+ 'applies_to',
+ $plugin->get_lang('AppliesTo'),
+ get_lang('None'),
+ 0
+);
+$form->addElement(
+ 'radio',
+ 'applies_to',
+ null,
+ get_lang('User'),
+ 1
+);
+$form->addElement(
+ 'radio',
+ 'applies_to',
+ null,
+ get_lang('Course'),
+ 2
+);
+$form->addElement(
+ 'radio',
+ 'applies_to',
+ null,
+ get_lang('Session'),
+ 3
+);
+$form->addSelect(
+ 'owner_id',
+ get_lang('Owner'),
+ $userOptions
+);
+$form->addCheckBox('visibility', $plugin->get_lang('VisibleInCatalog'));
+$form->addFile(
+ 'picture',
+ (get_lang(
+ 'AddImage'
+ )),
+ array('id' => 'picture', 'class' => 'picture-form', 'crop_image' => true, 'crop_ratio' => '4 / 3')
+);
+$form->addText('video_url', get_lang('VideoUrl'), false);
+$form->addHtmlEditor('service_information', $plugin->get_lang('ServiceInformation'), false);
+$form->addButtonSave(get_lang('Add'));
+$form->setDefaults($formDefaultValues);
+
+if ($form->validate()) {
+ $values = $form->getSubmitValues();
+
+ $plugin->storeService($values);
+
+ Display::addFlash(
+ Display::return_message($plugin->get_lang('ServiceAdded'), 'success')
+ );
+
+ header('Location: configuration.php');
+ exit;
+}
+
+$templateName = $plugin->get_lang('NewService');
+$tpl = new Template($templateName);
+
+$tpl->assign('header', $templateName);
+$tpl->assign('content', $form->returnForm());
+$tpl->display_one_col_template();
diff --git a/plugin/buycourses/src/services_edit.php b/plugin/buycourses/src/services_edit.php
new file mode 100644
index 0000000000..a811ba5876
--- /dev/null
+++ b/plugin/buycourses/src/services_edit.php
@@ -0,0 +1,140 @@
+getSelectedCurrency();
+$em = Database::getManager();
+$users = $em->getRepository('ChamiloUserBundle:User')->findAll();
+$userOptions = [];
+if (!empty($users)) {
+ foreach ($users as $user) {
+ $userOptions[$user->getId()] = $user->getCompleteNameWithUsername();
+ }
+}
+
+api_protect_admin_script(true);
+$htmlHeadXtra[] = api_get_css_asset('cropper/dist/cropper.min.css');
+$htmlHeadXtra[] = api_get_asset('cropper/dist/cropper.min.js');
+
+//view
+$interbreadcrumb[] = [
+ 'url' => 'configuration.php',
+ 'name' => $plugin->get_lang('Configuration')
+];
+
+$service = $plugin->getServices($serviceId);
+
+$formDefaultValues = [
+ 'name' => $service['name'],
+ 'description' => $service['description'],
+ 'price' => $service['price'],
+ 'duration_days' => $service['duration_days'],
+ 'owner_id' => intval($service['owner_id']),
+ 'applies_to' => intval($service['applies_to']),
+ 'visibility' => ($service['visibility'] == 1) ? true : false,
+ 'image' =>
+ is_file(api_get_path(SYS_PLUGIN_PATH).'buycourses/uploads/services/images/simg-'.$serviceId.'.png')
+ ?
+ api_get_path(WEB_PLUGIN_PATH).'buycourses/uploads/services/images/simg-'.$serviceId.'.png'
+ :
+ api_get_path(WEB_CODE_PATH).'img/session_default.png',
+ 'video_url' => $service['video_url'],
+ 'service_information' => $service['service_information']
+];
+
+$form = new FormValidator('Services');
+$form->addText('name', $plugin->get_lang('ServiceName'));
+$form->addTextarea('description', $plugin->get_lang('Description'));
+$form->addElement(
+ 'number',
+ 'price',
+ [$plugin->get_lang('Price'), null, $currency['iso_code']],
+ ['step' => 0.01]
+);
+$form->addElement(
+ 'number',
+ 'duration_days',
+ [$plugin->get_lang('Duration'), null, get_lang('Days')],
+ ['step' => 1]
+);
+$form->addElement(
+ 'radio',
+ 'applies_to',
+ $plugin->get_lang('AppliesTo'),
+ get_lang('None'),
+ 0
+);
+$form->addElement(
+ 'radio',
+ 'applies_to',
+ null,
+ get_lang('User'),
+ 1
+);
+$form->addElement(
+ 'radio',
+ 'applies_to',
+ null,
+ get_lang('Course'),
+ 2
+);
+$form->addElement(
+ 'radio',
+ 'applies_to',
+ null,
+ get_lang('Session'),
+ 3
+);
+$form->addSelect(
+ 'owner_id',
+ get_lang('Owner'),
+ $userOptions
+);
+$form->addCheckBox('visibility', $plugin->get_lang('VisibleInCatalog'));
+$form->addFile(
+ 'picture',
+ ($formDefaultValues['image'] != '' ? get_lang('UpdateImage') : get_lang(
+ 'AddImage'
+ )),
+ array('id' => 'picture', 'class' => 'picture-form', 'crop_image' => true, 'crop_ratio' => '4 / 3')
+);
+$form->addText('video_url', get_lang('VideoUrl'), false);
+$form->addHtmlEditor('service_information', $plugin->get_lang('ServiceInformation'), false);
+$form->addHidden('id', $serviceId);
+$form->addButtonSave(get_lang('Edit'));
+$form->setDefaults($formDefaultValues);
+if ($form->validate()) {
+ $values = $form->getSubmitValues();
+ $plugin->updateService($values, $serviceId);
+
+ Display::addFlash(
+ Display::return_message($plugin->get_lang('ServiceEdited'), 'success')
+ );
+
+ header('Location: configuration.php');
+ exit;
+}
+
+$templateName = $plugin->get_lang('EditService');
+$tpl = new Template($templateName);
+
+$tpl->assign('header', $templateName);
+$tpl->assign('content', $form->returnForm());
+$tpl->display_one_col_template();
diff --git a/plugin/buycourses/view/configuration.tpl b/plugin/buycourses/view/configuration.tpl
index 52daacaee4..22d21922a8 100644
--- a/plugin/buycourses/view/configuration.tpl
+++ b/plugin/buycourses/view/configuration.tpl
@@ -1,5 +1,3 @@
-
-
{% if sessions_are_included %}
@@ -10,6 +8,11 @@
{{ 'Sessions'|get_lang }}
+ {% if services_are_included %}
+
+ {{ 'Services'|get_plugin_lang('BuyCoursesPlugin') }}
+
+ {% endif %}
{% endif %}
@@ -131,4 +134,65 @@
{% endif %}
+ {% if services_are_included %}
+
+
+
+ {{ 'NewService'| get_plugin_lang('BuyCoursesPlugin') }}
+
+
+
+
+
+
+ | {{ 'Service'|get_plugin_lang('BuyCoursesPlugin') }} |
+ {{ 'Description'|get_lang }} |
+ {{ 'Duration'|get_plugin_lang('BuyCoursesPlugin') }} |
+ {{ 'VisibleInCatalog'|get_plugin_lang('BuyCoursesPlugin') }} |
+ {{ 'Owner'|get_lang }} |
+ {{ 'Price'|get_plugin_lang('BuyCoursesPlugin') }} |
+ {{ 'Options'|get_lang }} |
+
+
+
+ {% for item in services %}
+
+ |
+ {{ item.name }}
+ |
+
+ {{ item.description }}
+ |
+
+ {% if item.duration_days == 0 %}
+ {{ 'NoLimit'|get_lang }}
+ {% else %}
+ {{ item.duration_days }} {{ 'Days'|get_lang }}
+ {% endif %}
+ |
+
+ {% if item.visibility == 1 %}
+
+ {% else %}
+
+ {% endif %}
+ |
+
+ {{ item.owner_name }}
+ |
+
+ {{ "#{item.price} #{tem.currency ?: item.currency}" }}
+ |
+
+
+ {{ 'Edit'|get_lang }}
+
+ |
+
+ {% endfor %}
+
+
+
+
+ {% endif %}
diff --git a/plugin/buycourses/view/sales_report.tpl b/plugin/buycourses/view/sales_report.tpl
index e602274d39..ac5970868e 100644
--- a/plugin/buycourses/view/sales_report.tpl
+++ b/plugin/buycourses/view/sales_report.tpl
@@ -1,3 +1,16 @@
+
+
+
+
{{ form }}
diff --git a/plugin/buycourses/view/service_sales_report.tpl b/plugin/buycourses/view/service_sales_report.tpl
new file mode 100644
index 0000000000..1de157b7a8
--- /dev/null
+++ b/plugin/buycourses/view/service_sales_report.tpl
@@ -0,0 +1,94 @@
+
+
+
+
+ {{ form }}
+
+
+
+
+
+
+ | {{ 'ServiceName'|get_plugin_lang('BuyCoursesPlugin') }} |
+ {{ 'OrderReference'|get_plugin_lang('BuyCoursesPlugin') }} |
+ {{ 'OrderStatus'|get_plugin_lang('BuyCoursesPlugin') }} |
+ {{ 'OrderDate'|get_plugin_lang('BuyCoursesPlugin') }} |
+ {{ 'Price'|get_plugin_lang('BuyCoursesPlugin') }} |
+ {{ 'Renewable'|get_plugin_lang('BuyCoursesPlugin') }} |
+ {{ 'ServiceSaleInfo'|get_plugin_lang('BuyCoursesPlugin') }} |
+
+
+
+ {% for sale in sale_list %}
+
+ | {{ sale.service_name }} |
+ {{ sale.reference }} |
+
+ {% if sale.status == sale_status_cancelled %}
+ {{ 'SaleStatusCancelled'|get_plugin_lang('BuyCoursesPlugin') }}
+ {% elseif sale.status == sale_status_pending %}
+ {{ 'SaleStatusPending'|get_plugin_lang('BuyCoursesPlugin') }}
+ {% elseif sale.status == sale_status_completed %}
+ {{ 'SaleStatusCompleted'|get_plugin_lang('BuyCoursesPlugin') }}
+ {% endif %}
+ |
+ {{ sale.date }} |
+ {{ sale.currency ~ ' ' ~ sale.price }} |
+ {% if sale.recurring_payment == 0 %}
+ {{ 'No' | get_lang }} |
+ {% else %}
+
+ {{ 'Info' | get_lang }}
+ |
+ {% endif %}
+
+ {{ 'Info' | get_lang }}
+ |
+
+ {% endfor %}
+
+
+
+
+
+
+