mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-11-03 23:17:32 -05:00 
			
		
		
		
	Merge pull request #9209 from turbo124/v5-develop
Adjustments for logic for sending payment emails
This commit is contained in:
		
						commit
						f18ac57545
					
				@ -11,27 +11,29 @@
 | 
			
		||||
 | 
			
		||||
namespace App\Export\CSV;
 | 
			
		||||
 | 
			
		||||
use App\Models\Task;
 | 
			
		||||
use App\Models\User;
 | 
			
		||||
use App\Models\Quote;
 | 
			
		||||
use App\Models\Client;
 | 
			
		||||
use App\Models\ClientContact;
 | 
			
		||||
use App\Models\Company;
 | 
			
		||||
use App\Models\Credit;
 | 
			
		||||
use App\Models\Document;
 | 
			
		||||
use App\Models\Vendor;
 | 
			
		||||
use App\Utils\Helpers;
 | 
			
		||||
use App\Models\Company;
 | 
			
		||||
use App\Models\Expense;
 | 
			
		||||
use App\Models\Invoice;
 | 
			
		||||
use App\Models\Payment;
 | 
			
		||||
use App\Models\Product;
 | 
			
		||||
use App\Models\PurchaseOrder;
 | 
			
		||||
use App\Models\Quote;
 | 
			
		||||
use App\Models\RecurringInvoice;
 | 
			
		||||
use App\Models\Task;
 | 
			
		||||
use App\Models\Vendor;
 | 
			
		||||
use App\Transformers\PaymentTransformer;
 | 
			
		||||
use App\Transformers\TaskTransformer;
 | 
			
		||||
use App\Utils\Helpers;
 | 
			
		||||
use App\Utils\Traits\MakesHash;
 | 
			
		||||
use Illuminate\Database\Eloquent\Builder;
 | 
			
		||||
use Illuminate\Support\Carbon;
 | 
			
		||||
use App\Models\Document;
 | 
			
		||||
use League\Fractal\Manager;
 | 
			
		||||
use App\Models\ClientContact;
 | 
			
		||||
use App\Models\PurchaseOrder;
 | 
			
		||||
use Illuminate\Support\Carbon;
 | 
			
		||||
use App\Utils\Traits\MakesHash;
 | 
			
		||||
use App\Models\RecurringInvoice;
 | 
			
		||||
use App\Jobs\Document\ZipDocuments;
 | 
			
		||||
use App\Transformers\TaskTransformer;
 | 
			
		||||
use App\Transformers\PaymentTransformer;
 | 
			
		||||
use Illuminate\Database\Eloquent\Builder;
 | 
			
		||||
use League\Fractal\Serializer\ArraySerializer;
 | 
			
		||||
 | 
			
		||||
class BaseExport
 | 
			
		||||
