diff --git a/VERSION.txt b/VERSION.txt
index b2198ea2611b..faea5e9484eb 100644
--- a/VERSION.txt
+++ b/VERSION.txt
@@ -1 +1 @@
-5.5.43
\ No newline at end of file
+5.5.44
\ No newline at end of file
diff --git a/app/Export/CSV/RecurringInvoiceExport.php b/app/Export/CSV/RecurringInvoiceExport.php
index 30accbd22511..1bacb9d6a301 100644
--- a/app/Export/CSV/RecurringInvoiceExport.php
+++ b/app/Export/CSV/RecurringInvoiceExport.php
@@ -54,6 +54,7 @@ class RecurringInvoiceExport extends BaseExport
'po_number' => 'po_number',
'private_notes' => 'private_notes',
'public_notes' => 'public_notes',
+ 'next_send_date' => 'next_send_date',
'status' => 'status_id',
'tax_name1' => 'tax_name1',
'tax_name2' => 'tax_name2',
@@ -66,6 +67,7 @@ class RecurringInvoiceExport extends BaseExport
'currency' => 'currency_id',
'vendor' => 'vendor_id',
'project' => 'project_id',
+ 'frequency' => 'frequency_id'
];
private array $decorate_keys = [
@@ -162,6 +164,8 @@ class RecurringInvoiceExport extends BaseExport
$entity['vendor'] = $invoice->vendor ? $invoice->vendor->name : '';
}
+ $entity['frequency'] = $invoice->frequencyForKey($invoice->frequency_id);
+
return $entity;
}
}
diff --git a/app/Filters/DocumentFilters.php b/app/Filters/DocumentFilters.php
index fade4950705a..bf7b589aeef0 100644
--- a/app/Filters/DocumentFilters.php
+++ b/app/Filters/DocumentFilters.php
@@ -11,6 +11,7 @@
namespace App\Filters;
+use App\Models\Company;
use App\Models\User;
use Illuminate\Database\Eloquent\Builder;
@@ -54,6 +55,15 @@ class DocumentFilters extends QueryFilters
return $this->builder->orderBy($sort_col[0], $sort_col[1]);
}
+
+ public function company_documents($value = 'false')
+ {
+ if($value == 'true')
+ return $this->builder->where('documentable_type', Company::class);
+
+ return $this->builder;
+ }
+
/**
* Returns the base query.
*
diff --git a/app/Http/Controllers/EmailController.php b/app/Http/Controllers/EmailController.php
index 17b3f8ff0a78..7c2e75966b91 100644
--- a/app/Http/Controllers/EmailController.php
+++ b/app/Http/Controllers/EmailController.php
@@ -131,8 +131,6 @@ class EmailController extends BaseController
if(Ninja::isHosted() && !$entity_obj->company->account->account_sms_verified)
return response(['message' => 'Please verify your account to send emails.'], 400);
- nlog($entity);
-
if($entity == 'purchaseOrder' || $entity == 'purchase_order' || $template == 'purchase_order' || $entity == 'App\Models\PurchaseOrder'){
return $this->sendPurchaseOrder($entity_obj, $data, $template);
}
@@ -141,7 +139,7 @@ class EmailController extends BaseController
if (! $invitation->contact->trashed() && $invitation->contact->email) {
$entity_obj->service()->markSent()->save();
- EmailEntity::dispatch($invitation->fresh(), $invitation->company, $template, $data);
+ EmailEntity::dispatch($invitation->fresh(), $invitation->company, $template, $data)->delay(now()->addSeconds(2));
}
});
@@ -194,7 +192,7 @@ class EmailController extends BaseController
$data['template'] = $template;
- PurchaseOrderEmail::dispatch($entity_obj, $entity_obj->company, $data);
+ PurchaseOrderEmail::dispatch($entity_obj, $entity_obj->company, $data)->delay(now()->addSeconds(2));
return $this->itemResponse($entity_obj);
diff --git a/app/Http/Controllers/ImportController.php b/app/Http/Controllers/ImportController.php
index 25cc858e7500..41102869a90e 100644
--- a/app/Http/Controllers/ImportController.php
+++ b/app/Http/Controllers/ImportController.php
@@ -136,6 +136,8 @@ class ImportController extends Controller
}
$csv = Reader::createFromString($csvfile);
+ $csvdelimiter = self::detectDelimiter($csvfile);
+ $csv->setDelimiter($csvdelimiter);
$stmt = new Statement();
$data = iterator_to_array($stmt->process($csv));
@@ -156,4 +158,17 @@ class ImportController extends Controller
return $data;
}
+
+ public function detectDelimiter($csvfile)
+ {
+ $delimiters = array(',', '.', ';');
+ $bestDelimiter = false;
+ $count = 0;
+ foreach ($delimiters as $delimiter)
+ if (substr_count($csvfile, $delimiter) > $count) {
+ $count = substr_count($csvfile, $delimiter);
+ $bestDelimiter = $delimiter;
+ }
+ return $bestDelimiter;
+ }
}
diff --git a/app/Http/Controllers/OpenAPI/VendorSchema.php b/app/Http/Controllers/OpenAPI/VendorSchema.php
index 8cf71c4ca9ea..a50df21d6f07 100644
--- a/app/Http/Controllers/OpenAPI/VendorSchema.php
+++ b/app/Http/Controllers/OpenAPI/VendorSchema.php
@@ -26,7 +26,7 @@
* @OA\Property(property="city", type="string", example="", description="________"),
* @OA\Property(property="state", type="string", example="", description="________"),
* @OA\Property(property="postal_code", type="string", example="", description="________"),
- * @OA\Property(property="work_phone", type="string", example="555-3434-3434", description="The client phone number"),
+ * @OA\Property(property="phone", type="string", example="555-3434-3434", description="The client phone number"),
* @OA\Property(property="country_id", type="string", example="", description="________"),
* @OA\Property(property="currency_id", type="string", example="4", description="________"),
* @OA\Property(property="custom_value1", type="string", example="", description="________"),
diff --git a/app/Http/Requests/BankIntegration/StoreBankIntegrationRequest.php b/app/Http/Requests/BankIntegration/StoreBankIntegrationRequest.php
index 933f5848624d..80b53208a712 100644
--- a/app/Http/Requests/BankIntegration/StoreBankIntegrationRequest.php
+++ b/app/Http/Requests/BankIntegration/StoreBankIntegrationRequest.php
@@ -44,7 +44,7 @@ class StoreBankIntegrationRequest extends Request
{
$input = $this->all();
- if(!array_key_exists('provider_name', $input) || strlen($input['provider_name']) == 0 && array_key_exists('bank_account_name', $input))
+ if((!array_key_exists('provider_name', $input) || strlen($input['provider_name']) == 0) && array_key_exists('bank_account_name', $input))
$input['provider_name'] = $input['bank_account_name'];
$this->replace($input);
diff --git a/app/Http/Requests/BankTransaction/StoreBankTransactionRequest.php b/app/Http/Requests/BankTransaction/StoreBankTransactionRequest.php
index 529eaa79a61a..c2e6fe68bde9 100644
--- a/app/Http/Requests/BankTransaction/StoreBankTransactionRequest.php
+++ b/app/Http/Requests/BankTransaction/StoreBankTransactionRequest.php
@@ -34,8 +34,7 @@ class StoreBankTransactionRequest extends Request
$rules = [];
- if(isset($this->bank_integration_id))
- $rules['bank_integration_id'] = 'bail|required|exists:bank_integrations,id,company_id,'.auth()->user()->company()->id.',is_deleted,0';
+ $rules['bank_integration_id'] = 'bail|required|exists:bank_integrations,id,company_id,'.auth()->user()->company()->id.',is_deleted,0';
return $rules;
}
@@ -44,7 +43,9 @@ class StoreBankTransactionRequest extends Request
{
$input = $this->all();
- if(array_key_exists('bank_integration_id', $input) && strlen($input['bank_integration_id']) > 1 && !is_numeric($input['bank_integration_id']))
+ if(array_key_exists('bank_integration_id', $input) && $input['bank_integration_id'] == "")
+ unset($input['bank_integration_id']);
+ elseif(array_key_exists('bank_integration_id', $input) && strlen($input['bank_integration_id']) > 1 && !is_numeric($input['bank_integration_id']))
$input['bank_integration_id'] = $this->decodePrimaryKey($input['bank_integration_id']);
$this->replace($input);
diff --git a/app/Http/Requests/BankTransaction/UpdateBankTransactionRequest.php b/app/Http/Requests/BankTransaction/UpdateBankTransactionRequest.php
index 4f251c916766..54f789714316 100644
--- a/app/Http/Requests/BankTransaction/UpdateBankTransactionRequest.php
+++ b/app/Http/Requests/BankTransaction/UpdateBankTransactionRequest.php
@@ -45,8 +45,7 @@ class UpdateBankTransactionRequest extends Request
if(isset($this->expense_id))
$rules['expense_id'] = 'bail|required|exists:expenses,id,company_id,'.auth()->user()->company()->id.',is_deleted,0';
- if(isset($this->bank_integration_id))
- $rules['bank_integration_id'] = 'bail|required|exists:bank_integrations,id,company_id,'.auth()->user()->company()->id.',is_deleted,0';
+ $rules['bank_integration_id'] = 'bail|required|exists:bank_integrations,id,company_id,'.auth()->user()->company()->id.',is_deleted,0';
return $rules;
@@ -69,7 +68,9 @@ class UpdateBankTransactionRequest extends Request
if(array_key_exists('ninja_category_id', $input) && strlen($input['ninja_category_id']) > 1)
$input['ninja_category_id'] = $this->decodePrimaryKey($input['ninja_category_id']);
- if(array_key_exists('bank_integration_id', $input) && strlen($input['bank_integration_id']) > 1)
+ if(array_key_exists('bank_integration_id', $input) && $input['bank_integration_id'] == "")
+ unset($input['bank_integration_id']);
+ elseif(array_key_exists('bank_integration_id', $input) && strlen($input['bank_integration_id']) > 1)
$input['bank_integration_id'] = $this->decodePrimaryKey($input['bank_integration_id']);
$this->replace($input);
diff --git a/app/Http/Requests/Expense/StoreExpenseRequest.php b/app/Http/Requests/Expense/StoreExpenseRequest.php
index 0c964fef9016..a36369f01e90 100644
--- a/app/Http/Requests/Expense/StoreExpenseRequest.php
+++ b/app/Http/Requests/Expense/StoreExpenseRequest.php
@@ -45,6 +45,8 @@ class StoreExpenseRequest extends Request
$rules['client_id'] = 'bail|sometimes|exists:clients,id,company_id,'.auth()->user()->company()->id;
}
+ $rules['category_id'] = 'bail|nullable|sometimes|exists:expense_categories,id,company_id,'.auth()->user()->company()->id.',is_deleted,0';
+
return $this->globalRules($rules);
}
@@ -54,10 +56,6 @@ class StoreExpenseRequest extends Request
$input = $this->decodePrimaryKeys($input);
- if (array_key_exists('category_id', $input) && is_string($input['category_id'])) {
- $input['category_id'] = $this->decodePrimaryKey($input['category_id']);
- }
-
if (! array_key_exists('currency_id', $input) || strlen($input['currency_id']) == 0) {
$input['currency_id'] = (string) auth()->user()->company()->settings->currency_id;
}
@@ -66,7 +64,6 @@ class StoreExpenseRequest extends Request
$input['color'] = '';
}
-
/* Ensure the project is related */
if (array_key_exists('project_id', $input) && isset($input['project_id'])) {
$project = Project::withTrashed()->where('id', $input['project_id'])->company()->first();
diff --git a/app/Http/Requests/Expense/UpdateExpenseRequest.php b/app/Http/Requests/Expense/UpdateExpenseRequest.php
index 26b144731048..348cad69ddba 100644
--- a/app/Http/Requests/Expense/UpdateExpenseRequest.php
+++ b/app/Http/Requests/Expense/UpdateExpenseRequest.php
@@ -41,6 +41,8 @@ class UpdateExpenseRequest extends Request
$rules['number'] = Rule::unique('expenses')->where('company_id', auth()->user()->company()->id)->ignore($this->expense->id);
}
+ $rules['category_id'] = 'bail|sometimes|nullable|exists:expense_categories,id,company_id,'.auth()->user()->company()->id.',is_deleted,0';
+
return $this->globalRules($rules);
}
@@ -50,10 +52,6 @@ class UpdateExpenseRequest extends Request
$input = $this->decodePrimaryKeys($input);
- if (array_key_exists('category_id', $input) && is_string($input['category_id'])) {
- $input['category_id'] = $this->decodePrimaryKey($input['category_id']);
- }
-
if (array_key_exists('documents', $input)) {
unset($input['documents']);
}
diff --git a/app/Http/ValidationRules/Company/ValidCompanyQuantity.php b/app/Http/ValidationRules/Company/ValidCompanyQuantity.php
index a90e861c9ae2..fa04edd4a721 100644
--- a/app/Http/ValidationRules/Company/ValidCompanyQuantity.php
+++ b/app/Http/ValidationRules/Company/ValidCompanyQuantity.php
@@ -39,6 +39,6 @@ class ValidCompanyQuantity implements Rule
*/
public function message()
{
- return ctrans('texts.company_limit_reached');
+ return ctrans('texts.company_limit_reached', ['limit' => Ninja::isSelfHost() ? 10 : auth()->user()->company()->account->hosted_company_count]);
}
}
diff --git a/app/Import/Transformer/Csv/ClientTransformer.php b/app/Import/Transformer/Csv/ClientTransformer.php
index a2c4721bb8eb..543ad1cd205a 100644
--- a/app/Import/Transformer/Csv/ClientTransformer.php
+++ b/app/Import/Transformer/Csv/ClientTransformer.php
@@ -38,7 +38,7 @@ class ClientTransformer extends BaseTransformer
return [
'company_id' => $this->company->id,
'name' => $this->getString($data, 'client.name'),
- 'work_phone' => $this->getString($data, 'client.phone'),
+ 'phone' => $this->getString($data, 'client.phone'),
'address1' => $this->getString($data, 'client.address1'),
'address2' => $this->getString($data, 'client.address2'),
'postal_code' => $this->getString($data, 'client.postal_code'),
diff --git a/app/Import/Transformer/Wave/ClientTransformer.php b/app/Import/Transformer/Wave/ClientTransformer.php
index c5681e411152..844560f48679 100644
--- a/app/Import/Transformer/Wave/ClientTransformer.php
+++ b/app/Import/Transformer/Wave/ClientTransformer.php
@@ -42,7 +42,7 @@ class ClientTransformer extends BaseTransformer
'company_id' => $this->company->id,
'name' => $this->getString($data, 'customer_name'),
'number' => $this->getValueOrNull($data, 'account_number'),
- 'work_phone' => $this->getString($data, 'phone'),
+ 'phone' => $this->getString($data, 'phone'),
'website' => $this->getString($data, 'website'),
'country_id' => ! empty($data['country']) ? $this->getCountryId($data['country']) : null,
'state' => $this->getString($data, 'province/state'),
diff --git a/app/Import/Transformers/ClientTransformer.php b/app/Import/Transformers/ClientTransformer.php
index 1e7ed43ae226..a77af36b5693 100644
--- a/app/Import/Transformers/ClientTransformer.php
+++ b/app/Import/Transformers/ClientTransformer.php
@@ -35,7 +35,7 @@ class ClientTransformer extends BaseTransformer
return [
'company_id' => $this->maps['company']->id,
'name' => $this->getString($data, 'client.name'),
- 'work_phone' => $this->getString($data, 'client.phone'),
+ 'phone' => $this->getString($data, 'client.phone'),
'address1' => $this->getString($data, 'client.address1'),
'address2' => $this->getString($data, 'client.address2'),
'city' => $this->getString($data, 'client.city'),
diff --git a/app/Import/Transformers/Csv/ClientTransformer.php b/app/Import/Transformers/Csv/ClientTransformer.php
index 55d0baa8a1fa..44f826e1bbb5 100644
--- a/app/Import/Transformers/Csv/ClientTransformer.php
+++ b/app/Import/Transformers/Csv/ClientTransformer.php
@@ -37,7 +37,7 @@ class ClientTransformer extends BaseTransformer
return [
'company_id' => $this->maps['company']->id,
'name' => $this->getString($data, 'client.name'),
- 'work_phone' => $this->getString($data, 'client.phone'),
+ 'phone' => $this->getString($data, 'client.phone'),
'address1' => $this->getString($data, 'client.address1'),
'address2' => $this->getString($data, 'client.address2'),
'postal_code' => $this->getString($data, 'client.postal_code'),
diff --git a/app/Import/Transformers/Freshbooks/ClientTransformer.php b/app/Import/Transformers/Freshbooks/ClientTransformer.php
index bfa8743ed62d..5b82f400c223 100644
--- a/app/Import/Transformers/Freshbooks/ClientTransformer.php
+++ b/app/Import/Transformers/Freshbooks/ClientTransformer.php
@@ -34,7 +34,7 @@ class ClientTransformer extends BaseTransformer
return [
'company_id' => $this->maps['company']->id,
'name' => $this->getString($data, 'Organization'),
- 'work_phone' => $this->getString($data, 'Phone'),
+ 'phone' => $this->getString($data, 'Phone'),
'address1' => $this->getString($data, 'Street'),
'city' => $this->getString($data, 'City'),
'state' => $this->getString($data, 'Province/State'),
diff --git a/app/Import/Transformers/Invoicely/ClientTransformer.php b/app/Import/Transformers/Invoicely/ClientTransformer.php
index ddf3645b3610..5e2d58ae4a09 100644
--- a/app/Import/Transformers/Invoicely/ClientTransformer.php
+++ b/app/Import/Transformers/Invoicely/ClientTransformer.php
@@ -34,7 +34,7 @@ class ClientTransformer extends BaseTransformer
return [
'company_id' => $this->maps['company']->id,
'name' => $this->getString($data, 'Client Name'),
- 'work_phone' => $this->getString($data, 'Phone'),
+ 'phone' => $this->getString($data, 'Phone'),
'country_id' => isset($data['Country']) ? $this->getCountryIdBy2($data['Country']) : null,
'credit_balance' => 0,
'settings' => new \stdClass,
diff --git a/app/Import/Transformers/Waveaccounting/ClientTransformer.php b/app/Import/Transformers/Waveaccounting/ClientTransformer.php
index a19616f968f1..f9b95a42e487 100644
--- a/app/Import/Transformers/Waveaccounting/ClientTransformer.php
+++ b/app/Import/Transformers/Waveaccounting/ClientTransformer.php
@@ -42,7 +42,7 @@ class ClientTransformer extends BaseTransformer
'company_id' => $this->maps['company']->id,
'name' => $this->getString($data, 'customer_name'),
'number' => $this->getString($data, 'account_number'),
- 'work_phone' => $this->getString($data, 'phone'),
+ 'phone' => $this->getString($data, 'phone'),
'website' => $this->getString($data, 'website'),
'country_id' => ! empty($data['country']) ? $this->getCountryId($data['country']) : null,
'state' => $this->getString($data, 'province/state'),
diff --git a/app/Import/Transformers/Zoho/ClientTransformer.php b/app/Import/Transformers/Zoho/ClientTransformer.php
index e8e618d189be..6895fabdaeb2 100644
--- a/app/Import/Transformers/Zoho/ClientTransformer.php
+++ b/app/Import/Transformers/Zoho/ClientTransformer.php
@@ -41,7 +41,7 @@ class ClientTransformer extends BaseTransformer
return [
'company_id' => $this->maps['company']->id,
'name' => $this->getString($data, 'Company Name'),
- 'work_phone' => $this->getString($data, 'Phone'),
+ 'phone' => $this->getString($data, 'Phone'),
'private_notes' => $this->getString($data, 'Notes'),
'website' => $this->getString($data, 'Website'),
'id_number' => $this->getString($data, 'Customer ID'),
diff --git a/app/Jobs/Bank/MatchBankTransactions.php b/app/Jobs/Bank/MatchBankTransactions.php
index 9f5260e204ab..0532d51e8b58 100644
--- a/app/Jobs/Bank/MatchBankTransactions.php
+++ b/app/Jobs/Bank/MatchBankTransactions.php
@@ -266,7 +266,7 @@ class MatchBankTransactions implements ShouldQueue
/* Create Payment */
$payment = PaymentFactory::create($this->invoice->company_id, $this->invoice->user_id);
- $payment->amount = $amount;
+ $payment->amount = $this->bt->amount;
$payment->applied = $this->applied_amount;
$payment->status_id = Payment::STATUS_COMPLETED;
$payment->client_id = $this->invoice->client_id;
@@ -315,7 +315,7 @@ class MatchBankTransactions implements ShouldQueue
$this->invoice
->client
->service()
- ->updateBalanceAndPaidToDate($amount*-1, $amount)
+ ->updateBalanceAndPaidToDate($this->applied_amount*-1, $amount)
->save();
$this->invoice = $this->invoice
diff --git a/app/Mail/Engine/CreditEmailEngine.php b/app/Mail/Engine/CreditEmailEngine.php
index 12a12e600d88..25ac405d38ea 100644
--- a/app/Mail/Engine/CreditEmailEngine.php
+++ b/app/Mail/Engine/CreditEmailEngine.php
@@ -11,6 +11,7 @@
namespace App\Mail\Engine;
+use App\Jobs\Entity\CreateRawPdf;
use App\Models\Account;
use App\Utils\HtmlEngine;
use App\Utils\Ninja;
@@ -117,11 +118,17 @@ class CreditEmailEngine extends BaseEmailEngine
->setTextBody($text_body);
if ($this->client->getSetting('pdf_email_attachment') !== false && $this->credit->company->account->hasFeature(Account::FEATURE_PDF_ATTACHMENT)) {
- if (Ninja::isHosted()) {
- $this->setAttachments([$this->credit->pdf_file_path($this->invitation, 'url', true)]);
- } else {
- $this->setAttachments([$this->credit->pdf_file_path($this->invitation)]);
- }
+ // if (Ninja::isHosted()) {
+ // $this->setAttachments([$this->credit->pdf_file_path($this->invitation, 'url', true)]);
+ // } else {
+ // $this->setAttachments([$this->credit->pdf_file_path($this->invitation)]);
+ // }
+
+ $pdf = ((new CreateRawPdf($this->invitation, $this->invitation->company->db))->handle());
+
+ $this->setAttachments([['file' => base64_encode($pdf), 'name' => $this->credit->numberFormatter().'.pdf']]);
+
+
}
//attach third party documents
@@ -129,11 +136,11 @@ class CreditEmailEngine extends BaseEmailEngine
// Storage::url
foreach ($this->credit->documents as $document) {
- $this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => null]]);
+ $this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, 'file' => base64_encode($document->getFile())]]);
}
foreach ($this->credit->company->documents as $document) {
- $this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => null]]);
+ $this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, 'file' => base64_encode($document->getFile())]]);
}
}
diff --git a/app/Mail/Engine/InvoiceEmailEngine.php b/app/Mail/Engine/InvoiceEmailEngine.php
index 000d2f72748f..69810ba626ca 100644
--- a/app/Mail/Engine/InvoiceEmailEngine.php
+++ b/app/Mail/Engine/InvoiceEmailEngine.php
@@ -13,6 +13,7 @@ namespace App\Mail\Engine;
use App\DataMapper\EmailTemplateDefaults;
use App\Jobs\Entity\CreateEntityPdf;
+use App\Jobs\Entity\CreateRawPdf;
use App\Models\Account;
use App\Models\Expense;
use App\Models\Task;
@@ -126,11 +127,15 @@ class InvoiceEmailEngine extends BaseEmailEngine
->setTextBody($text_body);
if ($this->client->getSetting('pdf_email_attachment') !== false && $this->invoice->company->account->hasFeature(Account::FEATURE_PDF_ATTACHMENT)) {
- if (Ninja::isHosted()) {
- $this->setAttachments([$this->invoice->pdf_file_path($this->invitation, 'url', true)]);
- } else {
- $this->setAttachments([$this->invoice->pdf_file_path($this->invitation)]);
- }
+ // if (Ninja::isHosted()) {
+ // $this->setAttachments([$this->invoice->pdf_file_path($this->invitation, 'url', true)]);
+ // } else {
+ // $this->setAttachments([$this->invoice->pdf_file_path($this->invitation)]);
+ // }
+ // $file = (new CreateRawPdf($invitation, $invitation->company->db))->handle();
+ $pdf = ((new CreateRawPdf($this->invitation, $this->invitation->company->db))->handle());
+
+ $this->setAttachments([['file' => base64_encode($pdf), 'name' => $this->invoice->numberFormatter().'.pdf']]);
}
//attach third party documents
@@ -138,11 +143,11 @@ class InvoiceEmailEngine extends BaseEmailEngine
// Storage::url
foreach ($this->invoice->documents as $document) {
- $this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL]]);
+ $this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, ]]);
}
foreach ($this->invoice->company->documents as $document) {
- $this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL]]);
+ $this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, ]]);
}
$line_items = $this->invoice->line_items;
@@ -160,7 +165,7 @@ class InvoiceEmailEngine extends BaseEmailEngine
->cursor()
->each(function ($expense) {
foreach ($expense->documents as $document) {
- $this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL]]);
+ $this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, ]]);
}
});
}
@@ -176,7 +181,7 @@ class InvoiceEmailEngine extends BaseEmailEngine
->cursor()
->each(function ($task) {
foreach ($task->documents as $document) {
- $this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL]]);
+ $this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, ]]);
}
});
}
diff --git a/app/Mail/Engine/PaymentEmailEngine.php b/app/Mail/Engine/PaymentEmailEngine.php
index bf15b7aa2ca4..e9ad8767d284 100644
--- a/app/Mail/Engine/PaymentEmailEngine.php
+++ b/app/Mail/Engine/PaymentEmailEngine.php
@@ -12,6 +12,7 @@
namespace App\Mail\Engine;
use App\DataMapper\EmailTemplateDefaults;
+use App\Jobs\Entity\CreateRawPdf;
use App\Models\Account;
use App\Utils\Helpers;
use App\Utils\Ninja;
@@ -89,11 +90,15 @@ class PaymentEmailEngine extends BaseEmailEngine
if ($this->client->getSetting('pdf_email_attachment') !== false && $this->company->account->hasFeature(Account::FEATURE_PDF_ATTACHMENT)) {
$this->payment->invoices->each(function ($invoice) {
- if (Ninja::isHosted()) {
- $this->setAttachments([$invoice->pdf_file_path($invoice->invitations->first(), 'url', true)]);
- } else {
- $this->setAttachments([$invoice->pdf_file_path($invoice->invitations->first())]);
- }
+ // if (Ninja::isHosted()) {
+ // $this->setAttachments([$invoice->pdf_file_path($invoice->invitations->first(), 'url', true)]);
+ // } else {
+ // $this->setAttachments([$invoice->pdf_file_path($invoice->invitations->first())]);
+ // }
+ $pdf = ((new CreateRawPdf($invoice->invitations->first(), $invoice->company->db))->handle());
+
+ $this->setAttachments([['file' => base64_encode($pdf), 'name' => $invoice->numberFormatter().'.pdf']]);
+
});
}
diff --git a/app/Mail/Engine/PurchaseOrderEmailEngine.php b/app/Mail/Engine/PurchaseOrderEmailEngine.php
index fa6477c38c34..f11e046b68e2 100644
--- a/app/Mail/Engine/PurchaseOrderEmailEngine.php
+++ b/app/Mail/Engine/PurchaseOrderEmailEngine.php
@@ -13,6 +13,7 @@ namespace App\Mail\Engine;
use App\DataMapper\EmailTemplateDefaults;
use App\Jobs\Entity\CreateEntityPdf;
+use App\Jobs\Vendor\CreatePurchaseOrderPdf;
use App\Models\Account;
use App\Models\Expense;
use App\Models\PurchaseOrder;
@@ -125,11 +126,16 @@ class PurchaseOrderEmailEngine extends BaseEmailEngine
->setTextBody($text_body);
if ($this->vendor->getSetting('pdf_email_attachment') !== false && $this->purchase_order->company->account->hasFeature(Account::FEATURE_PDF_ATTACHMENT)) {
- if (Ninja::isHosted()) {
- $this->setAttachments([$this->purchase_order->pdf_file_path($this->invitation, 'url', true)]);
- } else {
- $this->setAttachments([$this->purchase_order->pdf_file_path($this->invitation)]);
- }
+ // if (Ninja::isHosted()) {
+ // $this->setAttachments([$this->purchase_order->pdf_file_path($this->invitation, 'url', true)]);
+ // } else {
+ // $this->setAttachments([$this->purchase_order->pdf_file_path($this->invitation)]);
+ // }
+
+ $pdf = (new CreatePurchaseOrderPdf($this->invitation))->rawPdf();
+
+ $this->setAttachments([['file' => base64_encode($pdf), 'name' => $this->purchase_order->numberFormatter().'.pdf']]);
+
}
//attach third party documents
@@ -138,10 +144,12 @@ class PurchaseOrderEmailEngine extends BaseEmailEngine
// Storage::url
foreach ($this->purchase_order->documents as $document) {
$this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => null]]);
+ // $this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, 'file' => base64_encode($document->getFile())]]);
}
foreach ($this->purchase_order->company->documents as $document) {
$this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => null]]);
+ // $this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, 'file' => base64_encode($document->getFile())]]);
}
}
diff --git a/app/Mail/Engine/QuoteEmailEngine.php b/app/Mail/Engine/QuoteEmailEngine.php
index 8b692c2f3e5d..63271c0600ba 100644
--- a/app/Mail/Engine/QuoteEmailEngine.php
+++ b/app/Mail/Engine/QuoteEmailEngine.php
@@ -11,6 +11,7 @@
namespace App\Mail\Engine;
+use App\Jobs\Entity\CreateRawPdf;
use App\Models\Account;
use App\Utils\HtmlEngine;
use App\Utils\Ninja;
@@ -116,11 +117,15 @@ class QuoteEmailEngine extends BaseEmailEngine
->setTextBody($text_body);
if ($this->client->getSetting('pdf_email_attachment') !== false && $this->quote->company->account->hasFeature(Account::FEATURE_PDF_ATTACHMENT)) {
- if (Ninja::isHosted()) {
- $this->setAttachments([$this->quote->pdf_file_path($this->invitation, 'url', true)]);
- } else {
- $this->setAttachments([$this->quote->pdf_file_path($this->invitation)]);
- }
+ // if (Ninja::isHosted()) {
+ // $this->setAttachments([$this->quote->pdf_file_path($this->invitation, 'url', true)]);
+ // } else {
+ // $this->setAttachments([$this->quote->pdf_file_path($this->invitation)]);
+ // }
+
+ $pdf = ((new CreateRawPdf($this->invitation, $this->invitation->company->db))->handle());
+
+ $this->setAttachments([['file' => base64_encode($pdf), 'name' => $this->quote->numberFormatter().'.pdf']]);
}
//attach third party documents
@@ -128,11 +133,11 @@ class QuoteEmailEngine extends BaseEmailEngine
// Storage::url
foreach ($this->quote->documents as $document) {
- $this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => null]]);
+ $this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, ]]);
}
foreach ($this->quote->company->documents as $document) {
- $this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => null]]);
+ $this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, ]]);
}
}
diff --git a/app/Mail/TemplateEmail.php b/app/Mail/TemplateEmail.php
index cbf07442c075..b5b443657f78 100644
--- a/app/Mail/TemplateEmail.php
+++ b/app/Mail/TemplateEmail.php
@@ -120,45 +120,53 @@ class TemplateEmail extends Mailable
/*In the hosted platform we need to slow things down a little for Storage to catch up.*/
- if(Ninja::isHosted() && $this->invitation){
+ // if(Ninja::isHosted() && $this->invitation){
- $path = false;
+ // $path = false;
- if($this->invitation->invoice)
- $path = $this->client->invoice_filepath($this->invitation).$this->invitation->invoice->numberFormatter().'.pdf';
- elseif($this->invitation->quote)
- $path = $this->client->quote_filepath($this->invitation).$this->invitation->quote->numberFormatter().'.pdf';
- elseif($this->invitation->credit)
- $path = $this->client->credit_filepath($this->invitation).$this->invitation->credit->numberFormatter().'.pdf';
+ // if($this->invitation->invoice)
+ // $path = $this->client->invoice_filepath($this->invitation).$this->invitation->invoice->numberFormatter().'.pdf';
+ // elseif($this->invitation->quote)
+ // $path = $this->client->quote_filepath($this->invitation).$this->invitation->quote->numberFormatter().'.pdf';
+ // elseif($this->invitation->credit)
+ // $path = $this->client->credit_filepath($this->invitation).$this->invitation->credit->numberFormatter().'.pdf';
- sleep(1);
+ // sleep(1);
- if($path && !Storage::disk(config('filesystems.default'))->exists($path)){
+ // if($path && !Storage::disk(config('filesystems.default'))->exists($path)){
- sleep(2);
+ // sleep(2);
- if(!Storage::disk(config('filesystems.default'))->exists($path)) {
- (new CreateEntityPdf($this->invitation))->handle();
- sleep(2);
- }
+ // if(!Storage::disk(config('filesystems.default'))->exists($path)) {
+ // (new CreateEntityPdf($this->invitation))->handle();
+ // sleep(2);
+ // }
- }
+ // }
+
+ // }
+
+ // $file = (new CreateRawPdf($invitation, $invitation->company->db))->handle();
- }
//22-10-2022 - Performance - To improve the performance/reliability of sending emails, attaching as Data is much better, stubs in place
foreach ($this->build_email->getAttachments() as $file) {
- if (is_string($file)) {
- // nlog($file);
- // $file_data = file_get_contents($file);
- // $this->attachData($file_data, basename($file));
- $this->attach($file);
- } elseif (is_array($file)) {
- // nlog($file['path']);
- // $file_data = file_get_contents($file['path']);
- // $this->attachData($file_data, $file['name']);
+ // if (is_string($file)) {
+ // // nlog($file);
+ // // $file_data = file_get_contents($file);
+ // // $this->attachData($file_data, basename($file));
+ // $this->attach($file);
+ // } elseif (is_array($file)) {
+ // // nlog($file['path']);
+ // // $file_data = file_get_contents($file['path']);
+ // // $this->attachData($file_data, $file['name']);
+ // $this->attach($file['path'], ['as' => $file['name'], 'mime' => null]);
+ // }
+ if(array_key_exists('file', $file))
+ $this->attachData(base64_decode($file['file']), $file['name']);
+ else
$this->attach($file['path'], ['as' => $file['name'], 'mime' => null]);
- }
+
}
if ($this->invitation && $this->invitation->invoice && $settings->ubl_email_attachment && $this->company->account->hasFeature(Account::FEATURE_PDF_ATTACHMENT)) {
diff --git a/app/Mail/VendorTemplateEmail.php b/app/Mail/VendorTemplateEmail.php
index 670a59e93676..ccf9ef06955e 100644
--- a/app/Mail/VendorTemplateEmail.php
+++ b/app/Mail/VendorTemplateEmail.php
@@ -110,40 +110,39 @@ class VendorTemplateEmail extends Mailable
'whitelabel' => $this->vendor->user->account->isPaid() ? true : false,
'logo' => $this->company->present()->logo($settings),
]);
- //->withSymfonyMessage(function ($message) {
- // $message->getHeaders()->addTextHeader('Tag', $this->company->company_key);
- // $message->invitation = $this->invitation;
- //});
- // ->tag($this->company->company_key);
- if(Ninja::isHosted() && $this->invitation){
- $path = false;
+ // if(Ninja::isHosted() && $this->invitation){
- if($this->invitation->purchase_order)
- $path = $this->vendor->purchase_order_filepath($this->invitation).$this->invitation->purchase_order->numberFormatter().'.pdf';
+ // $path = false;
- sleep(1);
+ // if($this->invitation->purchase_order)
+ // $path = $this->vendor->purchase_order_filepath($this->invitation).$this->invitation->purchase_order->numberFormatter().'.pdf';
- if($path && !Storage::disk(config('filesystems.default'))->exists($path)){
+ // sleep(1);
- sleep(2);
+ // if($path && !Storage::disk(config('filesystems.default'))->exists($path)){
- if(!Storage::disk(config('filesystems.default'))->exists($path)) {
- (new CreatePurchaseOrderPdf($this->invitation))->handle();
- sleep(2);
- }
+ // sleep(2);
- }
+ // if(!Storage::disk(config('filesystems.default'))->exists($path)) {
+ // (new CreatePurchaseOrderPdf($this->invitation))->handle();
+ // sleep(2);
+ // }
- }
+ // }
+
+ // }
foreach ($this->build_email->getAttachments() as $file) {
- if (is_string($file)) {
- $this->attach($file);
- } elseif (is_array($file)) {
- $this->attach($file['path'], ['as' => $file['name'], 'mime' => null]);
- }
+ // if (is_string($file)) {
+ // $this->attach($file);
+ // } elseif (is_array($file)) {
+ // $this->attach($file['path'], ['as' => $file['name'], 'mime' => null]);
+ // }
+
+ $this->attachData(base64_decode($file['file']), $file['name']);
+
}
return $this;
diff --git a/app/Models/Presenters/CompanyPresenter.php b/app/Models/Presenters/CompanyPresenter.php
index 57408a788590..9d44bee8c60d 100644
--- a/app/Models/Presenters/CompanyPresenter.php
+++ b/app/Models/Presenters/CompanyPresenter.php
@@ -119,7 +119,7 @@ class CompanyPresenter extends EntityPresenter
$str .= e($country->name).'
';
}
if ($settings->phone) {
- $str .= ctrans('texts.work_phone').': '.e($settings->phone).'
';
+ $str .= ctrans('texts.phone').': '.e($settings->phone).'
';
}
if ($settings->email) {
$str .= ctrans('texts.work_email').': '.e($settings->email).'
';
diff --git a/app/PaymentDrivers/CheckoutCom/CreditCard.php b/app/PaymentDrivers/CheckoutCom/CreditCard.php
index 27e6c4d67243..1ada04574b5e 100644
--- a/app/PaymentDrivers/CheckoutCom/CreditCard.php
+++ b/app/PaymentDrivers/CheckoutCom/CreditCard.php
@@ -94,8 +94,6 @@ class CreditCard implements MethodInterface
$customerRequest = $this->checkout->getCustomer();
- nlog($customerRequest);
-
$request = $this->bootRequest($gateway_response->token);
$request->capture = false;
$request->reference = '$1 payment for authorization.';
diff --git a/app/PaymentDrivers/CheckoutComPaymentDriver.php b/app/PaymentDrivers/CheckoutComPaymentDriver.php
index daa9aa7fcd68..c59534a05788 100644
--- a/app/PaymentDrivers/CheckoutComPaymentDriver.php
+++ b/app/PaymentDrivers/CheckoutComPaymentDriver.php
@@ -34,6 +34,7 @@ use Checkout\CheckoutArgumentException;
use Checkout\CheckoutAuthorizationException;
use Checkout\CheckoutDefaultSdk;
use Checkout\CheckoutFourSdk;
+use Checkout\Common\Phone;
use Checkout\Customers\CustomerRequest;
use Checkout\Customers\Four\CustomerRequest as FourCustomerRequest;
use Checkout\Environment;
@@ -300,9 +301,12 @@ class CheckoutComPaymentDriver extends BaseDriver
$request = new CustomerRequest();
}
- $request->email = $this->client->present()->email();
- $request->name = $this->client->present()->name();
- $request->phone = $this->client->present()->phone();
+ $phone = new Phone();
+ $phone->number = $this->client->present()->phone();
+
+ $request->email = $this->client->present()->email();
+ $request->name = $this->client->present()->name();
+ $request->phone = $phone;
try {
$response = $this->gateway->getCustomersClient()->create($request);
diff --git a/app/PaymentDrivers/Stripe/ACH.php b/app/PaymentDrivers/Stripe/ACH.php
index cc25056ca673..8e8a8f70ebf4 100644
--- a/app/PaymentDrivers/Stripe/ACH.php
+++ b/app/PaymentDrivers/Stripe/ACH.php
@@ -36,6 +36,7 @@ use Stripe\Exception\CardException;
use Stripe\Exception\InvalidRequestException;
use Stripe\Exception\RateLimitException;
use Stripe\PaymentIntent;
+use App\Utils\Number;
class ACH
{
@@ -172,9 +173,9 @@ class ACH
->first();
if ($invoice) {
- $description = "Invoice {$invoice->number} for {$amount} for client {$this->stripe->client->present()->name()}";
+ $description = ctrans('texts.stripe_paymenttext', ['invoicenumber' => $invoice->number, 'amount' => Number::formatMoney($amount, $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
} else {
- $description = "Payment with no invoice for amount {$amount} for client {$this->stripe->client->present()->name()}";
+ $description = ctrans('text.stripe_paymenttext_without_invoice', ['amount' => Number::formatMoney($amount, $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
}
@@ -210,9 +211,9 @@ class ACH
->first();
if ($invoice) {
- $description = "Invoice {$invoice->number} for {$amount} for client {$this->stripe->client->present()->name()}";
+ $description = ctrans('texts.stripe_paymenttext', ['invoicenumber' => $invoice->number, 'amount' => Number::formatMoney($amount, $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
} else {
- $description = "Payment with no invoice for amount {$amount} for client {$this->stripe->client->present()->name()}";
+ $description = ctrans('text.stripe_paymenttext_without_invoice', ['amount' => Number::formatMoney($amount, $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
}
if (substr($cgt->token, 0, 2) === 'pm') {
@@ -454,9 +455,9 @@ class ACH
->first();
if ($invoice) {
- $description = "Invoice {$invoice->number} for {$amount} for client {$this->stripe->client->present()->name()}";
+ $description = ctrans('texts.stripe_paymenttext', ['invoicenumber' => $invoice->number, 'amount' => Number::formatMoney($amount, $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
} else {
- $description = "Payment with no invoice for amount {$amount} for client {$this->stripe->client->present()->name()}";
+ $description = ctrans('text.stripe_paymenttext_without_invoice', ['amount' => Number::formatMoney($amount, $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
}
if (substr($source->token, 0, 2) === 'pm') {
diff --git a/app/PaymentDrivers/Stripe/Charge.php b/app/PaymentDrivers/Stripe/Charge.php
index 7dbd60c07f57..dabef4a6fbf6 100644
--- a/app/PaymentDrivers/Stripe/Charge.php
+++ b/app/PaymentDrivers/Stripe/Charge.php
@@ -32,6 +32,7 @@ use Stripe\Exception\CardException;
use Stripe\Exception\InvalidRequestException;
use Stripe\Exception\RateLimitException;
use Stripe\StripeClient;
+use App\Utils\Number;
class Charge
{
@@ -62,9 +63,9 @@ class Charge
$invoice = Invoice::whereIn('id', $this->transformKeys(array_column($payment_hash->invoices(), 'invoice_id')))->withTrashed()->first();
if ($invoice) {
- $description = "Invoice {$invoice->number} for {$amount} for client {$this->stripe->client->present()->name()}";
+ $description = ctrans('texts.stripe_paymenttext', ['invoicenumber' => $invoice->number, 'amount' => Number::formatMoney($amount, $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
} else {
- $description = "Payment with no invoice for amount {$amount} for client {$this->stripe->client->present()->name()}";
+ $description = ctrans('text.stripe_paymenttext_without_invoice', ['amount' => Number::formatMoney($amount, $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
}
$this->stripe->init();
diff --git a/app/PaymentDrivers/Stripe/CreditCard.php b/app/PaymentDrivers/Stripe/CreditCard.php
index 838af9c2328c..64b9df528317 100644
--- a/app/PaymentDrivers/Stripe/CreditCard.php
+++ b/app/PaymentDrivers/Stripe/CreditCard.php
@@ -23,6 +23,7 @@ use App\PaymentDrivers\StripePaymentDriver;
use App\PaymentDrivers\Stripe\Jobs\UpdateCustomer;
use Stripe\PaymentIntent;
use Stripe\PaymentMethod;
+use App\Utils\Number;
class CreditCard
{
@@ -62,7 +63,7 @@ class CreditCard
// $description = $this->stripe->decodeUnicodeString(ctrans('texts.invoices') . ': ' . collect($data['invoices'])->pluck('invoice_number')) . " for client {$this->stripe->client->present()->name()}";
$invoice_numbers = collect($data['invoices'])->pluck('invoice_number')->implode(',');
- $description = "Invoices: {$invoice_numbers} for {$data['total']['amount_with_fee']} for client {$this->stripe->client->present()->name()}";
+ $description = ctrans('texts.stripe_paymenttext', ['invoicenumber' => $invoice_numbers, 'amount' => Number::formatMoney($data['total']['amount_with_fee'], $this->stripe->client), 'client' => $this->stripe->client->present()->name()]);
$payment_intent_data = [
'amount' => $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency()),
diff --git a/app/PaymentDrivers/Stripe/Jobs/PaymentIntentWebhook.php b/app/PaymentDrivers/Stripe/Jobs/PaymentIntentWebhook.php
index 1caf382e567f..d3a8ad40e7d6 100644
--- a/app/PaymentDrivers/Stripe/Jobs/PaymentIntentWebhook.php
+++ b/app/PaymentDrivers/Stripe/Jobs/PaymentIntentWebhook.php
@@ -66,11 +66,9 @@ class PaymentIntentWebhook implements ShouldQueue
{
$payment = Payment::query()
->where('company_id', $company->id)
- ->where(function ($query) use ($transaction) {
- $query->where('transaction_reference', $transaction['payment_intent'])
- ->orWhere('transaction_reference', $transaction['id']);
- })
+ ->where('transaction_reference', $transaction['payment_intent'])
->first();
+
}
else
{
diff --git a/app/Repositories/ClientRepository.php b/app/Repositories/ClientRepository.php
index 23c6ae8cee28..6114916e80ad 100644
--- a/app/Repositories/ClientRepository.php
+++ b/app/Repositories/ClientRepository.php
@@ -56,6 +56,8 @@ class ClientRepository extends BaseRepository
*/
public function save(array $data, Client $client) : ?Client
{
+ $contact_data = $data;
+ unset($data['contacts']);
/* When uploading documents, only the document array is sent, so we must return early*/
if (array_key_exists('documents', $data) && count($data['documents']) >= 1) {
@@ -67,7 +69,7 @@ class ClientRepository extends BaseRepository
$client->fill($data);
if (array_key_exists('settings', $data)) {
- $client->saveSettings($data['settings'], $client);
+ $client->settings = $client->saveSettings($data['settings'], $client);
}
if (! $client->country_id) {
@@ -75,19 +77,9 @@ class ClientRepository extends BaseRepository
$client->country_id = $company->settings->country_id;
}
- try{
- $client->save();
- }
- catch(\Exception $e) {
-
- nlog("client save failed");
- nlog($data);
-
- }
+ $client->save();
if (! isset($client->number) || empty($client->number) || strlen($client->number) == 0) {
- // $client->number = $this->getNextClientNumber($client);
- // $client->save();
$x = 1;
@@ -111,7 +103,7 @@ class ClientRepository extends BaseRepository
$data['name'] = $client->present()->name();
}
- $this->contact_repo->save($data, $client);
+ $this->contact_repo->save($contact_data, $client);
return $client;
}
diff --git a/app/Services/Invoice/HandleRestore.php b/app/Services/Invoice/HandleRestore.php
index 412013aceb4c..0d46f8717e40 100644
--- a/app/Services/Invoice/HandleRestore.php
+++ b/app/Services/Invoice/HandleRestore.php
@@ -44,11 +44,12 @@ class HandleRestore extends AbstractService
return $this->invoice;
}
- //determine whether we need to un-delete payments OR just modify the payment amount /applied balances.
-
+ //cannot restore an invoice with a deleted payment
foreach ($this->invoice->payments as $payment) {
- //restore the payment record
- $this->invoice->restore();
+
+ if(($this->invoice->paid_to_date == 0) && $payment->is_deleted)
+ return $this->invoice;
+
}
//adjust ledger balance
@@ -56,8 +57,7 @@ class HandleRestore extends AbstractService
$this->invoice->client
->service()
- ->updateBalance($this->invoice->balance)
- ->updatePaidToDate($this->invoice->paid_to_date)
+ ->updateBalanceAndPaidToDate($this->invoice->balance,$this->invoice->paid_to_date)
->save();
$this->windBackInvoiceNumber();
@@ -120,11 +120,11 @@ class HandleRestore extends AbstractService
if ($this->adjustment_amount == $this->total_payments) {
$this->invoice->payments()->update(['payments.deleted_at' => null, 'payments.is_deleted' => false]);
- } else {
+ }
//adjust payments down by the amount applied to the invoice payment.
- $this->invoice->payments->each(function ($payment) {
+ $this->invoice->payments->fresh()->each(function ($payment) {
$payment_adjustment = $payment->paymentables
->where('paymentable_type', '=', 'invoices')
->where('paymentable_id', $this->invoice->id)
@@ -141,8 +141,7 @@ class HandleRestore extends AbstractService
$payment->restore();
$payment->save();
});
- }
-
+
return $this;
}
diff --git a/app/Services/Invoice/MarkInvoiceDeleted.php b/app/Services/Invoice/MarkInvoiceDeleted.php
index b16c468c7c1e..e317c403ade6 100644
--- a/app/Services/Invoice/MarkInvoiceDeleted.php
+++ b/app/Services/Invoice/MarkInvoiceDeleted.php
@@ -53,16 +53,6 @@ class MarkInvoiceDeleted extends AbstractService
->adjustPaidToDateAndBalance()
->adjustLedger();
- $transaction = [
- 'invoice' => $this->invoice->transaction_event(),
- 'payment' => $this->invoice->payments()->exists() ? $this->invoice->payments()->first()->transaction_event() : [],
- 'client' => $this->invoice->client->transaction_event(),
- 'credit' => [],
- 'metadata' => ['total_payments' => $this->total_payments, 'balance_adjustment' => $this->balance_adjustment, 'adjustment_amount' => $this->adjustment_amount],
- ];
-
- // TransactionLog::dispatch(TransactionEvent::INVOICE_DELETED, $transaction, $this->invoice->company->db);
-
return $this->invoice;
}
@@ -87,26 +77,17 @@ class MarkInvoiceDeleted extends AbstractService
return $this;
}
- // @deprecated
- private function adjustBalance()
- {
- // $client = $this->invoice->client->fresh();
- // $client->balance += $this->balance_adjustment * -1;
- // $client->save();
-
- // $this->invoice->client->service()->updateBalance($this->balance_adjustment * -1)->save(); //reduces the client balance by the invoice amount.
-
- return $this;
- }
-
/* Adjust the payment amounts */
private function adjustPayments()
{
//if total payments = adjustment amount - that means we need to delete the payments as well.
- if ($this->adjustment_amount == $this->total_payments) {
+nlog($this->adjustment_amount);
+nlog($this->total_payments);
+
+ if ($this->adjustment_amount == $this->total_payments)
$this->invoice->payments()->update(['payments.deleted_at' => now(), 'payments.is_deleted' => true]);
- } else {
+
//adjust payments down by the amount applied to the invoice payment.
@@ -125,7 +106,7 @@ class MarkInvoiceDeleted extends AbstractService
$payment->applied -= $payment_adjustment;
$payment->save();
});
- }
+
return $this;
}
diff --git a/app/Utils/HostedPDF/NinjaPdf.php b/app/Utils/HostedPDF/NinjaPdf.php
index 7a6da2097b53..e0598b54c928 100644
--- a/app/Utils/HostedPDF/NinjaPdf.php
+++ b/app/Utils/HostedPDF/NinjaPdf.php
@@ -28,6 +28,6 @@ class NinjaPdf
RequestOptions::JSON => ['html' => $html],
]);
- return $response->getBody();
+ return $response->getBody()->getContents();
}
}
diff --git a/app/Utils/Traits/ClientGroupSettingsSaver.php b/app/Utils/Traits/ClientGroupSettingsSaver.php
index 67c2b6a774b3..270f2e0588cb 100644
--- a/app/Utils/Traits/ClientGroupSettingsSaver.php
+++ b/app/Utils/Traits/ClientGroupSettingsSaver.php
@@ -30,7 +30,7 @@ trait ClientGroupSettingsSaver
* Saves a setting object.
*
* Works for groups|clients|companies
- * @param array $settings The request input settings array
+ * @param array|object $settings The request input settings array
* @param object $entity The entity which the settings belongs to
* @return void
*/
@@ -64,19 +64,6 @@ trait ClientGroupSettingsSaver
$entity_settings->{$key} = $value;
}
- $entity->settings = $entity_settings;
-
- try{
- $entity->save();
- }
- catch(\Exception $e){
-
- nlog("client settings failure");
- nlog($entity_settings);
- nlog($e->getMessage());
-
- }
-
return $entity_settings;
}
diff --git a/config/ninja.php b/config/ninja.php
index 314b877deb28..15fec9f598ce 100644
--- a/config/ninja.php
+++ b/config/ninja.php
@@ -14,8 +14,8 @@ return [
'require_https' => env('REQUIRE_HTTPS', true),
'app_url' => rtrim(env('APP_URL', ''), '/'),
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
- 'app_version' => '5.5.43',
- 'app_tag' => '5.5.43',
+ 'app_version' => '5.5.44',
+ 'app_tag' => '5.5.44',
'minimum_client_version' => '5.0.16',
'terms_version' => '1.0.1',
'api_secret' => env('API_SECRET', ''),
diff --git a/lang/en/texts.php b/lang/en/texts.php
index 1bc294749e4a..a98bcf88145e 100644
--- a/lang/en/texts.php
+++ b/lang/en/texts.php
@@ -254,6 +254,8 @@ $LANG = array(
'notification_invoice_paid' => 'A payment of :amount was made by client :client towards Invoice :invoice.',
'notification_invoice_sent' => 'The following client :client was emailed Invoice :invoice for :amount.',
'notification_invoice_viewed' => 'The following client :client viewed Invoice :invoice for :amount.',
+ 'stripe_paymenttext' => 'Invoice :invoicenumber for :amount for client :client',
+ 'stripe_paymenttext_without_invoice' => 'Payment with no invoice for amount :amount for client :client',
'reset_password' => 'You can reset your account password by clicking the following button:',
'secure_payment' => 'Secure Payment',
'card_number' => 'Card Number',
@@ -4061,7 +4063,7 @@ $LANG = array(
'save_payment_method_details' => 'Save payment method details',
'new_card' => 'New card',
'new_bank_account' => 'New bank account',
- 'company_limit_reached' => 'Limit of 10 companies per account.',
+ 'company_limit_reached' => 'Limit of :limit companies per account.',
'credits_applied_validation' => 'Total credits applied cannot be MORE than total of invoices',
'credit_number_taken' => 'Credit number already taken',
'credit_not_found' => 'Credit not found',
diff --git a/tests/Feature/ClientApiTest.php b/tests/Feature/ClientApiTest.php
index aae531575656..40b11fc70a4a 100644
--- a/tests/Feature/ClientApiTest.php
+++ b/tests/Feature/ClientApiTest.php
@@ -11,12 +11,20 @@
namespace Tests\Feature;
+use App\DataMapper\ClientSettings;
+use App\Factory\ClientFactory;
+use App\Http\Requests\Client\StoreClientRequest;
+use App\Models\Client;
use App\Models\Country;
+use App\Repositories\ClientContactRepository;
+use App\Repositories\ClientRepository;
use App\Utils\Number;
+use App\Utils\Traits\ClientGroupSettingsSaver;
use App\Utils\Traits\MakesHash;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Session;
+use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
use Tests\MockAccountData;
use Tests\TestCase;
@@ -30,6 +38,7 @@ class ClientApiTest extends TestCase
use MakesHash;
use DatabaseTransactions;
use MockAccountData;
+ use ClientGroupSettingsSaver;
protected function setUp() :void
{
@@ -44,6 +53,302 @@ class ClientApiTest extends TestCase
Model::reguard();
}
+ public function testCsvImportRepositoryPersistance()
+ {
+ Client::unguard();
+
+ $data = [
+ 'company_id' => $this->company->id,
+ 'name' => 'Christian xx',
+ 'phone' => '',
+ 'address1' => '',
+ 'address2' => '',
+ 'postal_code' => '',
+ 'city' => '',
+ 'state' => '',
+ 'shipping_address1' => '',
+ 'shipping_address2' => '',
+ 'shipping_city' => '',
+ 'shipping_state' => '',
+ 'shipping_postal_code' => '',
+ 'public_notes' => '',
+ 'private_notes' => '',
+ 'website' => '',
+ 'vat_number' => '',
+ 'id_number' => '',
+ 'custom_value1' => '',
+ 'custom_value2' => '',
+ 'custom_value3' => '',
+ 'custom_value4' => '',
+ 'balance' => '0',
+ 'paid_to_date' => '0',
+ 'credit_balance' => 0,
+ 'settings' => [
+ 'entity' => 'App\\Models\\Client',
+ 'currency_id' => '3',
+ ],
+ 'client_hash' => 'xx',
+ 'contacts' =>
+ [
+ [
+ 'first_name' => '',
+ 'last_name' => '',
+ 'email' => '',
+ 'phone' => '',
+ 'custom_value1' => '',
+ 'custom_value2' => '',
+ 'custom_value3' => '',
+ 'custom_value4' => '',
+ ]
+ ],
+ 'country_id' => NULL,
+ 'shipping_country_id' => NULL,
+ 'user_id' => $this->user->id,
+ ];
+
+ $repository_name = ClientRepository::class;
+ $factory_name = ClientFactory::class;
+
+ $repository = app()->make($repository_name);
+ $repository->import_mode = true;
+
+ $c = $repository->save(array_diff_key($data, ['user_id' => false]), ClientFactory::create($this->company->id, $this->user->id));
+
+ Client::reguard();
+
+ $c->refresh();
+
+ $this->assertEquals("3", $c->settings->currency_id);
+
+ }
+
+ public function testClientSettingsSave()
+ {
+
+ $std = new \stdClass;
+ $std->entity = 'App\\Models\\Client';
+ $std->currency_id = 3;
+
+ $this->settings = $this->client->settings;
+
+ $this->saveSettings($std, $this->client);
+
+ $this->assertTrue(true);
+
+ }
+
+
+ public function testClientSettingsSave2()
+ {
+
+ $std = new \stdClass;
+ $std->entity = 'App\\Models\\Client';
+ $std->industry_id = '';
+ $std->size_id = '';
+ $std->currency_id = 3;
+
+ $this->settings = $this->client->settings;
+
+ $this->saveSettings($std, $this->client);
+
+ $this->assertTrue(true);
+
+ }
+
+ public function testClientStoreValidation()
+ {
+
+ auth()->login($this->user, false);
+ auth()->user()->setCompany($this->company);
+
+ $data = array (
+ 'company_id' => $this->company->id,
+ 'name' => 'Christian xx',
+ 'phone' => '',
+ 'address1' => '',
+ 'address2' => '',
+ 'postal_code' => '',
+ 'city' => '',
+ 'state' => '',
+ 'shipping_address1' => '',
+ 'shipping_address2' => '',
+ 'shipping_city' => '',
+ 'shipping_state' => '',
+ 'shipping_postal_code' => '',
+ 'public_notes' => '',
+ 'private_notes' => '',
+ 'website' => '',
+ 'vat_number' => '',
+ 'id_number' => '',
+ 'custom_value1' => '',
+ 'custom_value2' => '',
+ 'custom_value3' => '',
+ 'custom_value4' => '',
+ 'balance' => '0',
+ 'paid_to_date' => '0',
+ 'credit_balance' => 0,
+ 'settings' =>
+ (object) array(
+ 'entity' => 'App\\Models\\Client',
+ 'currency_id' => '3',
+ ),
+ 'client_hash' => 'xx',
+ 'contacts' =>
+ array (
+ 0 =>
+ array (
+ 'first_name' => '',
+ 'last_name' => '',
+ 'email' => '',
+ 'phone' => '',
+ 'custom_value1' => '',
+ 'custom_value2' => '',
+ 'custom_value3' => '',
+ 'custom_value4' => '',
+ ),
+ ),
+ 'country_id' => NULL,
+ 'shipping_country_id' => NULL,
+ 'user_id' => $this->user->id,
+ );
+
+
+ $request_name = StoreClientRequest::class;
+ $repository_name = ClientRepository::class;
+ $factory_name = ClientFactory::class;
+
+ $repository = app()->make($repository_name);
+ $repository->import_mode = true;
+
+ $_syn_request_class = new $request_name;
+ $_syn_request_class->setContainer(app());
+ $_syn_request_class->initialize($data);
+ $_syn_request_class->prepareForValidation();
+
+ $validator = Validator::make($_syn_request_class->all(), $_syn_request_class->rules());
+
+ $_syn_request_class->setValidator($validator);
+
+ $this->assertFalse($validator->fails());
+
+
+ }
+
+
+
+ public function testClientImportDataStructure()
+ {
+
+
+ $data = array (
+ 'company_id' => $this->company->id,
+ 'name' => 'Christian xx',
+ 'phone' => '',
+ 'address1' => '',
+ 'address2' => '',
+ 'postal_code' => '',
+ 'city' => '',
+ 'state' => '',
+ 'shipping_address1' => '',
+ 'shipping_address2' => '',
+ 'shipping_city' => '',
+ 'shipping_state' => '',
+ 'shipping_postal_code' => '',
+ 'public_notes' => '',
+ 'private_notes' => '',
+ 'website' => '',
+ 'vat_number' => '',
+ 'id_number' => '',
+ 'custom_value1' => '',
+ 'custom_value2' => '',
+ 'custom_value3' => '',
+ 'custom_value4' => '',
+ 'balance' => '0',
+ 'paid_to_date' => '0',
+ 'credit_balance' => 0,
+ 'settings' =>
+ (object) array(
+ 'entity' => 'App\\Models\\Client',
+ 'currency_id' => '3',
+ ),
+ 'client_hash' => 'xx',
+ 'contacts' =>
+ array (
+ 0 =>
+ array (
+ 'first_name' => '',
+ 'last_name' => '',
+ 'email' => '',
+ 'phone' => '',
+ 'custom_value1' => '',
+ 'custom_value2' => '',
+ 'custom_value3' => '',
+ 'custom_value4' => '',
+ ),
+ ),
+ 'country_id' => NULL,
+ 'shipping_country_id' => NULL,
+ 'user_id' => $this->user->id,
+ );
+
+ $crepo = new ClientRepository(new ClientContactRepository());
+
+ $c = $crepo->save(array_diff_key($data, ['user_id' => false]), ClientFactory::create($this->company->id, $this->user->id));
+ $c->saveQuietly();
+
+ $this->assertEquals('Christian xx', $c->name);
+ $this->assertEquals('3', $c->settings->currency_id);
+ }
+
+ public function testClientCsvImport()
+ {
+
+ $settings = ClientSettings::defaults();
+ $settings->currency_id = "840";
+
+ $data = [
+ 'name' => $this->faker->firstName(),
+ 'id_number' => 'Coolio',
+ 'settings' => (array)$settings,
+ 'contacts' => [
+ [
+ 'first_name' => '',
+ 'last_name' => '',
+ 'email' => '',
+ 'phone' => '',
+ 'custom_value1' => '',
+ 'custom_value2' => '',
+ 'custom_value3' => '',
+ 'custom_value4' => '',
+ ]
+ ]
+ ];
+
+ $response = false;
+
+ try {
+ $response = $this->withHeaders([
+ 'X-API-SECRET' => config('ninja.api_secret'),
+ 'X-API-TOKEN' => $this->token,
+ ])->post('/api/v1/clients/', $data);
+ } catch (ValidationException $e) {
+ $message = json_decode($e->validator->getMessageBag(), 1);
+ nlog($message);
+ }
+
+ $response->assertStatus(200);
+
+ $crepo = new ClientRepository(new ClientContactRepository());
+
+ $c = $crepo->save($data, ClientFactory::create($this->company->id, $this->user->id));
+ $c->saveQuietly();
+
+
+ }
+
+
+
+
public function testIllegalPropertiesInClientSettings()
{
$settings = [
diff --git a/tests/Feature/DeleteInvoiceTest.php b/tests/Feature/DeleteInvoiceTest.php
index d49f6f27c9e9..8dcf2daf4764 100644
--- a/tests/Feature/DeleteInvoiceTest.php
+++ b/tests/Feature/DeleteInvoiceTest.php
@@ -162,6 +162,7 @@ class DeleteInvoiceTest extends TestCase
$payment = $payment->fresh();
$this->assertTrue($payment->is_deleted);
+ $this->assertEquals(0, $payment->amount);
$this->assertEquals(4, $payment->status_id);
$client->fresh();