| Server IP : 14.225.216.240 / Your IP : 216.73.216.26 Web Server : nginx/1.20.1 System : Linux localhost.localdomain 5.14.0-596.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Fri Jun 27 16:02:33 UTC 2025 x86_64 User : taidh ( 1001) PHP Version : 8.3.19 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /home/pts/app/Module/Crm/Controller/ |
Upload File : |
<?php
// phpcs:ignore
namespace App\Module\Crm\Controller;
use App\Module\Crm\Model\Optional\ActivityType;
use App\Module\Crm\Model\Optional\ActStatusCode;
use App\Module\Crm\Model\Activity\Activity;
use App\Module\Crm\Model\Activity\DataField as ActivityDF;
use App\Module\Crm\Model\Opportunity\Opportunity;
use App\Module\Crm\Model\SaleFunnel;
use App\PTS\Customer\Model\DataField;
use App\PTS\Customer\Model\Customer;
use App\PTS\Customer\Model\Address;
use App\PTS\Helpers\Plugins\Common;
use stdClass;
use Validator;
use Exception;
/**
* Activity module
*
* @category Class
* @package App\Module\Crm\Controller
* @author Phung, Truong K <truongkimphung1982@gmail.com>
* @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License
* @link https://pts-digital.com/ PTS Digital Technology Co.,Ltd
*/
class ActivityController extends BaseController
{
/**
* Activity module
*
* @var string
*/
protected static $activityMod = 'activities';
/**
* Type code
*
* @var string
*/
protected static $activityType;
/**
* Type ID
*
* @var int
*/
protected static $activityTypeId;
/**
* Type ID
*
* @var string
*/
protected static $activityTypeName;
/**
* List of status codes
*
* @var array
*/
protected static $statusCodes;
/**
* Activity module construct
*/
public function __construct()
{
parent::__construct();
self::$activityType = $code = request()->activityType ?? request()->session()->get('activityType');
if (!empty($code ?? '')) {
$rs = ActivityType::getInstance()->getActivityType($code);
if (($rs->id ?? 0) < 1) {
redirect()->route('home.index')->send();
}
self::$activityTypeId = $rs->id ?? 0;
self::$activityTypeName = $rs->name ?? null;
view()->share('activityTypeId', self::$activityTypeId);
view()->share('activityTypeName', self::$activityTypeName);
view()->share('activityType', $code);
request()->session()->put('activityType', $code);
}
self::$cls = Activity::getInstance();
self::$statusCodes = ActStatusCode::getInstance()->getActStatusCodesByActive();
view()->share('fn', self::$fn);
view()->share('rAdd', Common::hasRoute('activity.add'));
view()->share('rEdit', Common::hasRoute('activity.edit'));
view()->share('rStatus', Common::hasRoute('activity.status'));
view()->share('rDelete', Common::hasRoute('activity.delete'));
view()->share('rLocked', Common::hasRoute('activity.locked'));
view()->share('rAssign', Common::hasRoute('activity.assign'));
view()->share('statusCodes', self::$statusCodes);
}
/**
* List of acivity results
* --------------------------------------------------------------------------
* GET /activities/{activeType}
* --------------------------------------------------------------------------
*
* @return \Illuminate\Contracts\Support\Arrayable|array $data
*/
public function index()
{
$this->access(['activity.index']);
$args = request()->all();
$result['resp'] = self::$cls->getActivities(self::$activityTypeId, $args);
$result['args'] = $this->filterArgs($args);
return view(self::$fn . 'activity.index', $result);
}
/**
* List of activity results for search advance
* --------------------------------------------------------------------------
* GET /activities/{activeType}/search
* --------------------------------------------------------------------------
*
* @return \Illuminate\Contracts\Support\Arrayable|array $data
*/
public function search()
{
$this->access(['activity.index']);
$args = request()->all();
$args = $this->filterArgs($args);
$result['args'] = $args;
$isSearch = false;
if (isset($args) && is_object($args) && $args != new stdClass()) {
$result['resp'] = self::$cls->getActivitiesBySearch(self::$activityTypeId, $args);
$isSearch = true;
}
$result['isSearch'] = $isSearch;
return view(self::$fn . 'activity.search', $result);
}
/**
* Getting activity information
* --------------------------------------------------------------------------
* GET /activities/{activeType}/{guid}
* --------------------------------------------------------------------------
*
* @return \Illuminate\Contracts\Support\Arrayable|array $data
*/
public function detail($activityType, $guid)
{
$this->access(['activity.index']);
$result['activity'] = $activity = self::$cls->getActivityByGuid($guid);
if (($activity->id ?? 0) < 1) {
self::$backURL = route('activity.index', ['activityType' => $activityType]);
$this->back();
}
if (($activity->app_id ?? 0) != self::$appId && self::$developMode == 0) {
$this->accessDeny();
}
$result['guid'] = $guid;
$result['fields'] = ActivityDF::getInstance()->getDataFieldsByUID($activity->id);
return view(self::$fn . 'activity.detail', $result);
}
/**
* Activity form
* --------------------------------------------------------------------------
* GET /activities/{activeType}/forms
* GET /activities/{activeType}/{id}/forms
* --------------------------------------------------------------------------
*
* @param string $activityType The code's activity type
* @param int $id The ID's activity
*
* @return \Illuminate\Contracts\Support\Arrayable|array $data
*/
public function form($activityType, $id=0)
{
$this->access(['activity.add','activity.edit']);
if ($id < 1) {
$id = request()->get('id', 0);
}
$locale = request()->get('locale', app()->getLocale());
$result['locale'] = $locale;
if ($id > 0) {
$activity = self::$cls->getActivityById($id, $locale);
if (($activity->id ?? 0) < 1) {
self::$backURL = route('activity.index', ['activityType' => $activityType]);
$this->back();
}
if (self::$appId != ($activity->app_id ?? 0) && self::$developMode < 1) {
$this->accessDeny();
}
$result['activity'] = $activity;
} else {
$oppId = request()->get('opp_id', '');
if (!empty($oppId ?? '')) {
$result['opportunity'] = Opportunity::getInstance()->getOpportunityById($oppId);
}
$customerId = request()->get('cid', '');
if (!empty($customerId ?? '')) {
$result['keyword'] = Common::base64Decrypt($customerId);
}
}
$fieldsByCode = null;
$fields = ActivityDF::getInstance()->getDataFieldsByUID($id, $locale, $fieldsByCode);
$result['fields'] = $fieldsByCode ?? $fields ?? [];
return view(self::$fn . 'activity.form', $result ?? []);
}
/**
* Add/update fields of activity
*
* @param int $activityId The ID's activity
* @param object $args The request arguments.
*
* @return void
*/
protected function addUpdateFields($activityId, $args)
{
$locale = $args->locale ?? app()->getLocale();
$activityFields = ($args->fields ?? []);
if (count($activityFields)) {
$fieldActivityDF = [];
$systemFields = null;
foreach ($activityFields as $k => $data) {
$argsField = (object)[
'customer_id' => $args->customer_id ?? 0,
'activity_id' => $activityId,
'code' => $k,
'data' => $data,
'locale' => $locale,
'point' => (int)($data['point'] ?? 0),
];
$df = ActivityDF::getInstance()->addUpdateFields($argsField, $systemFields);
if ($df != null) {
$fieldActivityDF[] = $df;
}
}
$systemFields = null;
if (count($fieldActivityDF) > 0) {
self::$cls->updateDataField($activityId, $fieldActivityDF);
}
}
}
/**
* Activity submission
* --------------------------------------------------------------------------
* POST /activities/{activeType}
* PUT /activities/{activeType}
* --------------------------------------------------------------------------
*
* @param string $activityType The code's activity type
*
* @return mixed $redirect
*/
public function save($activityType=null)
{
$this->access(['activity.add','activity.edit']);
$params = request()->all();
$rules = [
'name' => 'required|between:' . self::$nameMin . ',' . self::$nameMax
];
$messages = [
'name.required' => trans(self::$ns . '::activity.name.required'),
'name.between' => trans(
self::$ns . '::activity.name.between',
['min' => self::$nameMin, 'max' => self::$nameMax]
)];
$validator = Validator::make($params, $rules, $messages);
if ($validator->passes()) {
$statusCode = self::SUCCESS;
$args = (object)$params;
$resp = self::$cls->addUpdate(self::$activityTypeId, $args, $statusCode);
$errorCode = $resp->error_code ?? '';
$errorNo = $resp->error_no ?? self::ERROR_UNDEFINED;
if ($errorNo == self::SUCCESS) {
$activityId = $resp->id ?? 0;
if (isset($args->location)) {
$args->ref_id = $activityId;
$args->ref_type = self::$activityMod;
Address::getInstance()->addUpdate(Address::APPOINTMENT, $args);
}
$this->addUpdateFields($activityId, $args);
$msg = trans(self::$ns . '::activity.success.add');
return redirect()->route(
'activity.detail',
['activityType' => $activityType, 'guid' => $resp->guid ?? Common::guid()]
)->with('success', $msg);
}
if ($statusCode != self::SUCCESS) {
$msg = $this->getError($statusCode);
} else {
$errors = array_merge(trans('errors'), trans(self::$ns . '::activity.error'));
$msg = $errors[$errorCode] ?? '';
$msg = str_replace(':name', self::$activityTypeName, $msg);
}
$validator->messages()->add('error', $msg);
}
return redirect()->back()->withErrors($validator)->withInput();
}
/**
* Change status of activity result information
* --------------------------------------------------------------------------
* PUT /activities/{activeType}/{guid}/status
* --------------------------------------------------------------------------
*
* @param string $guid The ID's activity
*
* @return mixed $redirect
*/
public function status($guid=null)
{
$this->access('activity.status');
self::$information = self::$cls->getActivityByGuid($guid);
parent::status($guid);
}
/**
* Deleting activity result information
* --------------------------------------------------------------------------
* DELETE /activities/{activeType}/{guid}
* --------------------------------------------------------------------------
*
* @param string $guid The ID's activity
*
* @return mixed $redirect
*/
public function delete($guid=null)
{
$this->access('activity.delete');
self::$information = self::$cls->getActivityByGuid($guid);
self::$backURL = route('activity.index', ['activityType' => self::$activityType]);
parent::delete($guid);
}
/**
* Locking activity result
* --------------------------------------------------------------------------
* PUT /activities/{activeType}/{guid}/locking
* --------------------------------------------------------------------------
*
* @param string $guid The ID's activity
*
* @return mixed $redirect
*/
public function locking($guid=null)
{
$this->access('activity.locked');
self::$information = self::$cls->getActivityByGuid($guid);
parent::locking($guid);
}
/**
* Render template email
* --------------------------------------------------------------------------
* POST /activities/{activeType}/{guid}/email-template
* --------------------------------------------------------------------------
*
* @param string $activityType The code's activity type
* @param string $guid The ID's activity
*
* @return mixed $view
*/
public function emailTemplate($activityType, $guid)
{
$this->access(['activity.index']);
$result['activity'] = $activity = self::$cls->getActivityByGuid($guid);
if (($activity->id ?? 0) < 1) {
return redirect()->back();
}
if (($activity->app_id ?? 0) != self::$appId && self::$developMode == 0) {
$this->accessDeny();
}
$result['guid'] = $guid;
$result['activityType'] = $activityType;
$fieldsByCode = null;
$fields = ActivityDF::getInstance()->getDataFieldsByUID($activity->id, null, $fieldsByCode);
$result['fields'] = $fieldsByCode ?? $fields ?? [];
return view(self::$fn . 'activity.emailTemplate', $result);
}
/**
* Complete form
*
* @param string $activityType The code's activity type
* @param string $guid The ID's activity
*
* @return mixed $view
*/
public function completeForm($activityType, $guid)
{
$this->access(['activity.index']);
$result['activity'] = $activity = self::$cls->getActivityByGuid($guid);
if (($activity->id ?? 0) < 1) {
self::$backURL = route('activity.index', ['activityType' => $activityType]);
$this->back();
}
if (($activity->app_id ?? 0) != self::$appId && self::$developMode == 0) {
$this->accessDeny();
}
$result['guid'] = $guid;
$result['activityType'] = $activityType;
$fieldsByCode = null;
$fields = ActivityDF::getInstance()->getDataFieldsByUID($activity->id, null, $fieldsByCode);
$result['fields'] = $fieldsByCode ?? $fields ?? [];
return view(self::$fn . 'activity.completeForm', $result);
}
/**
* Add/update suggest product
*
* @param int $activityId The ID's activity
* @param int $customerId The ID's customer
* @param mixed $opportunityId The ID's opportunity
* @param mixed $productsSuggest The json suggest product
*
* @return void
*/
protected function addUpdateProduct($activityId, $customerId, $opportunityId, $productsSuggest=null)
{
if (!empty($productsSuggest ?? '')) {
try {
$productsSuggest = json_decode($productsSuggest);
} catch (Exception $e) {
logger()->error($e);
$productsSuggest = [];
}
if (count($productsSuggest ?? []) > 0) {
foreach ($productsSuggest as $elem) {
$elem = (object)$elem;
$elem->activity_id = $activityId;
$elem->customer_id = $customerId;
$elem->opportunity_id = $opportunityId ?? 0;
SaleFunnel::getInstance()->addUpdateProduct($elem);
}
}
}
}
/**
* Verify fields of customer profile
*
* @param int $activityId The ID's activity
* @param int $customerId The ID's customer
* @param int $fnType The bitwise of function
* @param mixed $args The request arguments
*
* @return void
*/
protected function verifiedFields($activityId, $customerId, $fnType, $args)
{
$locale = $args->locale ?? app()->getLocale();
$systemFields = null;
$verifiedFields = [];
$requiredVerifyField = (int)($args->fields['result']['required_verify_fields'] ?? 0);
$requiredVerifyFields = (array)($args->required_verify_fields ?? []);
// verified field by employee
if ((int)($fnType&config('constant.fnc.VERIFY_FIELD')) > 0 && count($requiredVerifyFields) > 0) {
foreach ($requiredVerifyFields as $k => $elem) {
$elem = (object)($elem);
$elem->code = $k;
$elem->activity_id = $activityId;
$df = DataField::getInstance()->addUpdateFields(
$customerId,
$elem,
($elem->id ?? 0),
$locale,
$elem->point ?? 0,
1,
$systemFields
);
if ($df != null) {
$verifiedFields = array_merge($verifiedFields, $df);
}
}
if (count($verifiedFields) > 0) {
Customer::getInstance()->updateVerifiedField($customerId, $verifiedFields);
}
} elseif ($requiredVerifyField > 0) {
// verified by system
$argsVerified = (object)[
'activity_id' => $activityId,
'customer_id' => $customerId,
'locale' => $locale,
];
$statusCode = self::SUCCESS;
DataField::getInstance()->verifiedFieldBySystem($requiredVerifyField, $argsVerified, $statusCode);
}
}
/**
* Clone activity
*
* @param string $activityType The code's activity type
* @param int $activityId The ID's activity
* @param int $fnType The bitwise of function
*
* @return mixed $redirect
*/
protected function cloneActivity($activityType, $activityId, $fnType)
{
// clone activity with
if ((int)($fnType&config('constant.fnc.ACTIVITY_CLONE')) > 0) {
$relate = self::$cls->cloneActivity($activityType, $activityId ?? 0);
if ((int)($relate->id ?? 0) > 0) {
return redirect()->route(
'activity.edit',
['activityType' => $activityType, 'id' => $relate->id]
)->with('success', trans(self::$ns . '::activity.success.clone'));
}
}
}
/**
* Report submission
*
* @param string $activityType The code's activity type
* @param string $guid The ID's activity
*
* @return mixed $redirect
*/
public function reportSubmission($activityType, $guid)
{
$this->access(['activity.index']);
$params = request()->all();
$fnType = (int)($params['fn_type'] ?? 0);
$stage = $params['stage'] ?? null;
$rules = ['description' => 'required'];
$messages = [
'actual_start.required' => trans('date.actual_start.required'),
'actual_end.required' => trans('date.actual_end.required'),
'description.required' => trans(self::$ns . '::activity.description.required')
];
if ($stage == config('status.default_complete')) {
$rules = array_merge(
$rules,
['actual_start' => 'required', 'actual_end' => 'required']
);
}
if ($fnType > 0 && (int)($fnType&(1<<0))==0) {
unset($rules['description']);
}
$validator = Validator::make($params, $rules, $messages);
if ($validator->passes()) {
$statusCode = self::SUCCESS;
$args = (object)$params;
$customerId = $args->customer_id ?? 0;
$productsSuggest = $args->products_suggest ?? null;
$resp = self::$cls->reportSubmission($guid, $args, $statusCode);
$errorCode = $resp->error_code ?? '';
$errorNo = $resp->error_no ?? self::ERROR_UNDEFINED;
$msg = null;
if ($errorNo == self::SUCCESS) {
$activityId = $resp->id ?? 0;
$args->activity_id = $activityId;
$args->customer_id = $customerId;
$this->addUpdateFields($activityId, $args);
$this->addUpdateProduct($activityId, $customerId, $args->opportunity_id ?? 0, $productsSuggest);
$this->verifiedFields($activityId, $customerId, $fnType, $args);
$this->cloneActivity($activityType, $activityId, $fnType);
return redirect()->route(
'activity.detail',
['activityType' => $activityType, 'guid' => $resp->guid ?? Common::guid()]
) ->with('success', trans(self::$ns . '::activity.success.' . $stage));
}
if ($statusCode != self::SUCCESS) {
$msg = $this->getError($statusCode);
} else {
$errors = array_merge(trans('errors'), (array)trans(self::$ns . '::activity.error'));
$msg = $errors[$errorCode] ?? '';
$msg = str_replace(':name', self::$activityTypeName, $msg);
}
$validator->messages()->add('error', $msg);
}
return redirect()->back()->withErrors($validator)->withInput();
}
/**
* Kanban board
* --------------------------------------------------------------------------
* GET /activities/kanban
* --------------------------------------------------------------------------
*
* @return mixed $view
*/
public function kanban()
{
$args = request()->all();
$args = $this->filterArgs($args);
if (empty($args->end_date ?? '')) {
$args->end_date = Common::date(time());
}
if (empty($args->start_date ?? '')) {
$args->start_date = Common::date(strtotime('-30 day'));
}
$result['resp'] = self::$cls->getActivitiesByKanban($args);
$result['args'] = $args;
return view(self::$ns .'::activity.kanban', $result);
}
/**
* Display email template
*
* @param string $activityType The code's activity type
* @param string $guid The GUID's activity
* @param int $type Optional Values {1: email, 0: complete}
*
* @return mixed $json
*/
protected function contact($activityType, $guid, $type=0)
{
$httpStatus = self::METHOD_NOT_ALLOWED;
$response = new stdClass;
if (request()->ajax()) {
$statusCode = self::SUCCESS;
$fnView = 0;
$resp = self::$cls->updateActualStart($guid, $fnView, $statusCode);
$errorNo = $resp->error_no ?? self::ERROR_UNDEFINED;
$errorCode = $resp->error_code ?? '';
if ($errorNo == self::SUCCESS) {
$httpStatus = self::OK;
$response->data = $resp->mobile ?? '';
$response->complete_url = route(
'activity.complete',
['activityType' => $activityType,'guid' => $guid]
);
if ($type == 1) {
$response->data = $resp->email ?? '';
$response->complete_url = route(
'activity.emailTemplate',
['activityType' => $activityType,'guid' => $guid]
);
}
} elseif ($statusCode != self::SUCCESS) {
$httpStatus = $statusCode;
} else {
$response->error = trans(self::$ns . '::activity.error.' . $errorCode);
}
}
if ($httpStatus != self::OK && empty($response->error ?? '')) {
$response->error = $this->getError($httpStatus);
}
return response()->json($response, $httpStatus);
}
/**
* Show Mobile
* --------------------------------------------------------------------------
* PUT /activities/{activityType}/show-mobile
* --------------------------------------------------------------------------
*
* @param string $activityType The code's activity type
* @param string $guid The ID's activity
*
* @return mixed $json
*/
public function showMobile($activityType, $guid)
{
return $this->contact($activityType, $guid);
}
/**
* Return email template
* --------------------------------------------------------------------------
* PUT /activities/{activityType}/show-email
* --------------------------------------------------------------------------
*
* @param string $activityType The code's activity type
* @param string $guid The ID's activity
*
* @return mixed $json
*/
public function showEmail($activityType, $guid)
{
return $this->contact($activityType, $guid, 1);
}
}