mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-06-22 04:40:55 -04:00
Notify user on assignment of task
This commit is contained in:
parent
cb9e40d442
commit
45b43094b0
@ -186,7 +186,7 @@ class TransactionTransformer implements BankRevenueInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return Carbon::createFromFormat("d-m-Y", $input)->setTimezone($timezone_name)->format($date_format_default) ?? $input;
|
return Carbon::createFromFormat("d-m-Y", $input)->setTimezone($timezone_name)->format($date_format_default);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
return $input;
|
return $input;
|
||||||
}
|
}
|
||||||
|
@ -70,9 +70,9 @@ class ProRata
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @var \App\Models\RecurringInvoice $recurring_invoice **/
|
/** @var \App\Models\RecurringInvoice $recurring_invoice **/
|
||||||
$recurring_invoice = RecurringInvoice::find($invoice->recurring_id)->first();
|
$recurring_invoice = RecurringInvoice::find($invoice->recurring_id);
|
||||||
|
|
||||||
if (! $recurring_invoice) {
|
if (! $recurring_invoice) { // @phpstan-ignore-line
|
||||||
throw new \Exception("Invoice isn't attached to a recurring invoice");
|
throw new \Exception("Invoice isn't attached to a recurring invoice");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,6 @@ class PreviewPurchaseOrderRequest extends Request
|
|||||||
use CleanLineItems;
|
use CleanLineItems;
|
||||||
|
|
||||||
private ?Vendor $vendor = null;
|
private ?Vendor $vendor = null;
|
||||||
private string $entity_plural = '';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if the user is authorized to make this request.
|
* Determine if the user is authorized to make this request.
|
||||||
@ -72,7 +71,7 @@ class PreviewPurchaseOrderRequest extends Request
|
|||||||
{
|
{
|
||||||
$invitation = false;
|
$invitation = false;
|
||||||
|
|
||||||
if(! $this->entity_id ?? false) {
|
if(! isset($this->entity_id)) {
|
||||||
return $this->stubInvitation();
|
return $this->stubInvitation();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,12 +129,5 @@ class PreviewPurchaseOrderRequest extends Request
|
|||||||
return $entity;
|
return $entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function convertEntityPlural(string $entity): self
|
|
||||||
{
|
|
||||||
|
|
||||||
$this->entity_plural = 'purchase_orders';
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
71
app/Jobs/Task/TaskAssigned.php
Normal file
71
app/Jobs/Task/TaskAssigned.php
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Jobs\Task;
|
||||||
|
|
||||||
|
use App\Models\Task;
|
||||||
|
use App\Libraries\MultiDB;
|
||||||
|
use App\Services\Email\Email;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use App\Services\Email\EmailObject;
|
||||||
|
use Illuminate\Mail\Mailables\Address;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use App\Utils\Traits\Notifications\UserNotifies;
|
||||||
|
|
||||||
|
class TaskAssigned implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable;
|
||||||
|
use InteractsWithQueue;
|
||||||
|
use Queueable;
|
||||||
|
use SerializesModels;
|
||||||
|
use UserNotifies;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new job instance.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function __construct(private Task $task, private string $db)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(): void
|
||||||
|
{
|
||||||
|
|
||||||
|
MultiDB::setDb($this->db);
|
||||||
|
|
||||||
|
$company_user = $this->task->assignedCompanyUser();
|
||||||
|
|
||||||
|
if($this->findEntityAssignedNotification($company_user, 'task'))
|
||||||
|
{
|
||||||
|
$mo = new EmailObject();
|
||||||
|
$mo->subject = ctrans('texts.task_assigned_subject', ['task' => $this->task->number, 'date' => now()->setTimeZone($this->task->company->timezone()->name)->format($this->task->company->date_format()) ]);
|
||||||
|
$mo->body = ctrans('texts.task_assigned_body',['task' => $this->task->number, 'description' => $this->task->description ?? '', 'client' => $this->task->client ? $this->task->client->present()->name() : ' ']);
|
||||||
|
$mo->text_body = ctrans('texts.task_assigned_body',['task' => $this->task->number, 'description' => $this->task->description ?? '', 'client' => $this->task->client ? $this->task->client->present()->name() : ' ']);
|
||||||
|
$mo->company_key = $this->task->company->company_key;
|
||||||
|
$mo->html_template = 'email.template.generic';
|
||||||
|
$mo->to = [new Address($this->task->assigned_user->email, $this->task->assigned_user->present()->name())];
|
||||||
|
$mo->email_template_body = 'task_assigned_body';
|
||||||
|
$mo->email_template_subject = 'task_assigned_subject';
|
||||||
|
|
||||||
|
(new Email($mo, $this->task->company))->handle();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function failed($exception = null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -11,10 +11,11 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use App\Utils\Traits\MakesHash;
|
|
||||||
use Carbon\CarbonInterval;
|
use Carbon\CarbonInterval;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use App\Models\CompanyUser;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
|
use App\Utils\Traits\MakesHash;
|
||||||
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* App\Models\Task
|
* App\Models\Task
|
||||||
@ -332,4 +333,11 @@ class Task extends BaseModel
|
|||||||
})->toArray();
|
})->toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function assignedCompanyUser()
|
||||||
|
{
|
||||||
|
if(!$this->assigned_user_id)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return CompanyUser::where('company_id', $this->company_id)->where('user_id', $this->assigned_user_id)->first();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,26 +59,27 @@ class ClientContactObserver
|
|||||||
//ensure entity state is preserved
|
//ensure entity state is preserved
|
||||||
|
|
||||||
InvoiceInvitation::withTrashed()->where('client_contact_id', $client_contact_id)->cursor()->each(function ($invite) {
|
InvoiceInvitation::withTrashed()->where('client_contact_id', $client_contact_id)->cursor()->each(function ($invite) {
|
||||||
if ($invite->invoice()->doesnthave('invitations')) {
|
/** @var \App\Models\InvoiceInvitation $invite */
|
||||||
|
if ($invite->invoice()->doesnthave('invitations')) { // @phpstan-ignore-line
|
||||||
$invite->invoice->service()->createInvitations();
|
$invite->invoice->service()->createInvitations();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
QuoteInvitation::withTrashed()->where('client_contact_id', $client_contact_id)->cursor()->each(function ($invite) {
|
QuoteInvitation::withTrashed()->where('client_contact_id', $client_contact_id)->cursor()->each(function ($invite) {
|
||||||
if ($invite->quote()->doesnthave('invitations')) {
|
if ($invite->quote()->doesnthave('invitations')) { // @phpstan-ignore-line
|
||||||
$invite->quote->service()->createInvitations();
|
$invite->quote->service()->createInvitations();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
RecurringInvoiceInvitation::withTrashed()->where('client_contact_id', $client_contact_id)->cursor()->each(function ($invite) {
|
RecurringInvoiceInvitation::withTrashed()->where('client_contact_id', $client_contact_id)->cursor()->each(function ($invite) {
|
||||||
if ($invite->recurring_invoice()->doesnthave('invitations')) {
|
if ($invite->recurring_invoice()->doesnthave('invitations')) {// @phpstan-ignore-line
|
||||||
$invite->recurring_invoice->service()->createInvitations();
|
$invite->recurring_invoice->service()->createInvitations();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
CreditInvitation::withTrashed()->where('client_contact_id', $client_contact_id)->cursor()->each(function ($invite) {
|
CreditInvitation::withTrashed()->where('client_contact_id', $client_contact_id)->cursor()->each(function ($invite) {
|
||||||
if ($invite->credit()->doesnthave('invitations')) {
|
if ($invite->credit()->doesnthave('invitations')) {// @phpstan-ignore-line
|
||||||
$invite->credit->service()->createInvitations();
|
$invite->credit->service()->createInvitations();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -54,7 +54,6 @@ class TaskObserver
|
|||||||
$event = Webhook::EVENT_DELETE_TASK;
|
$event = Webhook::EVENT_DELETE_TASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$subscriptions = Webhook::where('company_id', $task->company_id)
|
$subscriptions = Webhook::where('company_id', $task->company_id)
|
||||||
->where('event_id', $event)
|
->where('event_id', $event)
|
||||||
->exists();
|
->exists();
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
namespace App\Repositories;
|
namespace App\Repositories;
|
||||||
|
|
||||||
use App\Factory\TaskFactory;
|
use App\Factory\TaskFactory;
|
||||||
|
use App\Jobs\Task\TaskAssigned;
|
||||||
use App\Models\Task;
|
use App\Models\Task;
|
||||||
use App\Utils\Traits\GeneratesCounter;
|
use App\Utils\Traits\GeneratesCounter;
|
||||||
use Illuminate\Database\QueryException;
|
use Illuminate\Database\QueryException;
|
||||||
@ -45,6 +46,10 @@ class TaskRepository extends BaseRepository
|
|||||||
$this->new_task = false;
|
$this->new_task = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(isset($data['assigned_user_id']) && $data['assigned_user_id'] != $task->assigned_user_id){
|
||||||
|
TaskAssigned::dispatch($task, $task->company->db)->delay(2);
|
||||||
|
}
|
||||||
|
|
||||||
$task->fill($data);
|
$task->fill($data);
|
||||||
$task->saveQuietly();
|
$task->saveQuietly();
|
||||||
|
|
||||||
|
@ -164,4 +164,9 @@ trait UserNotifies
|
|||||||
|
|
||||||
return count(array_intersect($required_notification, $company_user->notifications->email)) >= 1;
|
return count(array_intersect($required_notification, $company_user->notifications->email)) >= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function findEntityAssignedNotification(\App\Models\CompanyUser $company_user, string $entity)
|
||||||
|
{
|
||||||
|
return count(array_intersect(["{$entity}_assigned"], $company_user->notifications->email)) >= 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2880,19 +2880,6 @@ $lang = array(
|
|||||||
'refunded' => 'Refunded',
|
'refunded' => 'Refunded',
|
||||||
'marked_quote_as_sent' => 'Successfully marked quote as sent',
|
'marked_quote_as_sent' => 'Successfully marked quote as sent',
|
||||||
'custom_module_settings' => 'Custom Module Settings',
|
'custom_module_settings' => 'Custom Module Settings',
|
||||||
'ticket' => 'Ticket',
|
|
||||||
'tickets' => 'Tickets',
|
|
||||||
'ticket_number' => 'Ticket #',
|
|
||||||
'new_ticket' => 'New Ticket',
|
|
||||||
'edit_ticket' => 'Edit Ticket',
|
|
||||||
'view_ticket' => 'View Ticket',
|
|
||||||
'archive_ticket' => 'Archive Ticket',
|
|
||||||
'restore_ticket' => 'Restore Ticket',
|
|
||||||
'delete_ticket' => 'Delete Ticket',
|
|
||||||
'archived_ticket' => 'Successfully archived ticket',
|
|
||||||
'archived_tickets' => 'Successfully archived tickets',
|
|
||||||
'restored_ticket' => 'Successfully restored ticket',
|
|
||||||
'deleted_ticket' => 'Successfully deleted ticket',
|
|
||||||
'open' => 'Open',
|
'open' => 'Open',
|
||||||
'new' => 'New',
|
'new' => 'New',
|
||||||
'closed' => 'Closed',
|
'closed' => 'Closed',
|
||||||
@ -2909,14 +2896,6 @@ $lang = array(
|
|||||||
'assigned_to' => 'Assigned to',
|
'assigned_to' => 'Assigned to',
|
||||||
'reply' => 'Reply',
|
'reply' => 'Reply',
|
||||||
'awaiting_reply' => 'Awaiting reply',
|
'awaiting_reply' => 'Awaiting reply',
|
||||||
'ticket_close' => 'Close Ticket',
|
|
||||||
'ticket_reopen' => 'Reopen Ticket',
|
|
||||||
'ticket_open' => 'Open Ticket',
|
|
||||||
'ticket_split' => 'Split Ticket',
|
|
||||||
'ticket_merge' => 'Merge Ticket',
|
|
||||||
'ticket_update' => 'Update Ticket',
|
|
||||||
'ticket_settings' => 'Ticket Settings',
|
|
||||||
'updated_ticket' => 'Ticket Updated',
|
|
||||||
'mark_spam' => 'Mark as Spam',
|
'mark_spam' => 'Mark as Spam',
|
||||||
'local_part' => 'Local Part',
|
'local_part' => 'Local Part',
|
||||||
'local_part_unavailable' => 'Name taken',
|
'local_part_unavailable' => 'Name taken',
|
||||||
@ -2936,29 +2915,14 @@ $lang = array(
|
|||||||
'mime_types_help' => 'Comma separated list of allowed mime types, leave blank for all',
|
'mime_types_help' => 'Comma separated list of allowed mime types, leave blank for all',
|
||||||
'default_priority' => 'Default priority',
|
'default_priority' => 'Default priority',
|
||||||
'alert_new_comment_id' => 'New comment',
|
'alert_new_comment_id' => 'New comment',
|
||||||
'alert_comment_ticket_help' => 'Selecting a template will send a notification (to agent) when a comment is made.',
|
|
||||||
'alert_comment_ticket_email_help' => 'Comma separated emails to bcc on new comment.',
|
|
||||||
'new_ticket_notification_list' => 'Additional new ticket notifications',
|
|
||||||
'update_ticket_notification_list' => 'Additional new comment notifications',
|
'update_ticket_notification_list' => 'Additional new comment notifications',
|
||||||
'comma_separated_values' => 'admin@example.com, supervisor@example.com',
|
'comma_separated_values' => 'admin@example.com, supervisor@example.com',
|
||||||
'alert_ticket_assign_agent_id' => 'Ticket assignment',
|
|
||||||
'alert_ticket_assign_agent_id_hel' => 'Selecting a template will send a notification (to agent) when a ticket is assigned.',
|
|
||||||
'alert_ticket_assign_agent_id_notifications' => 'Additional ticket assigned notifications',
|
|
||||||
'alert_ticket_assign_agent_id_help' => 'Comma separated emails to bcc on ticket assignment.',
|
|
||||||
'alert_ticket_transfer_email_help' => 'Comma separated emails to bcc on ticket transfer.',
|
|
||||||
'alert_ticket_overdue_agent_id' => 'Ticket overdue',
|
|
||||||
'alert_ticket_overdue_email' => 'Additional overdue ticket notifications',
|
|
||||||
'alert_ticket_overdue_email_help' => 'Comma separated emails to bcc on ticket overdue.',
|
|
||||||
'alert_ticket_overdue_agent_id_help' => 'Selecting a template will send a notification (to agent) when a ticket becomes overdue.',
|
|
||||||
'default_agent' => 'Default Agent',
|
'default_agent' => 'Default Agent',
|
||||||
'default_agent_help' => 'If selected will automatically be assigned to all inbound tickets',
|
'default_agent_help' => 'If selected will automatically be assigned to all inbound tickets',
|
||||||
'show_agent_details' => 'Show agent details on responses',
|
'show_agent_details' => 'Show agent details on responses',
|
||||||
'avatar' => 'Avatar',
|
'avatar' => 'Avatar',
|
||||||
'remove_avatar' => 'Remove avatar',
|
'remove_avatar' => 'Remove avatar',
|
||||||
'ticket_not_found' => 'Ticket not found',
|
|
||||||
'add_template' => 'Add Template',
|
'add_template' => 'Add Template',
|
||||||
'updated_ticket_template' => 'Updated Ticket Template',
|
|
||||||
'created_ticket_template' => 'Created Ticket Template',
|
|
||||||
'archive_ticket_template' => 'Archive Template',
|
'archive_ticket_template' => 'Archive Template',
|
||||||
'restore_ticket_template' => 'Restore Template',
|
'restore_ticket_template' => 'Restore Template',
|
||||||
'archived_ticket_template' => 'Successfully archived template',
|
'archived_ticket_template' => 'Successfully archived template',
|
||||||
@ -5303,6 +5267,8 @@ $lang = array(
|
|||||||
'currency_bhutan_ngultrum' => 'Bhutan Ngultrum',
|
'currency_bhutan_ngultrum' => 'Bhutan Ngultrum',
|
||||||
'end_of_month' => 'End Of Month',
|
'end_of_month' => 'End Of Month',
|
||||||
'merge_e_invoice_to_pdf' => 'Merge E-Invoice and PDF',
|
'merge_e_invoice_to_pdf' => 'Merge E-Invoice and PDF',
|
||||||
|
'task_assigned_subject' => 'New task assignment [Task :task] [ :date ]',
|
||||||
|
'task_assigned_body' => 'You have been assigned task :task <br><br> Description: :description <br><br> Client: :client',
|
||||||
);
|
);
|
||||||
|
|
||||||
return $lang;
|
return $lang;
|
Loading…
x
Reference in New Issue
Block a user