Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Тестовое задание #410

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
304 changes: 220 additions & 84 deletions php/v2/ReturnOperation.php
Original file line number Diff line number Diff line change
@@ -1,139 +1,275 @@
<?php

/*
* Изменения и улучшения:
*
* 1. Разделила код на логически завершенные методы, чтобы каждый метод возвращал ожидаемый результат и код был более читаемым.
* 2. Добавила проверку наличия основных параметров входящего запроса.
* 3. Методам добавлен модификатор доступа private для ограничения доступа за пределами класса.
* 4. Переименовала некоторые переменные на более понятные названия.
* 5. Файл others.php оставила без изменений, так как не была уверена, что можно исправлять.
*/


namespace NW\WebService\References\Operations\Notification;

use Exception;

class TsReturnOperation extends ReferencesOperation
{
public const TYPE_NEW = 1;
public const TYPE_CHANGE = 2;

/**
* @throws \Exception
* @return array
* @throws Exception
*/
public function doOperation(): void
public function doOperation(): array
{
$data = $this->getValidateRequestData();
$reseller = $this->getReseller($data['resellerId']);
$client = $this->getClient($data);
$creator = $this->getEmployeeByType((int)$data['creatorId'], 'creator');
$expert = $this->getEmployeeByType((int)$data['expertId'], 'expert');
$differences = $this->getDifferences($data);
$templateData = $this->getTemplateData($data, $creator, $expert, $client, $differences);

return $this->sendNotifications($templateData, $reseller, $client, $data);

}

/**
* @throws Exception
*/
protected function getValidateRequestData(): array
{
$data = (array)$this->getRequest('data');
$resellerId = $data['resellerId'];
$notificationType = (int)$data['notificationType'];
$result = [
'notificationEmployeeByEmail' => false,
'notificationClientByEmail' => false,
'notificationClientBySms' => [
'isSent' => false,
'message' => '',
],
];

if (empty((int)$resellerId)) {
$result['notificationClientBySms']['message'] = 'Empty resellerId';
return $result;
if (empty((int)$data['resellerId'])) {
throw new Exception('Empty resellerId', 400);
}

if (empty((int)$notificationType)) {
throw new \Exception('Empty notificationType', 400);
if (empty((int)$data['notificationType'])) {
throw new Exception('Empty notificationType', 400);
}

$reseller = Seller::getById((int)$resellerId);
return $data;
}


/**
* Получаем reseller по Ид
*
* @param int $resellerId
* @return Seller
* @throws Exception
*/
private function getReseller(int $resellerId): Seller
{
$reseller = Seller::getById($resellerId);

if ($reseller === null) {
throw new \Exception('Seller not found!', 400);
throw new Exception('Seller not found!', 400);
}

return $reseller;
}

/**
* Получаем данные клиента по Ид
*
* @param array $data
* @return Contractor
* @throws Exception
*/
private function getClient(array $data): Contractor
{
$client = Contractor::getById((int)$data['clientId']);
if ($client === null || $client->type !== Contractor::TYPE_CUSTOMER || $client->Seller->id !== $resellerId) {
throw new \Exception('сlient not found!', 400);
}

$cFullName = $client->getFullName();
if (empty($client->getFullName())) {
$cFullName = $client->name;
if ($client === null ||
$client->type !== Contractor::TYPE_CUSTOMER ||
$client->id !== (int)$data['resellerId']) {
throw new Exception('Client not found or unauthorized!', 400);
}

$cr = Employee::getById((int)$data['creatorId']);
if ($cr === null) {
throw new \Exception('Creator not found!', 400);
}
return $client;
}

/**
* Получаем данные сотрудника по Ид
*
* @param int $employeeId
* @param string $type
* @return Employee
* @throws Exception
*/
private function getEmployeeByType(int $employeeId, string $type): Employee
{
$employee = Employee::getById($employeeId);

$et = Employee::getById((int)$data['expertId']);
if ($et === null) {
throw new \Exception('Expert not found!', 400);
if ($employee === null) {
throw new Exception(ucfirst($type) . ' not found!', 400);
}

$differences = '';
if ($notificationType === self::TYPE_NEW) {
$differences = __('NewPositionAdded', null, $resellerId);
} elseif ($notificationType === self::TYPE_CHANGE && !empty($data['differences'])) {
return $employee;
}

/**
*
* @param array $data
* @return mixed
*/
private function getDifferences(array $data)
{
if ((int)$data['notificationType'] === self::TYPE_NEW) {
$differences = __('NewPositionAdded', null, $data['resellerId']);
} elseif ((int)$data['notificationType']=== self::TYPE_CHANGE && !empty($data['differences'])) {
$differences = __('PositionStatusHasChanged', [
'FROM' => Status::getName((int)$data['differences']['from']),
'TO' => Status::getName((int)$data['differences']['to']),
], $resellerId);
'FROM' => Status::getName((int)$data['differences']['from']),
'TO' => Status::getName((int)$data['differences']['to']),
], $data['resellerId']);
}

return $differences ?? null;
}


private function getTemplateData(
array $data,
Employee $creator,
Employee $expert,
Contractor $client,
string $differences
): array {
$templateData = [
'COMPLAINT_ID' => (int)$data['complaintId'],
'COMPLAINT_NUMBER' => (string)$data['complaintNumber'],
'CREATOR_ID' => (int)$data['creatorId'],
'CREATOR_NAME' => $cr->getFullName(),
'EXPERT_ID' => (int)$data['expertId'],
'EXPERT_NAME' => $et->getFullName(),
'CLIENT_ID' => (int)$data['clientId'],
'CLIENT_NAME' => $cFullName,
'CREATOR_ID' => $creator->id,
'CREATOR_NAME' => $creator->getFullName(),
'EXPERT_ID' => $expert->id,
'EXPERT_NAME' => $expert->getFullName(),
'CLIENT_ID' => $client->id,
'CLIENT_NAME' => $client->getFullName() ?? $client->name,
'CONSUMPTION_ID' => (int)$data['consumptionId'],
'CONSUMPTION_NUMBER' => (string)$data['consumptionNumber'],
'AGREEMENT_NUMBER' => (string)$data['agreementNumber'],
'DATE' => (string)$data['date'],
'DIFFERENCES' => $differences,
];

// Если хоть одна переменная для шаблона не задана, то не отправляем уведомления
// Проверяем, что все необходимые данные заполнены
foreach ($templateData as $key => $tempData) {
if (empty($tempData)) {
throw new \Exception("Template Data ({$key}) is empty!", 500);
if ($tempData === '' || $tempData === null) {
throw new \Exception("Template Data ({$key}) is empty!", 400);
}
}

$emailFrom = getResellerEmailFrom($resellerId);
// Получаем email сотрудников из настроек
$emails = getEmailsByPermit($resellerId, 'tsGoodsReturn');
if (!empty($emailFrom) && count($emails) > 0) {
foreach ($emails as $email) {
MessagesClient::sendMessage([
0 => [ // MessageTypes::EMAIL
'emailFrom' => $emailFrom,
'emailTo' => $email,
'subject' => __('complaintEmployeeEmailSubject', $templateData, $resellerId),
'message' => __('complaintEmployeeEmailBody', $templateData, $resellerId),
],
], $resellerId, NotificationEvents::CHANGE_RETURN_STATUS);
$result['notificationEmployeeByEmail'] = true;
return $templateData;
}

}

private function sendNotifications(
array $templateData,
Seller $reseller,
Contractor $client,
array $data
): array {

$result = [
'notificationEmployeeByEmail' => false,
'notificationClientByEmail' => false,
'notificationClientBySms' => [
'isSent' => false,
'message' => '',
],
];

$emailFrom = getResellerEmailFrom();

// Отправляем уведомления на email сотрудникам
$this->sendEmployeeNotifications($emailFrom, $client->id, $reseller->id, $reseller->id, $templateData, $result);

// Отправляем уведомления клиенту, если изменен статус
if ($data['notificationType'] === self::TYPE_CHANGE && !empty($data['differences']['to'])) {
$this->sendClientNotifications($emailFrom, $client, $templateData, $reseller->id, $data['differences']['to'], $result);
}

// Шлём клиентское уведомление, только если произошла смена статуса
if ($notificationType === self::TYPE_CHANGE && !empty($data['differences']['to'])) {
if (!empty($emailFrom) && !empty($client->email)) {
MessagesClient::sendMessage([
0 => [ // MessageTypes::EMAIL
'emailFrom' => $emailFrom,
'emailTo' => $client->email,
'subject' => __('complaintClientEmailSubject', $templateData, $resellerId),
'message' => __('complaintClientEmailBody', $templateData, $resellerId),
],
], $resellerId, $client->id, NotificationEvents::CHANGE_RETURN_STATUS, (int)$data['differences']['to']);
$result['notificationClientByEmail'] = true;
return $result;
}

private function sendEmployeeNotifications(
?string $emailFrom,
int $clientId,
int $resellerId,
int $statusTo,
array $templateData,
array &$result
): void
{
$employeeEmails = getEmailsByPermit($resellerId, 'tsGoodsReturn');
if (!empty($emailFrom) && count($employeeEmails) > 0) {
foreach ($employeeEmails as $email) {
$this->sendEmailNotification($emailFrom, $email, $templateData, $resellerId, $clientId, $statusTo);
}

if (!empty($client->mobile)) {
$res = NotificationManager::send($resellerId, $client->id, NotificationEvents::CHANGE_RETURN_STATUS, (int)$data['differences']['to'], $templateData, $error);
if ($res) {
$result['notificationClientBySms']['isSent'] = true;
}
if (!empty($error)) {
$result['notificationClientBySms']['message'] = $error;
}
$result['notificationEmployeeByEmail'] = true;
}
}

private function sendClientNotifications(
?string $emailFrom,
Contractor $client,
array $templateData,
int $resellerId,
int $statusTo,
array &$result
): void {
// Отправка email уведомления клиенту
if ($emailFrom && $client->email) {
$this->sendEmailNotification($emailFrom, $client->email, $templateData, $resellerId, $client->id, $statusTo);
$result['notificationClientByEmail'] = true;
}

// Отправка SMS уведомления клиенту
if (!empty($client->mobile)) {
$error = '';
$result['notificationClientBySms']['isSent'] = NotificationManager::send(
$resellerId,
$client->id,
NotificationEvents::CHANGE_RETURN_STATUS,
$statusTo,
$templateData,
$error
);

if ($error) {
$result['notificationClientBySms']['message'] = $error;
}
}
}

return $result;
private function sendEmailNotification(
string $emailFrom,
string $emailTo,
array $templateData,
int $resellerId,
int $clientId,
int $statusTo
): void {
MessagesClient::sendMessage(
[
[
'emailFrom' => $emailFrom,
'emailTo' => $emailTo,
'subject' => __('complaintClientEmailSubject', $templateData, $resellerId),
'message' => __('complaintClientEmailBody', $templateData, $resellerId),
],
],
$resellerId,
$clientId,
NotificationEvents::CHANGE_RETURN_STATUS,
$statusTo
);
}

}
Loading