1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-10 13:12:50 +01:00

Merge pull request #7754 from turbo124/v5-develop

v5.5.11
This commit is contained in:
David Bomba 2022-08-17 17:19:16 +10:00 committed by GitHub
commit e37b24eab6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 818 additions and 526 deletions

View File

@ -1 +1 @@
5.5.10
5.5.11

View File

@ -166,7 +166,7 @@ class SendRemindersCron extends Command
$invoice_item = new InvoiceItem;
$invoice_item->type_id = '5';
$invoice_item->product_key = trans('texts.fee');
$invoice_item->product_key = ctrans('texts.fee');
$invoice_item->notes = ctrans('texts.late_fee_added', ['date' => $this->translateDate(now()->startOfDay(), $invoice->client->date_format(), $invoice->client->locale())]);
$invoice_item->quantity = 1;
$invoice_item->cost = $fee;

View File

@ -65,6 +65,7 @@ class BaseTransformer
public function getClient($client_name, $client_email)
{
if (! empty($client_name)) {
$client_id_search = $this->company
->clients()

View File

@ -38,13 +38,15 @@ class ClientTransformer extends BaseTransformer
$settings->payment_terms = $data['Payment Terms'];
}
$client_id_proxy = array_key_exists('Customer ID', $data) ? 'Customer ID' : 'Primary Contact ID';
return [
'company_id' => $this->company->id,
'name' => $this->getString($data, 'Company Name'),
'name' => $this->getString($data, 'Display Name'),
'phone' => $this->getString($data, 'Phone'),
'private_notes' => $this->getString($data, 'Notes'),
'website' => $this->getString($data, 'Website'),
'id_number' => $this->getString($data, 'Customer ID'),
'id_number' => $this->getString($data, $client_id_proxy),
'address1' => $this->getString($data, 'Billing Address'),
'address2' => $this->getString($data, 'Billing Street2'),
'city' => $this->getString($data, 'Billing City'),

View File

@ -40,7 +40,7 @@ class InvoiceTransformer extends BaseTransformer
$transformed = [
'company_id' => $this->company->id,
'client_id' => $this->getClient($this->getString($invoice_data, 'Customer ID'), null),
'client_id' => $this->getClient($this->getString($invoice_data, 'Customer ID'), $this->getString($invoice_data, 'Primary Contact EmailID')),
'number' => $this->getString($invoice_data, 'Invoice Number'),
'date' => isset($invoice_data['Invoice Date']) ? date('Y-m-d', strtotime($invoice_data['Invoice Date'])) : null,
'due_date' => isset($invoice_data['Due Date']) ? date('Y-m-d', strtotime($invoice_data['Due Date'])) : null,
@ -51,14 +51,19 @@ class InvoiceTransformer extends BaseTransformer
'balance' => $this->getFloat($invoice_data, 'Balance'),
'status_id' => $invoiceStatusMap[$status =
strtolower($this->getString($invoice_data, 'Invoice Status'))] ?? Invoice::STATUS_SENT,
'terms' => $this->getString($invoice_data, 'Terms & Conditions'),
// 'viewed' => $status === 'viewed',
];
$line_items = [];
foreach ($line_items_data as $record) {
$item_notes_key = array_key_exists('Item Description', $record) ? 'Item Description' : 'Item Desc';
$line_items[] = [
'product_key' => $this->getString($record, 'Item Name'),
'notes' => $this->getString($record, 'Item Description'),
'notes' => $this->getString($record, $item_notes_key),
'cost' => round($this->getFloat($record, 'Item Price'), 2),
'quantity' => $this->getFloat($record, 'Quantity'),
'discount' => $this->getString($record, 'Discount Amount'),

View File

@ -102,6 +102,17 @@ class NinjaMailerJob implements ShouldQueue
$this->nmo->mailable->tag($this->company->company_key);
if($this->nmo->invitation)
{
$this->nmo
->mailable
->withSymfonyMessage(function ($message) {
$message->getHeaders()->addTextHeader('x-invitation', $this->nmo->invitation->key);
});
}
//send email
try {
nlog("trying to send to {$this->nmo->to_user->email} ". now()->toDateTimeString());

View File

@ -26,6 +26,7 @@ use App\Models\Company;
use App\Models\CreditInvitation;
use App\Models\InvoiceInvitation;
use App\Models\Payment;
use App\Models\PurchaseOrderInvitation;
use App\Models\QuoteInvitation;
use App\Models\RecurringInvoiceInvitation;
use App\Models\SystemLog;
@ -283,6 +284,8 @@ class ProcessPostmarkWebhook implements ShouldQueue
return $invitation;
elseif($invitation = CreditInvitation::where('message_id', $message_id)->first())
return $invitation;
elseif($invitation = PurchaseOrderInvitation::where('message_id', $message_id)->first())
return $invitation;
else
return $invitation;
}

View File

@ -12,9 +12,15 @@
namespace App\Listeners\Mail;
use App\Libraries\MultiDB;
use App\Models\CreditInvitation;
use App\Models\InvoiceInvitation;
use App\Models\PurchaseOrderInvitation;
use App\Models\QuoteInvitation;
use App\Models\RecurringInvoiceInvitation;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Events\MessageSent;
use Illuminate\Support\Facades\Notification;
use Symfony\Component\Mime\MessageConverter;
class MailSentListener implements ShouldQueue
{
@ -35,19 +41,50 @@ class MailSentListener implements ShouldQueue
*/
public function handle(MessageSent $event)
{
nlog("mail listener");
nlog($event);
// if (property_exists($event->message, 'invitation') && $event->message->invitation) {
// MultiDB::setDb($event->sent->invitation->company->db);
// if ($event->message->getHeaders()->get('x-pm-message-id')) {
// $postmark_id = $event->sent->getHeaders()->get('x-pm-message-id')->getValue();
$message_id = $event->sent->getMessageId();
$message = MessageConverter::toEmail($event->sent->getOriginalMessage());
$invitation_key = $message->getHeaders()->get('x-invitation')->getValue();
if($message_id && $invitation_key)
{
$invitation = $this->discoverInvitation($invitation_key);
if(!$invitation)
return;
$invitation->message_id = $message_id;
$invitation->save();
}
// // nlog($postmark_id);
// $invitation = $event->sent->invitation;
// $invitation->message_id = $postmark_id;
// $invitation->save();
// }
// }
}
private function discoverInvitation($key)
{
$invitation = false;
foreach (MultiDB::$dbs as $db)
{
if($invitation = InvoiceInvitation::on($db)->where('key', $key)->first())
return $invitation;
elseif($invitation = QuoteInvitation::on($db)->where('key', $key)->first())
return $invitation;
elseif($invitation = RecurringInvoiceInvitation::on($db)->where('key', $key)->first())
return $invitation;
elseif($invitation = CreditInvitation::on($db)->where('key', $key)->first())
return $invitation;
elseif($invitation = PurchaseOrderInvitation::on($db)->where('key', $key)->first())
return $invitation;
}
return $invitation;
}
}

View File

@ -271,9 +271,9 @@ class EventServiceProvider extends ServiceProvider
],
MessageSending::class => [
],
// MessageSent::class => [
// MailSentListener::class,
// ],
MessageSent::class => [
MailSentListener::class,
],
UserWasCreated::class => [
CreatedUserActivity::class,
SendVerificationNotification::class,

View File

@ -50,10 +50,8 @@ class Design extends BaseDesign
/** Construct options */
public $options;
/** @var Invoice[] */
public $invoices;
/** @var Payment[] */
public $payments;
public $settings_object;

View File

@ -80,7 +80,6 @@ class ConvertQuote
/**
* Only create the invitations that are defined on the quote.
*
* @return Invoice $invoice
*/
private function createConversionInvitations($invoice, $quote)
{

View File

@ -129,7 +129,8 @@ class QuoteService
/**
* Sometimes we need to refresh the
* PDF when it is updated etc.
* @return InvoiceService
*
* @return QuoteService
*/
public function touchPdf($force = false)
{

View File

@ -840,7 +840,6 @@ class SubscriptionService
* Get the single charge products for the
* subscription
*
* @return ?Product Collection
*/
public function products()
{
@ -859,7 +858,6 @@ class SubscriptionService
* Get the recurring products for the
* subscription
*
* @return ?Product Collection
*/
public function recurring_products()
{

View File

@ -42,8 +42,8 @@ class CompanyUserTransformer extends EntityTransformer
return [
'permissions' => $company_user->permissions ?: '',
'notifications' => (object) $company_user->notifications ?: $blank_obj,
'settings' => (object) $company_user->settings ?: $blank_obj,
'notifications' => $company_user->notifications ? (object) $company_user->notifications : $blank_obj,
'settings' => $company_user->settings ? (object) $company_user->settings : $blank_obj,
'is_owner' => (bool) $company_user->is_owner,
'is_admin' => (bool) $company_user->is_admin,
'is_locked' => (bool) $company_user->is_locked,

View File

@ -80,7 +80,6 @@ class CreditTransformer extends EntityTransformer
'amount' => (float) $credit->amount,
'balance' => (float) $credit->balance,
'client_id' => (string) $this->encodePrimaryKey($credit->client_id),
'vendor_id' => (string) $this->encodePrimaryKey($credit->vendor_id),
'status_id' => (string) ($credit->status_id ?: 1),
'design_id' => (string) $this->encodePrimaryKey($credit->design_id),
'created_at' => (int) $credit->created_at,

View File

@ -137,7 +137,6 @@ class RecurringInvoiceTransformer extends EntityTransformer
'due_date_days' => (string) $invoice->due_date_days ?: '',
'paid_to_date' => (float) $invoice->paid_to_date,
'subscription_id' => (string) $this->encodePrimaryKey($invoice->subscription_id),
'recurring_dates' => (array) [],
];
if (request()->has('show_dates') && request()->query('show_dates') == 'true') {

View File

@ -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.10',
'app_tag' => '5.5.10',
'app_version' => '5.5.11',
'app_tag' => '5.5.11',
'minimum_client_version' => '5.0.16',
'terms_version' => '1.0.1',
'api_secret' => env('API_SECRET', ''),

View File

@ -4730,6 +4730,43 @@ $LANG = array(
'converted_to_expenses' => 'Successfully converted to expenses',
'entity_removed' => 'This document has been removed, please contact the vendor for further information',
'entity_removed_title' => 'Document no longer available',
'field' => 'Field',
'period' => 'Period',
'fields_per_row' => 'Fields Per Row',
'total_active_invoices' => 'Active Invoices',
'total_outstanding_invoices' => 'Outstanding Invoices',
'total_completed_payments' => 'Completed Payments',
'total_refunded_payments' => 'Refunded Payments',
'total_active_quotes' => 'Active Quotes',
'total_approved_quotes' => 'Approved Quotes',
'total_unapproved_quotes' => 'Unapproved Quotes',
'total_logged_tasks' => 'Logged Tasks',
'total_invoiced_tasks' => 'Invoiced Tasks',
'total_paid_tasks' => 'Paid Tasks',
'total_logged_expenses' => 'Logged Expenses',
'total_pending_expenses' => 'Pending Expenses',
'total_invoiced_expenses' => 'Invoiced Expenses',
'total_invoice_paid_expenses' => 'Invoice Paid Expenses',
'vendor_portal' => 'Vendor Portal',
'send_code' => 'Send Code',
'save_to_upload_documents' => 'Save the record to upload documents',
'expense_tax_rates' => 'Expense Tax Rates',
'invoice_item_tax_rates' => 'Invoice Item Tax Rates',
'verified_phone_number' => 'Successfully verified phone number',
'code_was_sent' => 'A code has been sent via SMS',
'resend' => 'Resend',
'verify' => 'Verify',
'enter_phone_number' => 'Please provide a phone number',
'invalid_phone_number' => 'Invalid phone number',
'verify_phone_number' => 'Verify Phone Number',
'verify_phone_number_help' => 'Please verify your phone number to send emails',
'merged_clients' => 'Successfully merged clients',
'merge_into' => 'Merge Into',
'php81_required' => 'Note: v5.5 requires PHP 8.1',
'bulk_email_purchase_orders' => 'Email Purchase Orders',
'bulk_email_invoices' => 'Email Invoices',
'bulk_email_quotes' => 'Email Quotes',
'bulk_email_credits' => 'Email Credits',
);
return $LANG;

View File

@ -200,7 +200,7 @@ $LANG = array(
'removed_logo' => 'Logotipo removido com sucesso',
'sent_message' => 'Mensagem enviada com sucesso',
'invoice_error' => 'Assegure-se de selecionar um cliente e corrigir quaisquer erros',
'limit_clients' => 'Desculpe, isto irá exceder o limite de :count clientes',
'limit_clients' => 'Sorry, this will exceed the limit of :count clients. Please upgrade to a paid plan.',
'payment_error' => 'Ocorreu um erro ao processar seu pagamento. Por favor tente novamente mais tarde.',
'registration_required' => 'Favor cadastre-se para enviar uma fatura por email',
'confirmation_required' => 'Por favor confirme seu endereço de email, :link para re-enviar o email de confirmação.',
@ -2241,7 +2241,7 @@ Quando tiver as quantias, volte a esta página de formas de pagamento e clique "
'navigation_variables' => 'Variáveis de Navegação',
'custom_variables' => 'Variáveis Personalizadas',
'invalid_file' => 'Tipo de arquivo inválido',
'add_documents_to_invoice' => 'Adicionar documentos à fatura',
'add_documents_to_invoice' => 'Add Documents to Invoice',
'mark_expense_paid' => 'Marcar como pago',
'white_label_license_error' => 'Falha ao validar a licença, verifique storage/logs/laravel-error.log para mais detalhes.',
'plan_price' => 'Preço do Plano',
@ -4628,6 +4628,102 @@ Quando tiver as quantias, volte a esta página de formas de pagamento e clique "
'notification_purchase_order_accepted_subject' => 'Purchase Order :purchase_order was accepted by :vendor',
'notification_purchase_order_accepted' => 'The following vendor :vendor accepted Purchase Order :purchase_order for :amount.',
'amount_received' => 'Amount received',
'purchase_order_already_expensed' => 'Already converted to an expense.',
'convert_to_expense' => 'Convert to Expense',
'add_to_inventory' => 'Add to Inventory',
'added_purchase_order_to_inventory' => 'Successfully added purchase order to inventory',
'added_purchase_orders_to_inventory' => 'Successfully added purchase orders to inventory',
'client_document_upload' => 'Client Document Upload',
'vendor_document_upload' => 'Vendor Document Upload',
'vendor_document_upload_help' => 'Enable vendors to upload documents',
'are_you_enjoying_the_app' => 'Are you enjoying the app?',
'yes_its_great' => 'Yes, it"s great!',
'not_so_much' => 'Not so much',
'would_you_rate_it' => 'Great to hear! Would you like to rate it?',
'would_you_tell_us_more' => 'Sorry to hear it! Would you like to tell us more?',
'sure_happy_to' => 'Sure, happy to',
'no_not_now' => 'No, not now',
'add' => 'Add',
'last_sent_template' => 'Last Sent Template',
'enable_flexible_search' => 'Enable Flexible Search',
'enable_flexible_search_help' => 'Match non-contiguous characters, ie. "ct" matches "cat"',
'vendor_details' => 'Vendor Details',
'purchase_order_details' => 'Purchase Order Details',
'qr_iban' => 'QR IBAN',
'besr_id' => 'BESR ID',
'clone_to_purchase_order' => 'Clone to PO',
'vendor_email_not_set' => 'Vendor does not have an email address set',
'bulk_send_email' => 'Send Email',
'marked_purchase_order_as_sent' => 'Successfully marked purchase order as sent',
'marked_purchase_orders_as_sent' => 'Successfully marked purchase orders as sent',
'accepted_purchase_order' => 'Successfully accepted purchase order',
'accepted_purchase_orders' => 'Successfully accepted purchase orders',
'cancelled_purchase_order' => 'Successfully cancelled purchase order',
'cancelled_purchase_orders' => 'Successfully cancelled purchase orders',
'please_select_a_vendor' => 'Please select a vendor',
'purchase_order_total' => 'Purchase Order Total',
'email_purchase_order' => 'Email Purchase Order',
'bulk_email_purchase_order' => 'Email Purchase Order',
'disconnected_email' => 'Successfully disconnected email',
'connect_email' => 'Connect Email',
'disconnect_email' => 'Disconnect Email',
'use_web_app_to_connect_microsoft' => 'Please use the web app to connect to Microsoft',
'email_provider' => 'Email Provider',
'connect_microsoft' => 'Connect Microsoft',
'disconnect_microsoft' => 'Disconnect Microsoft',
'connected_microsoft' => 'Successfully connected Microsoft',
'disconnected_microsoft' => 'Successfully disconnected Microsoft',
'microsoft_sign_in' => 'Login with Microsoft',
'microsoft_sign_up' => 'Sign up with Microsoft',
'emailed_purchase_order' => 'Successfully queued purchase order to be sent',
'emailed_purchase_orders' => 'Successfully queued purchase orders to be sent',
'enable_react_app' => 'Change to the React web app',
'purchase_order_design' => 'Purchase Order Design',
'purchase_order_terms' => 'Purchase Order Terms',
'purchase_order_footer' => 'Purchase Order Footer',
'require_purchase_order_signature' => 'Purchase Order Signature',
'require_purchase_order_signature_help' => 'Require vendor to provide their signature.',
'new_purchase_order' => 'New Purchase Order',
'edit_purchase_order' => 'Edit Purchase Order',
'created_purchase_order' => 'Successfully created purchase order',
'updated_purchase_order' => 'Successfully updated purchase order',
'archived_purchase_order' => 'Successfully archived purchase order',
'deleted_purchase_order' => 'Successfully deleted purchase order',
'removed_purchase_order' => 'Successfully removed purchase order',
'restored_purchase_order' => 'Successfully restored purchase order',
'search_purchase_order' => 'Search Purchase Order',
'search_purchase_orders' => 'Search Purchase Orders',
'login_url' => 'Login URL',
'enable_applying_payments' => 'Enable Applying Payments',
'enable_applying_payments_help' => 'Support separately creating and applying payments',
'stock_quantity' => 'Stock Quantity',
'notification_threshold' => 'Notification Threshold',
'track_inventory' => 'Track Inventory',
'track_inventory_help' => 'Display a product stock field and update when invoices are sent',
'stock_notifications' => 'Stock Notifications',
'stock_notifications_help' => 'Send an email when the stock reaches the threshold',
'vat' => 'VAT',
'view_map' => 'View Map',
'set_default_design' => 'Set Default Design',
'add_gateway_help_message' => 'Add a payment gateway (ie. Stripe, WePay or PayPal) to accept online payments',
'purchase_order_issued_to' => 'Purchase Order issued to',
'archive_task_status' => 'Archive Task Status',
'delete_task_status' => 'Delete Task Status',
'restore_task_status' => 'Restore Task Status',
'lang_Hebrew' => 'Hebrew',
'price_change_accepted' => 'Price change accepted',
'price_change_failed' => 'Price change failed with code',
'restore_purchases' => 'Restore Purchases',
'activate' => 'Activate',
'connect_apple' => 'Connect Apple',
'disconnect_apple' => 'Disconnect Apple',
'disconnected_apple' => 'Successfully disconnected Apple',
'send_now' => 'Send Now',
'received' => 'Received',
'converted_to_expense' => 'Successfully converted to expense',
'converted_to_expenses' => 'Successfully converted to expenses',
'entity_removed' => 'This document has been removed, please contact the vendor for further information',
'entity_removed_title' => 'Document no longer available',
);
return $LANG;

File diff suppressed because it is too large Load Diff

View File

@ -57,6 +57,16 @@
<directory name="app" />
</errorLevel>
</UndefinedMagicPropertyFetch>
<TooManyArguments>
<errorLevel type="suppress">
<directory name="app" />
</errorLevel>
</TooManyArguments>
<RedundantCast>
<errorLevel type="suppress">
<directory name="app" />
</errorLevel>
</RedundantCast>
<InvalidNullableReturnType>
<errorLevel type="suppress">
<directory name="app" />