Merge pull request #1561 from jloguercio/1.11.x

WIP - Added services handler to BuyCoursesPlugin - Refs BT#12074
pull/2487/head
José Loguercio 9 years ago committed by GitHub
commit f61bdf2cb9
  1. 63
      plugin/buycourses/database.php
  2. 10
      plugin/buycourses/lang/spanish.php
  3. 345
      plugin/buycourses/src/buy_course_plugin.class.php
  4. 20
      plugin/buycourses/src/configuration.php
  5. 2
      plugin/buycourses/src/sales_report.php
  6. 35
      plugin/buycourses/src/service_error.php
  7. 99
      plugin/buycourses/src/service_sales_report.php
  8. 123
      plugin/buycourses/src/services_add.php
  9. 140
      plugin/buycourses/src/services_edit.php
  10. 68
      plugin/buycourses/view/configuration.tpl
  11. 13
      plugin/buycourses/view/sales_report.tpl
  12. 94
      plugin/buycourses/view/service_sales_report.tpl

@ -209,6 +209,69 @@ $saleTable->addForeignKeyConstraint(
['onDelete' => 'CASCADE'] ['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); $queries = $pluginSchema->toSql($platform);
foreach ($queries as $query) { foreach ($queries as $query) {

@ -133,3 +133,13 @@ $strings['ByUser'] = "Por usuario";
$strings['PaymentMethod'] = "Método de pago"; $strings['PaymentMethod'] = "Método de pago";
$strings['SWIFT'] = "Código SWIFT"; $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['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";

@ -23,6 +23,8 @@ class BuyCoursesPlugin extends Plugin
const TABLE_TRANSFER = 'plugin_buycourses_transfer'; const TABLE_TRANSFER = 'plugin_buycourses_transfer';
const TABLE_COMMISSION = 'plugin_buycourses_commission'; const TABLE_COMMISSION = 'plugin_buycourses_commission';
const TABLE_PAYPAL_PAYOUTS = 'plugin_buycourses_paypal_payouts'; 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_COURSE = 1;
const PRODUCT_TYPE_SESSION = 2; const PRODUCT_TYPE_SESSION = 2;
const PAYMENT_TYPE_PAYPAL = 1; const PAYMENT_TYPE_PAYPAL = 1;
@ -33,6 +35,9 @@ class BuyCoursesPlugin extends Plugin
const SALE_STATUS_CANCELED = -1; const SALE_STATUS_CANCELED = -1;
const SALE_STATUS_PENDING = 0; const SALE_STATUS_PENDING = 0;
const SALE_STATUS_COMPLETED = 1; 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) <br/> Alex Aragón - BeezNest (Design icons and css styles) <br/>
Imanol Losada - BeezNest (introduction of sessions purchase) <br/> Imanol Losada - BeezNest (introduction of sessions purchase) <br/>
Angel Fernando Quiroz Campos - BeezNest (cleanup and new reports) <br/> Angel Fernando Quiroz Campos - BeezNest (cleanup and new reports) <br/>
José Loguercio Silva - BeezNest (pay teachers and commissions) José Loguercio Silva - BeezNest (Payouts and buy Services)
", ",
array( array(
'show_main_menu_tab' => 'boolean', 'show_main_menu_tab' => 'boolean',
'include_sessions' => 'boolean', 'include_sessions' => 'boolean',
'include_services' => 'boolean',
'paypal_enable' => 'boolean', 'paypal_enable' => 'boolean',
'transfer_enable' => 'boolean', 'transfer_enable' => 'boolean',
'commissions_enable' => 'boolean', 'commissions_enable' => 'boolean',
@ -80,7 +86,9 @@ class BuyCoursesPlugin extends Plugin
self::TABLE_SALE, self::TABLE_SALE,
self::TABLE_CURRENCY, self::TABLE_CURRENCY,
self::TABLE_COMMISSION, self::TABLE_COMMISSION,
self::TABLE_PAYPAL_PAYOUTS self::TABLE_PAYPAL_PAYOUTS,
self::TABLE_SERVICES,
self::TABLE_SERVICES_SALE
); );
$em = Database::getManager(); $em = Database::getManager();
$cn = $em->getConnection(); $cn = $em->getConnection();
@ -107,7 +115,9 @@ class BuyCoursesPlugin extends Plugin
self::TABLE_SALE, self::TABLE_SALE,
self::TABLE_CURRENCY, self::TABLE_CURRENCY,
self::TABLE_COMMISSION, self::TABLE_COMMISSION,
self::TABLE_PAYPAL_PAYOUTS self::TABLE_PAYPAL_PAYOUTS,
self::TABLE_SERVICES_SALE,
self::TABLE_SERVICES
); );
foreach ($tablesToBeDeleted as $tableToBeDeleted) { 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;
}
} }