@ -1258,4 +1260,32 @@ class BaseExport
 | 
			
		||||
        return $clean_row;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function queueDocuments(Builder $query)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        if($query->getModel() instanceof Document)
 | 
			
		||||
            $documents = $query->pluck('id')->toArray();
 | 
			
		||||
        else{
 | 
			
		||||
            $documents = $query->cursor()
 | 
			
		||||
                               ->map(function ($entity){
 | 
			
		||||
                                      return $entity->documents()->pluck('id')->toArray();
 | 
			
		||||
                               })->flatten()
 | 
			
		||||
                               ->toArray();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        nlog($documents);
 | 
			
		||||
        if(count($documents) > 0) {
 | 
			
		||||
 | 
			
		||||
            $user = $this->company->owner();
 | 
			
		||||
 | 
			
		||||
            if(auth()->user() && auth()->user()->account_id == $this->company->account_id)
 | 
			
		||||
                $user = auth()->user();
 | 
			
		||||
 | 
			
		||||
            if($this->input['user_id'])
 | 
			
		||||
                $user = User::where('id', $this->input['user_id'])->where('account_id', $this->company->account_id)->first();
 | 
			
		||||
 | 
			
		||||
            ZipDocuments::dispatch($documents, $this->company, $user);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -131,6 +131,10 @@ class ClientExport extends BaseExport
 | 
			
		||||
 | 
			
		||||
        $query = $this->addDateRange($query);
 | 
			
		||||
 | 
			
		||||
        if($this->input['document_email_attachment'] ?? false) {
 | 
			
		||||
            $this->queueDocuments($query);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $query;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -107,6 +107,10 @@ class CreditExport extends BaseExport
 | 
			
		||||
 | 
			
		||||
        $query = $this->addDateRange($query);
 | 
			
		||||
        
 | 
			
		||||
        if($this->input['document_email_attachment'] ?? false) {
 | 
			
		||||
            $this->queueDocuments($query);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $query;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -78,6 +78,10 @@ class DocumentExport extends BaseExport
 | 
			
		||||
 | 
			
		||||
        $query = $this->addDateRange($query);
 | 
			
		||||
        
 | 
			
		||||
        if($this->input['document_email_attachment'] ?? false) {
 | 
			
		||||
            $this->queueDocuments($query);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $query;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -104,6 +104,10 @@ class ExpenseExport extends BaseExport
 | 
			
		||||
            $query = $this->addCategoryFilter($query, $this->input['categories']);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        if($this->input['document_email_attachment'] ?? false) {
 | 
			
		||||
            $this->queueDocuments($query);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $query;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -62,10 +62,14 @@ class InvoiceExport extends BaseExport
 | 
			
		||||
 | 
			
		||||
        $query = $this->addDateRange($query);
 | 
			
		||||
 | 
			
		||||
        if(isset($this->input['status'])) {
 | 
			
		||||
        if($this->input['status'] ?? false) {
 | 
			
		||||
            $query = $this->addInvoiceStatusFilter($query, $this->input['status']);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if($this->input['document_email_attachment'] ?? false) {
 | 
			
		||||
            $this->queueDocuments($query);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $query;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
@ -120,15 +124,11 @@ class InvoiceExport extends BaseExport
 | 
			
		||||
            if (is_array($parts) && $parts[0] == 'invoice' && array_key_exists($parts[1], $transformed_invoice)) {
 | 
			
		||||
                $entity[$key] = $transformed_invoice[$parts[1]];
 | 
			
		||||
            } else {
 | 
			
		||||
                // nlog($key);
 | 
			
		||||
                $entity[$key] = $this->decorator->transform($key, $invoice);
 | 
			
		||||
                // $entity[$key] = '';
 | 
			
		||||
                // $entity[$key] = $this->resolveKey($key, $invoice, $this->invoice_transformer);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // return $entity;
 | 
			
		||||
        return $this->decorateAdvancedFields($invoice, $entity);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -167,7 +167,6 @@ class InvoiceExport extends BaseExport
 | 
			
		||||
            $entity['invoice.user_id'] = $invoice->user ? $invoice->user->present()->name() : '';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
nlog($entity);
 | 
			
		||||
        return $entity;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -77,6 +77,10 @@ class InvoiceItemExport extends BaseExport
 | 
			
		||||
 | 
			
		||||
        $query = $this->applyFilters($query);
 | 
			
		||||
        
 | 
			
		||||
        if($this->input['document_email_attachment'] ?? false) {
 | 
			
		||||
            $this->queueDocuments($query);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $query;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
@ -91,7 +95,6 @@ class InvoiceItemExport extends BaseExport
 | 
			
		||||
            return ['identifier' => $key, 'display_value' => $headerdisplay[$value]];
 | 
			
		||||
        })->toArray();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        $query->cursor()
 | 
			
		||||
            ->each(function ($resource) {
 | 
			
		||||
                $this->iterateItems($resource);
 | 
			
		||||
 | 
			
		||||
@ -61,6 +61,10 @@ class PaymentExport extends BaseExport
 | 
			
		||||
 | 
			
		||||
        $query = $this->addDateRange($query);
 | 
			
		||||
        
 | 
			
		||||
        if($this->input['document_email_attachment'] ?? false) {
 | 
			
		||||
            $this->queueDocuments($query);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $query;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -78,6 +78,10 @@ class ProductExport extends BaseExport
 | 
			
		||||
 | 
			
		||||
        $query = $this->addDateRange($query);
 | 
			
		||||
        
 | 
			
		||||
        if($this->input['document_email_attachment'] ?? false) {
 | 
			
		||||
            $this->queueDocuments($query);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $query;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -108,6 +108,10 @@ class PurchaseOrderExport extends BaseExport
 | 
			
		||||
 | 
			
		||||
        $query = $this->addDateRange($query);
 | 
			
		||||
        
 | 
			
		||||
        if($this->input['document_email_attachment'] ?? false) {
 | 
			
		||||
            $this->queueDocuments($query);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $query;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -67,6 +67,10 @@ class PurchaseOrderItemExport extends BaseExport
 | 
			
		||||
 | 
			
		||||
        $query = $this->addDateRange($query);
 | 
			
		||||
 | 
			
		||||
        if($this->input['document_email_attachment'] ?? false) {
 | 
			
		||||
            $this->queueDocuments($query);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $query;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -69,6 +69,10 @@ class QuoteExport extends BaseExport
 | 
			
		||||
 | 
			
		||||
        $query = $this->addDateRange($query);
 | 
			
		||||
 | 
			
		||||
        if($this->input['document_email_attachment'] ?? false) {
 | 
			
		||||
            $this->queueDocuments($query);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $query;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -70,6 +70,10 @@ class QuoteItemExport extends BaseExport
 | 
			
		||||
 | 
			
		||||
        $query = $this->addDateRange($query);
 | 
			
		||||
        
 | 
			
		||||
        if($this->input['document_email_attachment'] ?? false) {
 | 
			
		||||
            $this->queueDocuments($query);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $query;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -72,6 +72,10 @@ class TaskExport extends BaseExport
 | 
			
		||||
 | 
			
		||||
        $query = $this->addDateRange($query);
 | 
			
		||||
 | 
			
		||||
        if($this->input['document_email_attachment'] ?? false) {
 | 
			
		||||
            $this->queueDocuments($query);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $query;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -66,6 +66,10 @@ class VendorExport extends BaseExport
 | 
			
		||||
 | 
			
		||||
        $query = $this->addDateRange($query);
 | 
			
		||||
 | 
			
		||||
        if($this->input['document_email_attachment'] ?? false) {
 | 
			
		||||
            $this->queueDocuments($query);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $query;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -37,6 +37,7 @@ class GenericReportRequest extends Request
 | 
			
		||||
            'start_date' => 'bail|required_if:date_range,custom|nullable|date',
 | 
			
		||||
            'report_keys' => 'present|array',
 | 
			
		||||
            'send_email' => 'required|bool',
 | 
			
		||||
            'document_email_attachment' => 'sometimes|bool'
 | 
			
		||||
            // 'status' => 'sometimes|string|nullable|in:all,draft,sent,viewed,paid,unpaid,overdue',
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
@ -62,6 +63,8 @@ class GenericReportRequest extends Request
 | 
			
		||||
            $input['end_date'] = null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $input['user_id'] = auth()->user()->id;
 | 
			
		||||
 | 
			
		||||
        $this->replace($input);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -49,9 +49,9 @@ class ZipDocuments implements ShouldQueue
 | 
			
		||||
    public $tries = 1;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param $invoices
 | 
			
		||||
     * @param array $document_ids
 | 
			
		||||
     * @param Company $company
 | 
			
		||||
     * @param $email
 | 
			
		||||
     * @param User $user
 | 
			
		||||
     * @deprecated confirm to be deleted
 | 
			
		||||
     * Create a new job instance.
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
@ -68,7 +68,7 @@ class EmailPayment implements ShouldQueue
 | 
			
		||||
            $this->payment->load('invoices');
 | 
			
		||||
 | 
			
		||||
            if (!$this->contact) {
 | 
			
		||||
                $this->contact = $this->payment->client->contacts()->first();
 | 
			
		||||
                $this->contact = $this->payment->client->contacts()->orderBy('is_primary', 'desc')->first();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $this->contact->load('client');
 | 
			
		||||
 | 
			
		||||
@ -48,8 +48,6 @@ class PreviewReport implements ShouldQueue
 | 
			
		||||
            $report = $export->run();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // nlog($report);
 | 
			
		||||
 | 
			
		||||
        Cache::put($this->hash, $report, 60 * 60);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -14,22 +14,38 @@ namespace App\Services\Payment;
 | 
			
		||||
use App\Jobs\Payment\EmailPayment;
 | 
			
		||||
use App\Models\ClientContact;
 | 
			
		||||
use App\Models\Payment;
 | 
			
		||||
use Illuminate\Database\QueryException;
 | 
			
		||||
 | 
			
		||||
class SendEmail
 | 
			
		||||
{
 | 
			
		||||
    public function __construct(public Payment $payment, public ?ClientContact $contact)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
    public function __construct(public Payment $payment, public ?ClientContact $contact) {}
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Builds the correct template to send.
 | 
			
		||||
     */
 | 
			
		||||
    public function run()
 | 
			
		||||
    {
 | 
			
		||||
        $this->payment->load('company', 'client.contacts', 'invoices');
 | 
			
		||||
        $this->payment->load('company', 'invoices');
 | 
			
		||||
 | 
			
		||||
        if (!$this->contact) {
 | 
			
		||||
            $this->contact = $this->payment->client->contacts()->first();
 | 
			
		||||
 | 
			
		||||
            if($invoice = $this->payment->invoices->first() ?? false) {
 | 
			
		||||
 | 
			
		||||
                $invitation =
 | 
			
		||||
                $invoice
 | 
			
		||||
                    ->invitations()
 | 
			
		||||
                    ->whereHas("contact", function ($q) {
 | 
			
		||||
                        $q->where('send_email', true)->orderBy("is_primary", 'ASC');
 | 
			
		||||
                    })
 | 
			
		||||
                    ->first();
 | 
			
		||||
 | 
			
		||||
                if($invitation) {
 | 
			
		||||
                    $this->contact = $invitation->contact;
 | 
			
		||||
                } else {
 | 
			
		||||
                    $this->contact = $this->payment->client->contacts()->orderBy('send_email', 'desc')->orderBy('is_primary', 'desc')->first();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        EmailPayment::dispatch($this->payment, $this->payment->company, $this->contact);
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,7 @@ return new class extends Migration
 | 
			
		||||
            ->cursor()
 | 
			
		||||
            ->each(function (Invoice $invoice) {    
 | 
			
		||||
                
 | 
			
		||||
                $hit = false;
 | 
			
		||||
 | 
			
		||||
                $line_items = $invoice->line_items;
 | 
			
		||||
 | 
			
		||||
@ -35,15 +36,19 @@ return new class extends Migration
 | 
			
		||||
 | 
			
		||||
                        if($product = Product::where('company_id', $invoice->company_id)->where('product_key', $item->product_key)->where('cost', '>', 0)->first())
 | 
			
		||||
                        {
 | 
			
		||||
                            if((property_exists($item, 'product_cost') && $item->product_cost == 0) || !property_exists($item, 'product_cost'))
 | 
			
		||||
                            if((property_exists($item, 'product_cost') && $item->product_cost == 0) || !property_exists($item, 'product_cost')){
 | 
			
		||||
                                $hit = true;
 | 
			
		||||
                                $line_items[$key]->product_cost = (float)$product->cost;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        
 | 
			
		||||
                    }
 | 
			
		||||
                    
 | 
			
		||||
                    if($hit){
 | 
			
		||||
                        $invoice->line_items = $line_items;
 | 
			
		||||
                        $invoice->saveQuietly();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -11,10 +11,22 @@
 | 
			
		||||
 | 
			
		||||
namespace Tests\Unit;
 | 
			
		||||
 | 
			
		||||
use App\Helpers\Invoice\InvoiceSum;
 | 
			
		||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
 | 
			
		||||
use Tests\MockAccountData;
 | 
			
		||||
use Tests\TestCase;
 | 
			
		||||
use App\Models\Invoice;
 | 
			
		||||
use Tests\MockAccountData;
 | 
			
		||||
use App\Helpers\Invoice\InvoiceSum;
 | 
			
		||||
use App\Models\Client;
 | 
			
		||||
use App\Models\Credit;
 | 
			
		||||
use App\Models\Document;
 | 
			
		||||
use App\Models\Expense;
 | 
			
		||||
use App\Models\Payment;
 | 
			
		||||
use App\Models\Product;
 | 
			
		||||
use App\Models\Project;
 | 
			
		||||
use App\Models\PurchaseOrder;
 | 
			
		||||
use App\Models\Quote;
 | 
			
		||||
use App\Models\Task;
 | 
			
		||||
use App\Models\Vendor;
 | 
			
		||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @test
 | 
			
		||||
@ -55,4 +67,21 @@ class EntityTest extends TestCase
 | 
			
		||||
 | 
			
		||||
        $this->assertEquals('InvoiceInvitation', class_basename($invitation));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function testDocumentRelationExists()
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        $this->assertTrue(method_exists(Invoice::class, 'documents'));
 | 
			
		||||
        $this->assertTrue(method_exists(Quote::class, 'documents'));
 | 
			
		||||
        $this->assertTrue(method_exists(Credit::class, 'documents'));
 | 
			
		||||
        $this->assertTrue(method_exists(PurchaseOrder::class, 'documents'));
 | 
			
		||||
        $this->assertTrue(method_exists(Client::class, 'documents'));
 | 
			
		||||
        $this->assertTrue(method_exists(Vendor::class, 'documents'));
 | 
			
		||||
        $this->assertTrue(method_exists(Product::class, 'documents'));
 | 
			
		||||
        $this->assertTrue(method_exists(Payment::class, 'documents'));
 | 
			
		||||
        $this->assertTrue(method_exists(Expense::class, 'documents'));
 | 
			
		||||
        $this->assertTrue(method_exists(Project::class, 'documents'));
 | 
			
		||||
        $this->assertTrue(method_exists(Task::class, 'documents'));
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user