@ -13,6 +13,7 @@ require_once __DIR__.'/../../../main/inc/global.inc.php';
$plugin = BuyCoursesPlugin::create(); $plugin = BuyCoursesPlugin::create();
$includeSession = $plugin->get('include_sessions') === 'true'; $includeSession = $plugin->get('include_sessions') === 'true';
$includeServices = $plugin->get('include_services') === 'true';
api_protect_admin_script(true); api_protect_admin_script(true);
@ -20,22 +21,21 @@ Display::addFlash(Display::return_message(get_lang('Info').' - '.$plugin->get_la
$courses = $plugin->getCoursesForConfiguration(); $courses = $plugin->getCoursesForConfiguration();
//view // breadcrumbs
$interbreadcrumb[] = [ $interbreadcrumb[] = [
'url' => 'course_catalog.php', 'url' => api_get_path(WEB_PLUGIN_PATH) . 'buycourses/index.php',
'name' => $plugin->get_lang('CourseListOnSale') 'name' => $plugin->get_lang('Home')
];
$interbreadcrumb[] = [
'url' => 'paymentsetup.php',
'name' => get_lang('Configuration')
]; ];
$templateName = $plugin->get_lang('AvailableCourses'); $templateName = $plugin->get_lang('AvailableCourses');
$tpl = new Template($templateName); $tpl = new Template($templateName);
$tpl->assign('product_type_course', BuyCoursesPlugin::PRODUCT_TYPE_COURSE); $tpl->assign('product_type_course', BuyCoursesPlugin::PRODUCT_TYPE_COURSE);
$tpl->assign('product_type_session', BuyCoursesPlugin::PRODUCT_TYPE_SESSION); $tpl->assign('product_type_session', BuyCoursesPlugin::PRODUCT_TYPE_SESSION);
$tpl->assign('courses', $courses); $tpl->assign('courses', $courses);
$tpl->assign('sessions_are_included', $includeSession); $tpl->assign('sessions_are_included', $includeSession);
$tpl->assign('services_are_included', $includeServices);
if ($includeSession) { if ($includeSession) {
$sessions = $plugin->getSessionsForConfiguration(); $sessions = $plugin->getSessionsForConfiguration();
@ -43,6 +43,12 @@ if ($includeSession) {
$tpl->assign('sessions', $sessions); $tpl->assign('sessions', $sessions);
} }
if ($includeServices) {
$services = $plugin->getServices();
$tpl->assign('services', $services);
}
$content = $tpl->fetch('buycourses/view/configuration.tpl'); $content = $tpl->fetch('buycourses/view/configuration.tpl');
$tpl->assign('header', $templateName); $tpl->assign('header', $templateName);

@ -16,6 +16,7 @@ $plugin = BuyCoursesPlugin::create();
$paypalEnable = $plugin->get('paypal_enable'); $paypalEnable = $plugin->get('paypal_enable');
$commissionsEnable = $plugin->get('commissions_enable'); $commissionsEnable = $plugin->get('commissions_enable');
$includeServices = $plugin->get('include_services');
if (isset($_GET['order'])) { if (isset($_GET['order'])) {
$sale = $plugin->getSale($_GET['order']); $sale = $plugin->getSale($_GET['order']);
@ -170,6 +171,7 @@ if ($commissionsEnable == "true") {
$template->assign('form', $form->returnForm()); $template->assign('form', $form->returnForm());
$template->assign('selected_sale', $selectedSale); $template->assign('selected_sale', $selectedSale);
$template->assign('selected_status', $selectedStatus); $template->assign('selected_status', $selectedStatus);
$template->assign('services_are_included', $includeServices);
$template->assign('sale_list', $saleList); $template->assign('sale_list', $saleList);
$template->assign('sale_status_canceled', BuyCoursesPlugin::SALE_STATUS_CANCELED); $template->assign('sale_status_canceled', BuyCoursesPlugin::SALE_STATUS_CANCELED);
$template->assign('sale_status_pending', BuyCoursesPlugin::SALE_STATUS_PENDING); $template->assign('sale_status_pending', BuyCoursesPlugin::SALE_STATUS_PENDING);

@ -0,0 +1,35 @@
<?php
/* For license terms, see /license.txt */
/**
* Errors management for the Buy Courses plugin - Redirects to service_catalog.php with a error msg
* @package chamilo.plugin.buycourses
*/
/**
* Config
*/
require_once '../config.php';
if (isset($_SESSION['bc_service_sale_id'])) {
$plugin = BuyCoursesPlugin::create();
$serviceSaleId = $_SESSION['bc_service_sale_id'];
unset($_SESSION['bc_service_sale_id']);
$serviceSale = $plugin->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;

@ -0,0 +1,99 @@
<?php
/* For license terms, see /license.txt */
/**
* List of pending payments of the Buy Courses plugin
* @package chamilo.plugin.buycourses
*/
//Initialization
$cidReset = true;
require_once '../config.php';
api_protect_admin_script();
$plugin = BuyCoursesPlugin::create();
$paypalEnable = $plugin->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();

@ -0,0 +1,123 @@
<?php
/* For license terms, see /license.txt */
/**
* Create new Services for the Buy Courses plugin
* @package chamilo.plugin.buycourses
*/
/**
* Init
*/
$cidReset = true;
require_once '../../../main/inc/global.inc.php';
$plugin = BuyCoursesPlugin::create();
$currency = $plugin->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();

@ -0,0 +1,140 @@
<?php
/* For license terms, see /license.txt */
/**
* Create new Services for the Buy Courses plugin
* @package chamilo.plugin.buycourses
*/
/**
* Init
*/
$cidReset = true;
require_once '../../../main/inc/global.inc.php';
$serviceId = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : null;
if (!$serviceId) {
header('Location: configuration.php');
}
$plugin = BuyCoursesPlugin::create();
$currency = $plugin->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();

@ -1,5 +1,3 @@
<script type='text/javascript' src="../js/buycourses.js"></script>
<link rel="stylesheet" type="text/css" href="../resources/css/style.css"/> <link rel="stylesheet" type="text/css" href="../resources/css/style.css"/>
{% if sessions_are_included %} {% if sessions_are_included %}
@ -10,6 +8,11 @@
<li role="presentation"> <li role="presentation">
<a href="#sessions" aria-controls="sessions" role="tab" data-toggle="tab">{{ 'Sessions'|get_lang }}</a> <a href="#sessions" aria-controls="sessions" role="tab" data-toggle="tab">{{ 'Sessions'|get_lang }}</a>
</li> </li>
{% if services_are_included %}
<li role="presentation">
<a href="#services" aria-controls="services" role="tab" data-toggle="tab">{{ 'Services'|get_plugin_lang('BuyCoursesPlugin') }}</a>
</li>
{% endif %}
</ul> </ul>
{% endif %} {% endif %}
@ -131,4 +134,65 @@
</div> </div>
</div> </div>
{% endif %} {% endif %}
{% if services_are_included %}
<div role="tabpanel" class="tab-pane" id="services">
<div class="table-responsive">
<a href="{{ _p.web_plugin ~ 'buycourses/src/services_add.php' }}" class="btn btn-primary">
<em class="fa fa-cart-plus fa-fw"></em> {{ 'NewService'| get_plugin_lang('BuyCoursesPlugin') }}
</a>
</br>
</br>
<table id="services_table" class="table">
<thead>
<tr>
<th>{{ 'Service'|get_plugin_lang('BuyCoursesPlugin') }}</th>
<th>{{ 'Description'|get_lang }}</th>
<th class="text-center">{{ 'Duration'|get_plugin_lang('BuyCoursesPlugin') }}</th>
<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>
<th class="text-right">{{ 'Options'|get_lang }}</th>
</tr>
</thead>
<tbody>
{% for item in services %}
<tr data-item="{{ item.id }}" data-type="service">
<td>
{{ item.name }}
</td>
<td>
{{ item.description }}
</td>
<td class="text-center">
{% if item.duration_days == 0 %}
{{ 'NoLimit'|get_lang }}
{% else %}
{{ item.duration_days }} {{ 'Days'|get_lang }}
{% endif %}
</td>
<td class="text-center">
{% if item.visibility == 1 %}
<em class="fa fa-fw fa-check-square-o"></em>
{% else %}
<em class="fa fa-fw fa-square-o"></em>
{% endif %}
</td>
<td class="text-center">
{{ item.owner_name }}
</td>
<td class="text-right" width="200">
{{ "#{item.price} #{tem.currency ?: item.currency}" }}
</td>
<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">
<em class="fa fa-wrench fa-fw"></em> {{ 'Edit'|get_lang }}
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endif %}
</div> </div>

@ -1,3 +1,16 @@
<link rel="stylesheet" type="text/css" href="../resources/css/style.css"/>
<ul class="nav nav-tabs buy-courses-sessions-tabs" role="tablist">
<li id="buy-courses-sessions-tab" class="active" role="presentation">
<a href="sales_report.php" aria-controls="buy-courses_sessions" role="tab">{{ 'CourseSessionBlock'|get_lang }}</a>
</li>
{% if services_are_included %}
<li id="buy-services-tab" class="{{ showing_services ? 'active' : '' }}" role="presentation">
<a href="service_sales_report.php" aria-controls="buy-services" role="tab">{{ 'Services'|get_plugin_lang('BuyCoursesPlugin') }}</a>
</li>
{% endif %}
</ul>
</br>
</br>
{{ form }} {{ form }}
<div class="table-responsive"> <div class="table-responsive">

@ -0,0 +1,94 @@
<link rel="stylesheet" type="text/css" href="../resources/css/style.css"/>
<script type="text/javascript" src="../resources/js/modals.js"></script>
<div class="row">
<div class="col-md-3 col-sm-12 col-xs-12">
{{ form }}
</div>
<div class="col-md-9 col-sm-12 col-xs-12">
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead>
<tr>
<th class="text-center">{{ 'ServiceName'|get_plugin_lang('BuyCoursesPlugin') }}</th>
<th class="text-center">{{ 'OrderReference'|get_plugin_lang('BuyCoursesPlugin') }}</th>
<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>
<th class="text-center">{{ 'Renewable'|get_plugin_lang('BuyCoursesPlugin') }}</th>
<th class="text-center">{{ 'ServiceSaleInfo'|get_plugin_lang('BuyCoursesPlugin') }}</th>
</tr>
</thead>
<tbody>
{% for sale in sale_list %}
<tr>
<td class="text-center">{{ sale.service_name }}</td>
<td class="text-center">{{ sale.reference }}</td>
<td class="text-center">
{% 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 %}
</td>
<td class="text-center">{{ sale.date }}</td>
<td class="text-right">{{ sale.currency ~ ' ' ~ sale.price }}</td>
{% if sale.recurring_payment == 0 %}
<td class="text-center">{{ 'No' | get_lang }}</td>
{% else %}
<td class="text-center">
<a id="renewable_info" tag="{{ sale.id }}" name="r_{{ sale.id }}" class="btn btn-warning btn-sm">{{ 'Info' | get_lang }}</a>
</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>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<script>
$(document).on('ready', function () {
$("td a").click(function() {
var id = $(this).attr('tag');
var action = $(this).attr('id');
$.ajax({
data: 'id='+id,
url: '{{ _p.web_plugin }}buycourses/src/buycourses.ajax.php?a='+action,
type: 'POST',
beforeSend: function() {
if (action == 'renewable_info') {
$('a[name=r_'+id+']').html('<em class="fa fa-spinner fa-pulse"></em> {{ 'Loading' | get_lang }}');
} else if (action == 'service_sale_info') {
$('a[name=s_'+id+']').html('<em class="fa fa-spinner fa-pulse"></em> {{ 'Loading' | get_lang }}');
}
},
success: function(response) {
$('a[name=r_'+id+']').html('{{ 'Info' | get_lang }}');
$('a[name=s_'+id+']').html('{{ 'Info' | get_lang }}');
var title = "";
if (action == "renewable_info") {
title = "{{ 'RecurringPaymentProfilePaypalInformation' | get_plugin_lang('BuyCoursesPlugin') }}";
} else if (action == 'service_sale_info') {
title = "{{ 'ServiceSaleInfo' | get_plugin_lang('BuyCoursesPlugin') }}";
}
bootbox.dialog({
message: response,
title: title,
buttons: {
main: {
label: "{{ 'Close' | get_lang }}",
className: "btn-default"
}
}
});
}
})
});
});
</script>
Loading…
Cancel
Save