From 2b1e0e0e69003417c56289129e0ef94db3499b4f Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 28 Jun 2024 07:37:46 +1000 Subject: [PATCH 01/16] Updated translations --- lang/da/texts.php | 66 +++++++++++++++++--------------------------- lang/en/texts.php | 11 +++++++- lang/fr_CA/texts.php | 60 +++++++++++++++------------------------- 3 files changed, 57 insertions(+), 80 deletions(-) diff --git a/lang/da/texts.php b/lang/da/texts.php index 1f0bd29703f3..6612e9c386b6 100644 --- a/lang/da/texts.php +++ b/lang/da/texts.php @@ -392,7 +392,7 @@ $lang = array( 'payment_cvv' => 'Dette er det 3-4 cifrede nummer på bagsiden af dit kort', 'payment_footer1' => '*Fakturaadressen skal matche den der er tilknyttet kortet.', 'payment_footer2' => '*Klik kun på "Betal Nu" én gang - transaktionen kan tage helt op til 1 minut inden den er færdig.', - 'id_number' => 'CVR/SE-nummer', + 'id_number' => 'ID Nummer', 'white_label_link' => 'Hvidmærket', 'white_label_header' => 'Hvidmærket', 'bought_white_label' => 'Hvidmærket licens accepteret', @@ -2363,7 +2363,7 @@ $lang = array( 'currency_gold_troy_ounce' => 'Guld Troy Ounce', 'currency_nicaraguan_córdoba' => 'Nicaraguanske Córdoba', 'currency_malagasy_ariary' => 'Madagaskars ariary', - "currency_tongan_pa_anga" => "tonganske paanga", + "currency_tongan_paanga" => "Tongan Pa'anga", 'review_app_help' => 'Vi håber, du nyder at bruge appen.
Hvis du ville overveje :link ville vi sætte stor pris på det!', 'writing_a_review' => 'skrive en anmeldelse', @@ -2879,19 +2879,6 @@ $lang = array( 'refunded' => 'Refunderet', 'marked_quote_as_sent' => 'Succesfuldt markeret tilbud som sendt', 'custom_module_settings' => 'Speciel Modul Indstillinger', - 'ticket' => 'Sag', - 'tickets' => 'Sager', - 'ticket_number' => 'Sag #', - 'new_ticket' => 'Ny sag', - 'edit_ticket' => 'Redigér sag', - 'view_ticket' => 'Vis sag', - 'archive_ticket' => 'Arkivér sag', - 'restore_ticket' => 'Genskab sag', - 'delete_ticket' => 'Slet sag', - 'archived_ticket' => 'Sag blev arkiveret', - 'archived_tickets' => 'Sager blev arkiveret', - 'restored_ticket' => 'Sag blev genskabt', - 'deleted_ticket' => 'Sag blev slettet', 'open' => 'Åben', 'new' => 'Ny', 'closed' => 'Lukket', @@ -2908,14 +2895,6 @@ $lang = array( 'assigned_to' => 'Tildelt', 'reply' => 'Svar', 'awaiting_reply' => 'Afventer svar', - 'ticket_close' => 'Luk sag', - 'ticket_reopen' => 'Genåbn sag', - 'ticket_open' => 'Åbn sag', - 'ticket_split' => 'Opdel sag', - 'ticket_merge' => 'Sammenflet sag', - 'ticket_update' => 'Opdatér sag', - 'ticket_settings' => 'Sagsindstillinger', - 'updated_ticket' => 'Sag blev opdateret', 'mark_spam' => 'Marker som spam', 'local_part' => 'Lokal del', 'local_part_unavailable' => 'Navn taget', @@ -2933,31 +2912,23 @@ $lang = array( 'mime_types' => 'Mime typer', 'mime_types_placeholder' => '. PDF , .docx, .jpg', 'mime_types_help' => 'Kommasepareret liste over tilladte mime-typer, lad tom for alle', + 'ticket_number_start_help' => 'Ticket number must be greater than the current ticket number', + 'new_ticket_template_id' => 'New ticket', + 'new_ticket_autoresponder_help' => 'Selecting a template will send an auto response to a client/contact when a new ticket is created', + 'update_ticket_template_id' => 'Updated ticket', + 'update_ticket_autoresponder_help' => 'Selecting a template will send an auto response to a client/contact when a ticket is updated', + 'close_ticket_template_id' => 'Closed ticket', + 'close_ticket_autoresponder_help' => 'Selecting a template will send an auto response to a client/contact when a ticket is closed', 'default_priority' => 'Standardprioritet', 'alert_new_comment_id' => 'Ny kommentar', - 'alert_comment_ticket_help' => 'Hvis du vælger en skabelon, sendes der en meddelelse (til agent), når der kommer en kommentar.', - 'alert_comment_ticket_email_help' => 'Kommaseparerede e-mails til bcc ved ny kommentar.', - 'new_ticket_notification_list' => 'Yderligere nye Sag -meddelelser', 'update_ticket_notification_list' => 'Yderligere meddelelser om nye kommentarer', 'comma_separated_values' => 'admin@example.com, supervisor@example.com', - 'alert_ticket_assign_agent_id' => 'Tildeling af sag', - 'alert_ticket_assign_agent_id_hel' => 'Valg af en skabelon vil sende en meddelelse (til agent), når en Sag er tildelt.', - 'alert_ticket_assign_agent_id_notifications' => 'Yderligere Sag tildelte meddelelser', - 'alert_ticket_assign_agent_id_help' => 'Kommaseparerede e-mails til bcc på Sag opgave.', - 'alert_ticket_transfer_email_help' => 'Kommaseparerede e-mails til bcc ved Sag overførsel.', - 'alert_ticket_overdue_agent_id' => 'Sag er forfalden', - 'alert_ticket_overdue_email' => 'Yderligere forfaldne Sag -meddelelser', - 'alert_ticket_overdue_email_help' => 'Kommaseparerede e-mails til bcc på Sag forsinket.', - 'alert_ticket_overdue_agent_id_help' => 'Valg af en skabelon vil sende en meddelelse (til agent), når en Sag bliver forsinket.', 'default_agent' => 'Standardagent', 'default_agent_help' => 'Hvis valgt vil det automatisk blive tildelt alle indgående billetter', 'show_agent_details' => 'Vis agentoplysninger om svar', 'avatar' => 'Avatar', 'remove_avatar' => 'Fjern avatar', - 'ticket_not_found' => 'Sag blev ikke fundet', 'add_template' => 'Tilføj skabelon', - 'updated_ticket_template' => 'Sagsskabelon blev opdateret', - 'created_ticket_template' => 'Sagsskabelon blev oprettet', 'archive_ticket_template' => 'Arkiv skabelon', 'restore_ticket_template' => 'Genskab skabelon', 'archived_ticket_template' => 'Succesfuldt arkiveret skabelon', @@ -3130,7 +3101,7 @@ $lang = array( 'sign_up_with_google' => 'Tilmeld dig med Google', 'long_press_multiselect' => 'Tryk længe på Multiselect', 'migrate_to_next_version' => 'Migrer til den næste version af Faktura Ninja', - 'migrate_intro_text' => 'Vi har arbejdet på næste version af Faktura Ninja. Klik på knappen nedenfor for at starte migreringen.', + 'migrate_intro_text' => 'Vi har arbejdet på næste version af Invoice Ninja. Klik på knappen nedenfor for at starte migreringen.', 'start_the_migration' => 'Start migreringen', 'migration' => 'Migration', 'welcome_to_the_new_version' => 'Velkommen til den nye version af Faktura Ninja', @@ -4504,7 +4475,7 @@ $lang = array( 'view_purchase_order' => 'Vis Indkøbsordre', 'purchase_orders_backup_subject' => 'Dine indkøbsordrer er klar til download', 'notification_purchase_order_viewed_subject' => 'Indkøbsordre :invoice blev set af :client', - 'notification_purchase_order_viewed' => 'Følgende Sælger :client har set Indkøbsordre :invoice for :amount .', + 'notification_purchase_order_viewed' => 'Følgende leverandør :client har set Indkøbsordre :invoice for :amount .', 'purchase_order_date' => 'Dato for købsordre', 'purchase_orders' => 'Indkøbsordre', 'purchase_order_number_placeholder' => 'Indkøbsordre nr. :purchase_order', @@ -5302,6 +5273,19 @@ $lang = array( 'currency_bhutan_ngultrum' => 'Bhutan Ngultrum', 'end_of_month' => 'End Of Month', 'merge_e_invoice_to_pdf' => 'Merge E-Invoice and PDF', + 'task_assigned_subject' => 'New task assignment [Task :task] [ :date ]', + 'task_assigned_body' => 'You have been assigned task :task

Description: :description

Client: :client', + 'activity_141' => 'User :user entered note: :notes', + 'quote_reminder_subject' => 'Reminder: Quote :quote from :company', + 'quote_reminder_message' => 'Reminder for quote :number for :amount', + 'quote_reminder1' => 'First Quote Reminder', + 'before_valid_until_date' => 'Before the valid until date', + 'after_valid_until_date' => 'After the valid until date', + 'after_quote_date' => 'After the quote date', + 'remind_quote' => 'Remind Quote', + 'end_of_month' => 'End Of Month', + 'tax_currency_mismatch' => 'Tax currency is different from invoice currency', + 'edocument_import_already_exists' => '\nThe invoice has already been imported on :date' ); -return $lang; \ No newline at end of file +return $lang; diff --git a/lang/en/texts.php b/lang/en/texts.php index 7a44966e7df6..550c81dfd1a7 100644 --- a/lang/en/texts.php +++ b/lang/en/texts.php @@ -5286,7 +5286,16 @@ $lang = array( 'remind_quote' => 'Remind Quote', 'end_of_month' => 'End Of Month', 'tax_currency_mismatch' => 'Tax currency is different from invoice currency', - 'edocument_import_already_exists' => '\nThe invoice has already been imported on :date' + 'edocument_import_already_exists' => '\nThe invoice has already been imported on :date', + 'before_valid_until' => 'Before the valid until', + 'after_valid_until' => 'After the valid until', + 'task_assigned_notification' => 'Task Assigned Notification', + 'task_assigned_notification_help' => 'Send an email when a task is assigned', + 'invoices_locked_end_of_month' => 'Invoices are locked at the end of the month', + 'referral_url' => 'Referral URL', + 'add_comment' => 'Add Comment', + 'added_comment' => 'Successfully saved comment', + 'tickets' => 'Tickets', ); return $lang; diff --git a/lang/fr_CA/texts.php b/lang/fr_CA/texts.php index fff46aa33247..331307d6912e 100644 --- a/lang/fr_CA/texts.php +++ b/lang/fr_CA/texts.php @@ -2361,7 +2361,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette 'currency_gold_troy_ounce' => 'Once troy d\'or', 'currency_nicaraguan_córdoba' => 'Cordoba nicaraguayen', 'currency_malagasy_ariary' => 'Ariary malgache', - "currency_tongan_pa_anga" => "Pa'anga tongien", + "currency_tongan_paanga" => "Pa'anga tongien", 'review_app_help' => 'Nous espérons que votre utilisation de cette application vous est agréable.
Un commentaire de votre part serait grandement apprécié!', 'writing_a_review' => 'rédiger un commentaire', @@ -2877,19 +2877,6 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette 'refunded' => 'Remboursé', 'marked_quote_as_sent' => 'La soumission a été marquée comme envoyée', 'custom_module_settings' => 'Paramètres personnalisés de modules', - 'ticket' => 'Billet', - 'tickets' => 'Billets', - 'ticket_number' => 'Billet #', - 'new_ticket' => 'Nouveau billet', - 'edit_ticket' => 'Éditer le billet', - 'view_ticket' => 'Voir le billet', - 'archive_ticket' => 'Archiver le billet', - 'restore_ticket' => 'Restaurer le billet', - 'delete_ticket' => 'Supprimer le billet', - 'archived_ticket' => 'Le billet a été archivé', - 'archived_tickets' => 'Les billets ont été archivés', - 'restored_ticket' => 'Le billet a été restauré', - 'deleted_ticket' => 'Le billet a été supprimé', 'open' => 'Ouvert', 'new' => 'Nouveau', 'closed' => 'Désactivé', @@ -2906,14 +2893,6 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette 'assigned_to' => 'Assigné à', 'reply' => 'Répondre', 'awaiting_reply' => 'En attente de réponse', - 'ticket_close' => 'Fermer le billet', - 'ticket_reopen' => 'Réouvrir le billet', - 'ticket_open' => 'Ouvrir le billet', - 'ticket_split' => 'Scinder le billet', - 'ticket_merge' => 'Fusionner le billet', - 'ticket_update' => 'Mettre à jour le billet', - 'ticket_settings' => 'Paramètres des billets', - 'updated_ticket' => 'Billet mis à jour', 'mark_spam' => 'Marquer comme pourriel', 'local_part' => 'Partie locale', 'local_part_unavailable' => 'Nom déjà pris', @@ -2931,31 +2910,23 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette 'mime_types' => 'Type MIME', 'mime_types_placeholder' => '.pdf , .docx, .jpg', 'mime_types_help' => 'Liste séparée par une virgule pour les types MIME autorisés. Laissant vide pour tout autoriser', + 'ticket_number_start_help' => 'Le numéro du billet doit être supérieur au numéro de billet actuel.', + 'new_ticket_template_id' => 'Nouveau billet', + 'new_ticket_autoresponder_help' => 'La sélection d\'un modèle enverra automatiquement une réponse automatique à un client/contact lors de la création d\'un nouveau billet.', + 'update_ticket_template_id' => 'Le billet a été mis à jour', + 'update_ticket_autoresponder_help' => 'La sélection d\'un modèle déclenchera automatiquement l\'envoi d\'une réponse automatique à un client/contact lors de la mise à jour d\'un billet.', + 'close_ticket_template_id' => 'Le billet a ét fermé', + 'close_ticket_autoresponder_help' => 'La sélection d\'un modèle enverra automatiquement une réponse automatique à un client/contact lors de la fermeture d\'un billet.', 'default_priority' => 'Priorité par défaut', 'alert_new_comment_id' => 'Nouveau commentaire', - 'alert_comment_ticket_help' => 'En sélectionnant un modèle, une notification (à l\'agent) sera envoyée lorsqu\'un commentaire est fait', - 'alert_comment_ticket_email_help' => 'Courriels séparés par une virgule pour Cci sur un nouveau commentaire.', - 'new_ticket_notification_list' => 'Notifications de nouveaux billets additionnels', 'update_ticket_notification_list' => 'Notifications de nouveaux commentaires additionnels', 'comma_separated_values' => 'admin@exemple.com, supervisor@exemple.com', - 'alert_ticket_assign_agent_id' => 'Assignation de billet', - 'alert_ticket_assign_agent_id_hel' => 'En sélectionnant un modèle, une notification (à l\'agent) sera envoyée lorsqu\'un billet est assigné.', - 'alert_ticket_assign_agent_id_notifications' => 'Notifications de billets assignés additionnels', - 'alert_ticket_assign_agent_id_help' => 'Courriels séparés par une virgule pour Cci pour un billet assigné.', - 'alert_ticket_transfer_email_help' => 'Courriels séparés par une virgule pour Cci sur un billet transféré.', - 'alert_ticket_overdue_agent_id' => 'Billet en retard', - 'alert_ticket_overdue_email' => 'Notifications de billets en retard additionnels', - 'alert_ticket_overdue_email_help' => 'Courriels séparés par une virgule pour Cci sur un billet en retard.', - 'alert_ticket_overdue_agent_id_help' => 'En sélectionnant un modèle, une notification (à l\'agent) sera envoyée lorsqu\'un billet est en retard.', 'default_agent' => 'Agent par défaut', 'default_agent_help' => 'Cette sélection va automatiquement être assignée à tous les courriels entrants', 'show_agent_details' => 'Afficher les informations de l\'agent dans les réponses', 'avatar' => 'Avatar', 'remove_avatar' => 'Retirer l\'avatar', - 'ticket_not_found' => 'Billet introuvable', 'add_template' => 'Ajouter un modèle', - 'updated_ticket_template' => 'Modèle de billets mise à jour', - 'created_ticket_template' => 'Modèle de billet créés', 'archive_ticket_template' => 'Archiver le modèle', 'restore_ticket_template' => 'Restaurer le modèle', 'archived_ticket_template' => 'Le modèle a été archivé', @@ -5300,6 +5271,19 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette 'currency_bhutan_ngultrum' => 'Ngultrum Bhoutan', 'end_of_month' => 'Fin de mois', 'merge_e_invoice_to_pdf' => 'Fusionner E-Facture et PDF', + 'task_assigned_subject' => 'Nouvelle tâche assignée [Tâche:task] [ :date ]', + 'task_assigned_body' => 'Vous avez été assigné à la tâche :task

Description: :description

Client: :client', + 'activity_141' => 'L\'utilisateur:user a saisi la note: :notes', + 'quote_reminder_subject' => 'Rappel: Soumission:quote de :company', + 'quote_reminder_message' => 'Rappel pour la soumission :number de :amount', + 'quote_reminder1' => 'Rappel pour la première soumission', + 'before_valid_until_date' => 'Avant la date Valide jusqu\'au', + 'after_valid_until_date' => 'Après la date Valide jusqu\'au', + 'after_quote_date' => 'Après al date de soumission', + 'remind_quote' => 'Rappel de soumission', + 'end_of_month' => 'Fin de mois', + 'tax_currency_mismatch' => 'La devise de la taxe est différente de la devise de la facture.', + 'edocument_import_already_exists' => '\nLa facture a déjà été importée le :date' ); -return $lang; \ No newline at end of file +return $lang; From ecfa558bf3b733c18a505b4aaeb8d0e2767c2301 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 28 Jun 2024 09:40:40 +1000 Subject: [PATCH 02/16] do not leave index.html in /public --- .github/workflows/react_release.yml | 2 +- app/DataMapper/Tax/BaseRule.php | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/react_release.yml b/.github/workflows/react_release.yml index 55f42040ffdf..bce78bb249c3 100644 --- a/.github/workflows/react_release.yml +++ b/.github/workflows/react_release.yml @@ -48,7 +48,7 @@ jobs: npm i npm run build cp -r dist/* ../public/ - cp dist/index.html ../resources/views/react/index.blade.php + mv dist/index.html ../resources/views/react/index.blade.php - name: Prepare JS/CSS assets run: | diff --git a/app/DataMapper/Tax/BaseRule.php b/app/DataMapper/Tax/BaseRule.php index 78eb1bd9445b..b5b97766d674 100644 --- a/app/DataMapper/Tax/BaseRule.php +++ b/app/DataMapper/Tax/BaseRule.php @@ -379,6 +379,7 @@ class BaseRule implements RuleInterface public function override($item): self { + nlog("override"); $this->tax_rate1 = $item->tax_rate1; $this->tax_name1 = $item->tax_name1; $this->tax_rate2 = $item->tax_rate2; @@ -386,6 +387,7 @@ class BaseRule implements RuleInterface $this->tax_rate3 = $item->tax_rate3; $this->tax_name3 = $item->tax_name3; + nlog($item); return $this; } From b35d54a2c61e415b5792f550e7564e43b235c296 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 28 Jun 2024 09:43:00 +1000 Subject: [PATCH 03/16] Exclude vendor directory from file checks --- app/Http/Controllers/SelfUpdateController.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/SelfUpdateController.php b/app/Http/Controllers/SelfUpdateController.php index 09127929bd77..77c1e07bf2c7 100644 --- a/app/Http/Controllers/SelfUpdateController.php +++ b/app/Http/Controllers/SelfUpdateController.php @@ -35,6 +35,7 @@ class SelfUpdateController extends BaseController 'bootstrap/cache/services.php', 'bootstrap/cache/routes-v7.php', 'bootstrap/cache/livewire-components.php', + 'public/index.html', ]; public function __construct() @@ -114,7 +115,7 @@ class SelfUpdateController extends BaseController Artisan::call('config:clear'); Artisan::call('cache:clear'); - $this->runModelChecks(); + // $this->runModelChecks(); nlog('Called Artisan commands'); @@ -159,7 +160,7 @@ class SelfUpdateController extends BaseController $directoryIterator = new \RecursiveDirectoryIterator(base_path(), \RecursiveDirectoryIterator::SKIP_DOTS); foreach (new \RecursiveIteratorIterator($directoryIterator) as $file) { - if (strpos($file->getPathname(), '.git') !== false) { + if (strpos($file->getPathname(), '.git') !== false || strpos($file->getPathname(), 'vendor/') !== false) { continue; } From 6aac4a03b7e8853faab0e27be98e01a7a1de3ecd Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 28 Jun 2024 09:54:28 +1000 Subject: [PATCH 04/16] Fixes for override taxes for AT region --- app/DataMapper/Tax/BaseRule.php | 2 -- app/DataMapper/Tax/DE/Rule.php | 8 ++++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/DataMapper/Tax/BaseRule.php b/app/DataMapper/Tax/BaseRule.php index b5b97766d674..78eb1bd9445b 100644 --- a/app/DataMapper/Tax/BaseRule.php +++ b/app/DataMapper/Tax/BaseRule.php @@ -379,7 +379,6 @@ class BaseRule implements RuleInterface public function override($item): self { - nlog("override"); $this->tax_rate1 = $item->tax_rate1; $this->tax_name1 = $item->tax_name1; $this->tax_rate2 = $item->tax_rate2; @@ -387,7 +386,6 @@ class BaseRule implements RuleInterface $this->tax_rate3 = $item->tax_rate3; $this->tax_name3 = $item->tax_name3; - nlog($item); return $this; } diff --git a/app/DataMapper/Tax/DE/Rule.php b/app/DataMapper/Tax/DE/Rule.php index 3de96b14ac5f..726043cf5aa3 100644 --- a/app/DataMapper/Tax/DE/Rule.php +++ b/app/DataMapper/Tax/DE/Rule.php @@ -207,6 +207,14 @@ class Rule extends BaseRule implements RuleInterface */ public function override($item): self { + + $this->tax_rate1 = $item->tax_rate1; + $this->tax_name1 = $item->tax_name1; + $this->tax_rate2 = $item->tax_rate2; + $this->tax_name2 = $item->tax_name2; + $this->tax_rate3 = $item->tax_rate3; + $this->tax_name3 = $item->tax_name3; + return $this; } From 93c6de7747baf3a266522e047791d50ca7b35797 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 28 Jun 2024 12:48:36 +1000 Subject: [PATCH 05/16] Updates for paypal text --- composer.lock | 46 +++++++++---------- .../ninja2020/gateways/paypal/pay.blade.php | 2 +- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/composer.lock b/composer.lock index 4ff8320f9507..3a62ab2f9a94 100644 --- a/composer.lock +++ b/composer.lock @@ -535,16 +535,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.315.0", + "version": "3.315.1", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "a7f6026f00771025c32548dac321541face0dedc" + "reference": "13871330833e167d098240dab74b8b069b9b07e3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/a7f6026f00771025c32548dac321541face0dedc", - "reference": "a7f6026f00771025c32548dac321541face0dedc", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/13871330833e167d098240dab74b8b069b9b07e3", + "reference": "13871330833e167d098240dab74b8b069b9b07e3", "shasum": "" }, "require": { @@ -624,9 +624,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.315.0" + "source": "https://github.com/aws/aws-sdk-php/tree/3.315.1" }, - "time": "2024-06-26T18:08:22+00:00" + "time": "2024-06-27T18:03:53+00:00" }, { "name": "bacon/bacon-qr-code", @@ -4609,16 +4609,16 @@ }, { "name": "laravel/framework", - "version": "v11.12.0", + "version": "v11.13.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "9a6d9cea83cfa6b9e8eda05c89741d0411d8ebe8" + "reference": "92deaa4f037ff100e36809443811301819a8cf84" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/9a6d9cea83cfa6b9e8eda05c89741d0411d8ebe8", - "reference": "9a6d9cea83cfa6b9e8eda05c89741d0411d8ebe8", + "url": "https://api.github.com/repos/laravel/framework/zipball/92deaa4f037ff100e36809443811301819a8cf84", + "reference": "92deaa4f037ff100e36809443811301819a8cf84", "shasum": "" }, "require": { @@ -4810,7 +4810,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2024-06-25T19:33:56+00:00" + "time": "2024-06-27T09:04:50+00:00" }, { "name": "laravel/pint", @@ -11010,16 +11010,16 @@ }, { "name": "sprain/swiss-qr-bill", - "version": "v4.12.1", + "version": "v4.13", "source": { "type": "git", "url": "https://github.com/sprain/php-swiss-qr-bill.git", - "reference": "3728cd1366ac631a0587c0997a4878c37923e55b" + "reference": "5490e9139c4050d18533440cd9ff51a64955c035" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sprain/php-swiss-qr-bill/zipball/3728cd1366ac631a0587c0997a4878c37923e55b", - "reference": "3728cd1366ac631a0587c0997a4878c37923e55b", + "url": "https://api.github.com/repos/sprain/php-swiss-qr-bill/zipball/5490e9139c4050d18533440cd9ff51a64955c035", + "reference": "5490e9139c4050d18533440cd9ff51a64955c035", "shasum": "" }, "require": { @@ -11067,7 +11067,7 @@ "description": "A PHP library to create Swiss QR bills", "support": { "issues": "https://github.com/sprain/php-swiss-qr-bill/issues", - "source": "https://github.com/sprain/php-swiss-qr-bill/tree/v4.12.1" + "source": "https://github.com/sprain/php-swiss-qr-bill/tree/v4.13" }, "funding": [ { @@ -11075,7 +11075,7 @@ "type": "github" } ], - "time": "2024-05-16T07:19:59+00:00" + "time": "2024-06-27T11:17:56+00:00" }, { "name": "square/square", @@ -19006,16 +19006,16 @@ }, { "name": "spatie/error-solutions", - "version": "1.0.2", + "version": "1.0.3", "source": { "type": "git", "url": "https://github.com/spatie/error-solutions.git", - "reference": "9782ba6e25cb026cc653619e01ca695d428b3f03" + "reference": "55ea4117e0fde89d520883734ab9b71064c48876" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/error-solutions/zipball/9782ba6e25cb026cc653619e01ca695d428b3f03", - "reference": "9782ba6e25cb026cc653619e01ca695d428b3f03", + "url": "https://api.github.com/repos/spatie/error-solutions/zipball/55ea4117e0fde89d520883734ab9b71064c48876", + "reference": "55ea4117e0fde89d520883734ab9b71064c48876", "shasum": "" }, "require": { @@ -19068,7 +19068,7 @@ ], "support": { "issues": "https://github.com/spatie/error-solutions/issues", - "source": "https://github.com/spatie/error-solutions/tree/1.0.2" + "source": "https://github.com/spatie/error-solutions/tree/1.0.3" }, "funding": [ { @@ -19076,7 +19076,7 @@ "type": "github" } ], - "time": "2024-06-26T13:09:17+00:00" + "time": "2024-06-27T12:22:48+00:00" }, { "name": "spatie/flare-client-php", diff --git a/resources/views/portal/ninja2020/gateways/paypal/pay.blade.php b/resources/views/portal/ninja2020/gateways/paypal/pay.blade.php index 86eba7ccf830..29137b17a426 100644 --- a/resources/views/portal/ninja2020/gateways/paypal/pay.blade.php +++ b/resources/views/portal/ninja2020/gateways/paypal/pay.blade.php @@ -1,4 +1,4 @@ -@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.payment_type_credit_card'), 'card_title' => '']) +@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.paypal'), 'card_title' => '']) @section('gateway_head') From 028eb24fd98beb82b06c34c44356136583ecda6b Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 28 Jun 2024 15:16:08 +1000 Subject: [PATCH 06/16] Static analysis --- app/Export/CSV/CreditExport.php | 2 +- app/Export/CSV/ExpenseExport.php | 2 +- app/Export/CSV/InvoiceExport.php | 5 +- app/Export/CSV/InvoiceItemExport.php | 4 +- app/Export/CSV/PurchaseOrderExport.php | 5 +- app/Http/Controllers/ClientController.php | 2 +- .../ContactHashLoginController.php | 5 +- .../Controllers/MailgunWebhookController.php | 1 - .../Reports/ReportExportController.php | 21 ++--- .../Reports/ReportPreviewController.php | 7 +- app/Http/Controllers/SelfUpdateController.php | 32 ++++---- app/Http/Controllers/TwilioController.php | 2 +- .../Requests/Client/UpdateClientRequest.php | 2 +- .../Email/ClientEmailHistoryRequest.php | 1 - .../Email/EntityEmailHistoryRequest.php | 1 - .../UpdateRecurringInvoiceRequest.php | 2 +- .../Requests/Report/GenericReportRequest.php | 1 - app/Http/Requests/User/UpdateUserRequest.php | 2 +- .../User/HasValidPhoneNumber.php | 2 +- app/Models/Task.php | 2 +- .../Admin/EntityViewedNotification.php | 22 ++--- app/PaymentDrivers/BaseDriver.php | 4 +- app/PaymentDrivers/CheckoutCom/Webhook.php | 2 +- app/PaymentDrivers/Eway/CreditCard.php | 4 +- app/PaymentDrivers/GoCardless/ACH.php | 2 +- app/PaymentDrivers/MolliePaymentDriver.php | 2 +- app/PaymentDrivers/StripePaymentDriver.php | 2 +- .../EDocument/Imports/ZugferdEDocument.php | 11 ++- .../EDocument/Standards/FatturaPA.php | 2 +- app/Services/Email/AdminEmail.php | 2 +- app/Services/Payment/RefundPayment.php | 3 - app/Services/Pdf/PdfBuilder.php | 2 +- app/Services/Pdf/PdfMock.php | 2 +- app/Services/PdfMaker/Design.php | 4 +- .../Designs/Utilities/DesignHelpers.php | 6 +- app/Services/PdfMaker/PdfMaker.php | 10 --- app/Services/PdfMaker/PdfMakerUtilities.php | 2 +- .../PurchaseOrder/CreateInvitations.php | 6 +- app/Services/PurchaseOrder/MarkSent.php | 12 +-- app/Services/Quote/MarkApproved.php | 40 --------- app/Services/Quote/UpdateReminder.php | 68 +++++++-------- app/Services/Recurring/UpdatePrice.php | 2 +- app/Services/Report/ProfitLoss.php | 82 +++++++++---------- .../Scheduler/EmailStatementService.php | 5 -- .../Subscription/SubscriptionCalculator.php | 2 +- .../Subscription/SubscriptionService.php | 4 +- app/Services/Template/TemplateService.php | 1 + phpstan.neon | 8 +- 48 files changed, 176 insertions(+), 237 deletions(-) delete mode 100644 app/Services/Quote/MarkApproved.php diff --git a/app/Export/CSV/CreditExport.php b/app/Export/CSV/CreditExport.php index 1295d8ec2b6d..5f1e8b56d19d 100644 --- a/app/Export/CSV/CreditExport.php +++ b/app/Export/CSV/CreditExport.php @@ -241,7 +241,7 @@ class CreditExport extends BaseExport } if (in_array('credit.user_id', $this->input['report_keys'])) { - $entity['credit.user_id'] = $credit->user ? $credit->user->present()->name() : ''; + $entity['credit.user_id'] = $credit->user ? $credit->user->present()->name() : ''; //@phpstan-ignore-line } return $entity; diff --git a/app/Export/CSV/ExpenseExport.php b/app/Export/CSV/ExpenseExport.php index dfcc554b8891..76f49d997b5b 100644 --- a/app/Export/CSV/ExpenseExport.php +++ b/app/Export/CSV/ExpenseExport.php @@ -85,7 +85,7 @@ class ExpenseExport extends BaseExport ->where('company_id', $this->company->id); - if(!$this->input['include_deleted'] ?? false) { + if(!$this->input['include_deleted'] ?? false) { // @phpstan-ignore-line $query->where('is_deleted', 0); } diff --git a/app/Export/CSV/InvoiceExport.php b/app/Export/CSV/InvoiceExport.php index b4e00d42b8b7..d0839d03d6fb 100644 --- a/app/Export/CSV/InvoiceExport.php +++ b/app/Export/CSV/InvoiceExport.php @@ -63,7 +63,7 @@ class InvoiceExport extends BaseExport ->where('company_id', $this->company->id); - if(!$this->input['include_deleted'] ?? false) { + if(!$this->input['include_deleted'] ?? false) {// @phpstan-ignore-line $query->where('is_deleted', 0); } @@ -166,7 +166,8 @@ class InvoiceExport extends BaseExport } if (in_array('invoice.user_id', $this->input['report_keys'])) { - $entity['invoice.user_id'] = $invoice->user ? $invoice->user->present()->name() : ''; + $entity['invoice.user_id'] = $invoice->user ? $invoice->user->present()->name() : ''; // @phpstan-ignore-line + } return $entity; diff --git a/app/Export/CSV/InvoiceItemExport.php b/app/Export/CSV/InvoiceItemExport.php index f6d5d814a763..0e5efcac0b6d 100644 --- a/app/Export/CSV/InvoiceItemExport.php +++ b/app/Export/CSV/InvoiceItemExport.php @@ -75,7 +75,7 @@ class InvoiceItemExport extends BaseExport }) ->where('company_id', $this->company->id); - if(!$this->input['include_deleted'] ?? false) { + if(!$this->input['include_deleted'] ?? false) {// @phpstan-ignore-line $query->where('is_deleted', 0); } @@ -258,7 +258,7 @@ class InvoiceItemExport extends BaseExport } if (in_array('invoice.user_id', $this->input['report_keys'])) { - $entity['invoice.user_id'] = $invoice->user ? $invoice->user->present()->name() : ''; + $entity['invoice.user_id'] = $invoice->user ? $invoice->user->present()->name() : '';// @phpstan-ignore-line } return $entity; diff --git a/app/Export/CSV/PurchaseOrderExport.php b/app/Export/CSV/PurchaseOrderExport.php index 2f83844a4186..e1091dd6672f 100644 --- a/app/Export/CSV/PurchaseOrderExport.php +++ b/app/Export/CSV/PurchaseOrderExport.php @@ -63,7 +63,7 @@ class PurchaseOrderExport extends BaseExport }) ->where('company_id', $this->company->id); - if(!$this->input['include_deleted'] ?? false) { + if(!$this->input['include_deleted'] ?? false) { // @phpstan-ignore-line $query->where('is_deleted', 0); } @@ -167,7 +167,8 @@ class PurchaseOrderExport extends BaseExport } if (in_array('purchase_order.user_id', $this->input['report_keys'])) { - $entity['purchase_order.user_id'] = $purchase_order->user ? $purchase_order->user->present()->name() : ''; + $entity['purchase_order.user_id'] = $purchase_order->user ? $purchase_order->user->present()->name() : ''; // @phpstan-ignore-line + } if (in_array('purchase_order.assigned_user_id', $this->input['report_keys'])) { diff --git a/app/Http/Controllers/ClientController.php b/app/Http/Controllers/ClientController.php index 76fe6c661abd..2401fab5b381 100644 --- a/app/Http/Controllers/ClientController.php +++ b/app/Http/Controllers/ClientController.php @@ -429,7 +429,7 @@ class ClientController extends BaseController /** @var ?\Postmark\Models\DynamicResponseModel $response */ $response = $postmark->activateBounce((int)$bounce_id); - if($response && $response?->Message == 'OK' && !$response->Bounce->Inactive && $response->Bounce->Email) { + if($response && $response?->Message == 'OK' && !$response->Bounce->Inactive && $response->Bounce->Email) { // @phpstan-ignore-line $email = $response->Bounce->Email; //remove email from quarantine. //@TODO diff --git a/app/Http/Controllers/ClientPortal/ContactHashLoginController.php b/app/Http/Controllers/ClientPortal/ContactHashLoginController.php index d03e4cba3ab5..70c7d3404923 100644 --- a/app/Http/Controllers/ClientPortal/ContactHashLoginController.php +++ b/app/Http/Controllers/ClientPortal/ContactHashLoginController.php @@ -57,8 +57,9 @@ class ContactHashLoginController extends Controller return render('generic.error', [ 'title' => session()->get('title'), 'notification' => session()->get('notification'), - 'account' => auth()->guard('contact')?->user()?->user?->account, - 'company' => auth()->guard('contact')?->user()?->user?->company + 'account' => auth()->guard('contact')?->user()?->user?->account,// @phpstan-ignore-line + 'company' => auth()->guard('contact')?->user()?->user?->company // @phpstan-ignore-line + ]); } diff --git a/app/Http/Controllers/MailgunWebhookController.php b/app/Http/Controllers/MailgunWebhookController.php index 8a382836597e..0585ebc02d97 100644 --- a/app/Http/Controllers/MailgunWebhookController.php +++ b/app/Http/Controllers/MailgunWebhookController.php @@ -20,7 +20,6 @@ use Illuminate\Http\Request; */ class MailgunWebhookController extends BaseController { - private $invitation; public function __construct() { diff --git a/app/Http/Controllers/Reports/ReportExportController.php b/app/Http/Controllers/Reports/ReportExportController.php index 67a73e9b210a..ae3752a9e3e4 100644 --- a/app/Http/Controllers/Reports/ReportExportController.php +++ b/app/Http/Controllers/Reports/ReportExportController.php @@ -36,21 +36,16 @@ class ReportExportController extends BaseController return response()->json(['message' => 'Still working.....'], 409); } - if($report) { + Cache::forget($hash); - Cache::forget($hash); - - $headers = [ - 'Content-Disposition' => 'attachment', - 'Content-Type' => 'text/csv', - ]; - - return response()->streamDownload(function () use ($report) { - echo $report; - }, $this->filename, $headers); - - } + $headers = [ + 'Content-Disposition' => 'attachment', + 'Content-Type' => 'text/csv', + ]; + return response()->streamDownload(function () use ($report) { + echo $report; + }, $this->filename, $headers); } } diff --git a/app/Http/Controllers/Reports/ReportPreviewController.php b/app/Http/Controllers/Reports/ReportPreviewController.php index 1f33ecd413ef..2eb4eea34514 100644 --- a/app/Http/Controllers/Reports/ReportPreviewController.php +++ b/app/Http/Controllers/Reports/ReportPreviewController.php @@ -34,12 +34,9 @@ class ReportPreviewController extends BaseController return response()->json(['message' => 'Still working.....'], 409); } - if($report) { + Cache::forget($hash); - Cache::forget($hash); - - return response()->json($report, 200); - } + return response()->json($report, 200); } diff --git a/app/Http/Controllers/SelfUpdateController.php b/app/Http/Controllers/SelfUpdateController.php index 77c1e07bf2c7..d25b056a0e1a 100644 --- a/app/Http/Controllers/SelfUpdateController.php +++ b/app/Http/Controllers/SelfUpdateController.php @@ -122,26 +122,26 @@ class SelfUpdateController extends BaseController return response()->json(['message' => 'Update completed'], 200); } - private function runModelChecks() - { - Company::query() - ->cursor() - ->each(function ($company) { + // private function runModelChecks() + // { + // Company::query() + // ->cursor() + // ->each(function ($company) { - $settings = $company->settings; + // $settings = $company->settings; - if(property_exists($settings->pdf_variables, 'purchase_order_details')) { - return; - } + // if(property_exists($settings->pdf_variables, 'purchase_order_details')) { + // return; + // } - $pdf_variables = $settings->pdf_variables; - $pdf_variables->purchase_order_details = []; - $settings->pdf_variables = $pdf_variables; - $company->settings = $settings; - $company->save(); + // $pdf_variables = $settings->pdf_variables; + // $pdf_variables->purchase_order_details = []; + // $settings->pdf_variables = $pdf_variables; + // $company->settings = $settings; + // $company->save(); - }); - } + // }); + // } private function clearCacheDir() { diff --git a/app/Http/Controllers/TwilioController.php b/app/Http/Controllers/TwilioController.php index 126ce23ea0fe..f7366d0b8f65 100644 --- a/app/Http/Controllers/TwilioController.php +++ b/app/Http/Controllers/TwilioController.php @@ -164,7 +164,7 @@ class TwilioController extends BaseController return response()->json(['message' => 'Please update your first and/or last name in the User Details before verifying your number.'], 400); } - if (!$user->phone || $user->phone == '') { + if (!$user->phone || empty($user->phone)) { return response()->json(['message' => 'User found, but no valid phone number on file, please contact support.'], 400); } diff --git a/app/Http/Requests/Client/UpdateClientRequest.php b/app/Http/Requests/Client/UpdateClientRequest.php index 8933954de922..81da5af205f0 100644 --- a/app/Http/Requests/Client/UpdateClientRequest.php +++ b/app/Http/Requests/Client/UpdateClientRequest.php @@ -170,7 +170,7 @@ class UpdateClientRequest extends Request * down to the free plan setting properties which * are saveable * - * @param \stdClass $settings + * @param mixed $settings * @return \stdClass $settings */ private function filterSaveableSettings($settings) diff --git a/app/Http/Requests/Email/ClientEmailHistoryRequest.php b/app/Http/Requests/Email/ClientEmailHistoryRequest.php index 50dd772e39d6..2f0efc233f1d 100644 --- a/app/Http/Requests/Email/ClientEmailHistoryRequest.php +++ b/app/Http/Requests/Email/ClientEmailHistoryRequest.php @@ -18,7 +18,6 @@ class ClientEmailHistoryRequest extends Request { use MakesHash; - private string $error_message = ''; /** * Determine if the user is authorized to make this request. * diff --git a/app/Http/Requests/Email/EntityEmailHistoryRequest.php b/app/Http/Requests/Email/EntityEmailHistoryRequest.php index 180496e979be..5f08442a88b3 100644 --- a/app/Http/Requests/Email/EntityEmailHistoryRequest.php +++ b/app/Http/Requests/Email/EntityEmailHistoryRequest.php @@ -20,7 +20,6 @@ class EntityEmailHistoryRequest extends Request { use MakesHash; - private string $error_message = ''; private string $entity_plural = ''; /** * Determine if the user is authorized to make this request. diff --git a/app/Http/Requests/RecurringInvoice/UpdateRecurringInvoiceRequest.php b/app/Http/Requests/RecurringInvoice/UpdateRecurringInvoiceRequest.php index db70ca922927..a89baa8d2cf9 100644 --- a/app/Http/Requests/RecurringInvoice/UpdateRecurringInvoiceRequest.php +++ b/app/Http/Requests/RecurringInvoice/UpdateRecurringInvoiceRequest.php @@ -126,7 +126,7 @@ class UpdateRecurringInvoiceRequest extends Request } if (isset($input['line_items'])) { - $input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : []; + $input['line_items'] = $this->cleanItems($input['line_items']); $input['amount'] = $this->entityTotalAmount($input['line_items']); } diff --git a/app/Http/Requests/Report/GenericReportRequest.php b/app/Http/Requests/Report/GenericReportRequest.php index c9d467423fca..085de868efb3 100644 --- a/app/Http/Requests/Report/GenericReportRequest.php +++ b/app/Http/Requests/Report/GenericReportRequest.php @@ -17,7 +17,6 @@ use Illuminate\Auth\Access\AuthorizationException; class GenericReportRequest extends Request { - private string $error_message = ''; /** * Determine if the user is authorized to make this request. diff --git a/app/Http/Requests/User/UpdateUserRequest.php b/app/Http/Requests/User/UpdateUserRequest.php index 6b5bbf84a859..c95765e9c4ac 100644 --- a/app/Http/Requests/User/UpdateUserRequest.php +++ b/app/Http/Requests/User/UpdateUserRequest.php @@ -77,7 +77,7 @@ class UpdateUserRequest extends Request unset($input['oauth_user_token']); } - if(isset($input['password']) && strlen($input['password'] ?? '') > 1) + if(isset($input['password']) && is_string($input['password'])) { $input['password'] = trim($input['password']); } diff --git a/app/Http/ValidationRules/User/HasValidPhoneNumber.php b/app/Http/ValidationRules/User/HasValidPhoneNumber.php index 4d179b4ad0ee..48cde515fc81 100644 --- a/app/Http/ValidationRules/User/HasValidPhoneNumber.php +++ b/app/Http/ValidationRules/User/HasValidPhoneNumber.php @@ -51,7 +51,7 @@ class HasValidPhoneNumber implements Rule $twilio = new \Twilio\Rest\Client($sid, $token); - $country = auth()->user()->account?->companies()?->first()?->country(); + $country = auth()->user()->account?->companies()?->first()?->country(); //@phpstan-ignore-line if (!$country || strlen(auth()->user()->phone) < 2) { return true; diff --git a/app/Models/Task.php b/app/Models/Task.php index 5106f86bdd31..8479ec26f6f6 100644 --- a/app/Models/Task.php +++ b/app/Models/Task.php @@ -186,7 +186,7 @@ class Task extends BaseModel } if($this->status) { - return '
' . $this->status?->name ?? ''; + return '
' . $this->status?->name ?? ''; //@phpstan-ignore-line } return ''; diff --git a/app/Notifications/Admin/EntityViewedNotification.php b/app/Notifications/Admin/EntityViewedNotification.php index fc70cf7d9e5d..3975a8516ff2 100644 --- a/app/Notifications/Admin/EntityViewedNotification.php +++ b/app/Notifications/Admin/EntityViewedNotification.php @@ -136,16 +136,16 @@ class EntityViewedNotification extends Notification // return $data; // } - private function buildSubject() - { - $subject = ctrans( - "texts.notification_{$this->entity_name}_viewed_subject", - [ - 'client' => $this->contact->present()->name(), - $this->entity_name => $this->entity->number, - ] - ); + // private function buildSubject() + // { + // $subject = ctrans( + // "texts.notification_{$this->entity_name}_viewed_subject", + // [ + // 'client' => $this->contact->present()->name(), + // $this->entity_name => $this->entity->number, + // ] + // ); - return $subject; - } + // return $subject; + // } } diff --git a/app/PaymentDrivers/BaseDriver.php b/app/PaymentDrivers/BaseDriver.php index 86163415ad4e..e3720e0a3db7 100644 --- a/app/PaymentDrivers/BaseDriver.php +++ b/app/PaymentDrivers/BaseDriver.php @@ -559,7 +559,7 @@ class BaseDriver extends AbstractPaymentDriver $error = 'Payment Aborted'; } - if (! is_null($this->payment_hash)) { + if (! is_null($this->payment_hash)) { //@phpstan-ignore-line $this->unWindGatewayFees($this->payment_hash); } @@ -830,7 +830,7 @@ class BaseDriver extends AbstractPaymentDriver } $invoices_string = \implode(', ', collect($this->payment_hash->invoices())->pluck('invoice_number')->toArray()) ?: null; - $amount = Number::formatMoney($this->payment_hash?->amount_with_fee() ?? 0, $this->client); + $amount = Number::formatMoney($this->payment_hash?->amount_with_fee() ?? 0, $this->client); // @phpstan-ignore-line if($abbreviated && $invoices_string) { return $invoices_string; diff --git a/app/PaymentDrivers/CheckoutCom/Webhook.php b/app/PaymentDrivers/CheckoutCom/Webhook.php index 62cbc3039f15..14ac34025633 100644 --- a/app/PaymentDrivers/CheckoutCom/Webhook.php +++ b/app/PaymentDrivers/CheckoutCom/Webhook.php @@ -40,7 +40,7 @@ class Webhook $error_details = $e->error_details; nlog($error_details); - $http_status_code = isset($e->http_metadata) ? $e->http_metadata->getStatusCode() : null; + $http_status_code = isset($e->http_metadata) ? $e->http_metadata->getStatusCode() : null; //@phpstan-ignore-line } catch (CheckoutAuthorizationException $e) { // Bad Invalid authorization } diff --git a/app/PaymentDrivers/Eway/CreditCard.php b/app/PaymentDrivers/Eway/CreditCard.php index 8bd3e1602001..e7f97124566d 100644 --- a/app/PaymentDrivers/Eway/CreditCard.php +++ b/app/PaymentDrivers/Eway/CreditCard.php @@ -78,7 +78,7 @@ class CreditCard $this->logResponse($response); - throw new PaymentFailed($response_status['message'] ?? 'Unknown response from gateway, please contact you merchant.', 400); + throw new PaymentFailed($response_status['message'] ?? 'Unknown response from gateway, please contact you merchant.', 400); //@phpstan-ignore-line } //success @@ -135,7 +135,7 @@ class CreditCard $invoice_numbers = ''; if ($this->eway_driver->payment_hash->data) { - $invoice_numbers = collect($this->eway_driver->payment_hash->data->invoices)->pluck('invoice_number')->implode(','); + $invoice_numbers = collect($this->eway_driver->payment_hash->data->invoices)->pluck('invoice_number')->implode(','); //@phpstan-ignore-line } $amount = array_sum(array_column($this->eway_driver->payment_hash->invoices(), 'amount')) + $this->eway_driver->payment_hash->fee_total; diff --git a/app/PaymentDrivers/GoCardless/ACH.php b/app/PaymentDrivers/GoCardless/ACH.php index 694cac15b9af..e52e8ce54101 100644 --- a/app/PaymentDrivers/GoCardless/ACH.php +++ b/app/PaymentDrivers/GoCardless/ACH.php @@ -173,7 +173,7 @@ class ACH implements MethodInterface $description = "Amount {$request->amount} from client {$this->go_cardless->client->present()->name()}"; } - $amount = $this->go_cardless->convertToGoCardlessAmount($this->go_cardless->payment_hash?->amount_with_fee(), $this->go_cardless->client->currency()->precision); + $amount = $this->go_cardless->convertToGoCardlessAmount($this->go_cardless->payment_hash?->amount_with_fee(), $this->go_cardless->client->currency()->precision); //@phpstan-ignore-line try { $payment = $this->go_cardless->gateway->payments()->create([ diff --git a/app/PaymentDrivers/MolliePaymentDriver.php b/app/PaymentDrivers/MolliePaymentDriver.php index 0f02d33e12f3..d2fd97d53fec 100644 --- a/app/PaymentDrivers/MolliePaymentDriver.php +++ b/app/PaymentDrivers/MolliePaymentDriver.php @@ -156,7 +156,7 @@ class MolliePaymentDriver extends BaseDriver return [ 'transaction_reference' => $refund->id, 'transaction_response' => json_encode($refund), - 'success' => $refund->status === 'refunded' ? true : false, + 'success' => $refund->status === 'refunded' ? true : false, //@phpstan-ignore-line 'description' => $refund->description, 'code' => 200, ]; diff --git a/app/PaymentDrivers/StripePaymentDriver.php b/app/PaymentDrivers/StripePaymentDriver.php index cb3b0584d4e6..69920e31e6b5 100644 --- a/app/PaymentDrivers/StripePaymentDriver.php +++ b/app/PaymentDrivers/StripePaymentDriver.php @@ -489,7 +489,7 @@ class StripePaymentDriver extends BaseDriver { $customer = Customer::retrieve($customer_id, $this->stripe_connect_auth); - return $customer ?? null; + return $customer ?? null; // @phpstan-ignore-line } /** diff --git a/app/Services/EDocument/Imports/ZugferdEDocument.php b/app/Services/EDocument/Imports/ZugferdEDocument.php index 49fb780ffab3..f8ec7a6f7dd9 100644 --- a/app/Services/EDocument/Imports/ZugferdEDocument.php +++ b/app/Services/EDocument/Imports/ZugferdEDocument.php @@ -46,8 +46,9 @@ class ZugferdEDocument extends AbstractService { $this->document->getDocumentInformation($documentno, $documenttypecode, $documentdate, $invoiceCurrency, $taxCurrency, $documentname, $documentlanguage, $effectiveSpecifiedPeriod); $this->document->getDocumentSummation($grandTotalAmount, $duePayableAmount, $lineTotalAmount, $chargeTotalAmount, $allowanceTotalAmount, $taxBasisTotalAmount, $taxTotalAmount, $roundingAmount, $totalPrepaidAmount); - $expense = Expense::where('amount', $grandTotalAmount)->where("transaction_reference", $documentno)->whereDate("date", $documentdate)->first(); - if (empty($expense)) { + /** @var \App\Models\Expense $expense */ + $expense = Expense::where("company_id", $user->company()->id)->where('amount', $grandTotalAmount)->where("transaction_reference", $documentno)->whereDate("date", $documentdate)->first(); + if (!$expense) { // The document does not exist as an expense // Handle accordingly $visualizer = new ZugferdVisualizer($this->document); @@ -59,13 +60,11 @@ class ZugferdEDocument extends AbstractService { $expense = ExpenseFactory::create($user->company()->id, $user->id); $expense->date = $documentdate; - $expense->user_id = $user->id; - $expense->company_id = $user->company->id; $expense->public_notes = $documentno; - $expense->currency_id = Currency::whereCode($invoiceCurrency)->first()->id; + $expense->currency_id = Currency::whereCode($invoiceCurrency)->first()->id ?? $user->company()->settings->currency_id; $expense->save(); - $origin_file = TempFile::UploadedFileFromRaw($this->tempdocument, $this->documentname, "application/xml"); + $origin_file = TempFile::UploadedFileFromRaw($this->tempdocument, $this->documentname, "application/xml"); (new UploadFile($origin_file, UploadFile::DOCUMENT, $user, $expense->company, $expense, null, false))->handle(); $uploaded_file = TempFile::UploadedFileFromRaw($visualizer->renderPdf(), $documentno."_visualiser.pdf", "application/pdf"); (new UploadFile($uploaded_file, UploadFile::DOCUMENT, $user, $expense->company, $expense, null, false))->handle(); diff --git a/app/Services/EDocument/Standards/FatturaPA.php b/app/Services/EDocument/Standards/FatturaPA.php index 626c67d26dc1..455083033ce8 100644 --- a/app/Services/EDocument/Standards/FatturaPA.php +++ b/app/Services/EDocument/Standards/FatturaPA.php @@ -44,7 +44,7 @@ use CleverIt\UBL\Invoice\FatturaPA\common\FatturaElettronicaHeader; */ class FatturaPA extends AbstractService { - private $xml; + // private $xml; //urn:cen.eu:en16931:2017#compliant#urn:fatturapa.gov.it:CIUS-IT:2.0.0 //UFF001 diff --git a/app/Services/Email/AdminEmail.php b/app/Services/Email/AdminEmail.php index 4dc1e1188152..1a1a76513b8b 100644 --- a/app/Services/Email/AdminEmail.php +++ b/app/Services/Email/AdminEmail.php @@ -205,7 +205,7 @@ class AdminEmail implements ShouldQueue $this->entityEmailFailed($message); /* Don't send postmark failures to Sentry */ - if (Ninja::isHosted() && (!$e instanceof ClientException)) { + if (Ninja::isHosted() && (!$e instanceof ClientException)) { //@phpstan-ignore-line app('sentry')->captureException($e); } } diff --git a/app/Services/Payment/RefundPayment.php b/app/Services/Payment/RefundPayment.php index 144abff2068c..a17baa67051e 100644 --- a/app/Services/Payment/RefundPayment.php +++ b/app/Services/Payment/RefundPayment.php @@ -33,9 +33,6 @@ class RefundPayment public function __construct(public Payment $payment, public array $refund_data) { - $this->gateway_refund_status = false; - - $this->activity_repository = new ActivityRepository(); } public function run() diff --git a/app/Services/Pdf/PdfBuilder.php b/app/Services/Pdf/PdfBuilder.php index 5af214dbd30a..fe27b6979af3 100644 --- a/app/Services/Pdf/PdfBuilder.php +++ b/app/Services/Pdf/PdfBuilder.php @@ -1665,7 +1665,7 @@ class PdfBuilder if ($child['element'] !== 'script') { if ($this->service->company->markdown_enabled && array_key_exists('content', $child)) { $child['content'] = str_replace('
', "\r", ($child['content'] ?? '')); - $child['content'] = $this->commonmark->convert($child['content'] ?? ''); + $child['content'] = $this->commonmark->convert($child['content'] ?? ''); //@phpstan-ignore-line } } diff --git a/app/Services/Pdf/PdfMock.php b/app/Services/Pdf/PdfMock.php index 7bc40ec22006..5ef5350e9da2 100644 --- a/app/Services/Pdf/PdfMock.php +++ b/app/Services/Pdf/PdfMock.php @@ -469,7 +469,7 @@ class PdfMock '$country_2' => 'AF', '$firstName' => 'Benedict', '$user.name' => 'Derrick Monahan DDS Erna Wunsch', - '$font_name' => isset($this->settings?->primary_font) ? $this->settings?->primary_font : 'Roboto', + '$font_name' => isset($this->settings?->primary_font) ? $this->settings?->primary_font : 'Roboto', //@phpstan-ignore-line '$auto_bill' => 'This invoice will automatically be billed to your credit card on file on the due date.', '$payments' => '', '$task.tax' => '', diff --git a/app/Services/PdfMaker/Design.php b/app/Services/PdfMaker/Design.php index d674e2c6b696..c9b5bfa94ca5 100644 --- a/app/Services/PdfMaker/Design.php +++ b/app/Services/PdfMaker/Design.php @@ -287,7 +287,7 @@ class Design extends BaseDesign { $elements = []; - if (!$this->client) { + if (!$this->client) {//@phpstan-ignore-line return $elements; } @@ -359,7 +359,7 @@ class Design extends BaseDesign $variables = $this->context['pdf_variables']['credit_details']; } - if ($this->vendor) { + if ($this->vendor) { //@phpstan-ignore-line $variables = $this->context['pdf_variables']['purchase_order_details']; } diff --git a/app/Services/PdfMaker/Designs/Utilities/DesignHelpers.php b/app/Services/PdfMaker/Designs/Utilities/DesignHelpers.php index 0ffdda3e9e17..7c00cfb1871e 100644 --- a/app/Services/PdfMaker/Designs/Utilities/DesignHelpers.php +++ b/app/Services/PdfMaker/Designs/Utilities/DesignHelpers.php @@ -64,9 +64,9 @@ trait DesignHelpers $this->document(); - $this->settings_object = $this->vendor ? $this->vendor->company : $this->client; + $this->settings_object = $this->vendor ? $this->vendor->company : $this->client; //@phpstan-ignore-line - $this->company = $this->vendor ? $this->vendor->company : $this->client->company; + $this->company = $this->vendor ? $this->vendor->company : $this->client->company; //@phpstan-ignore-line return $this; } @@ -387,7 +387,7 @@ trait DesignHelpers return ''; } - if ($this->client->company->custom_fields && ! property_exists($this->client->company->custom_fields, $field)) { + if ($this->client->company->custom_fields && ! property_exists($this->client->company->custom_fields, $field)) { //@phpstan-ignore-line return ''; } diff --git a/app/Services/PdfMaker/PdfMaker.php b/app/Services/PdfMaker/PdfMaker.php index 876500e13309..c251c3a1da43 100644 --- a/app/Services/PdfMaker/PdfMaker.php +++ b/app/Services/PdfMaker/PdfMaker.php @@ -27,16 +27,6 @@ class PdfMaker public $document; - private $xpath; - - private $filters = [ - ' '', - ' '', - ']]]]>]]>' => '', - ']]>' => '', - '' => '', - ]; - private $options; /** @var CommonMarkConverter */ diff --git a/app/Services/PdfMaker/PdfMakerUtilities.php b/app/Services/PdfMaker/PdfMakerUtilities.php index 281f576c0465..b317973a52c4 100644 --- a/app/Services/PdfMaker/PdfMakerUtilities.php +++ b/app/Services/PdfMaker/PdfMakerUtilities.php @@ -94,7 +94,7 @@ trait PdfMakerUtilities if ($child['element'] !== 'script') { if (array_key_exists('process_markdown', $this->data) && array_key_exists('content', $child) && $this->data['process_markdown']) { $child['content'] = str_replace('
', "\r", ($child['content'] ?? '')); - $child['content'] = $this->commonmark->convert($child['content'] ?? ''); + $child['content'] = $this->commonmark->convert($child['content'] ?? ''); //@phpstan-ignore-line } } diff --git a/app/Services/PurchaseOrder/CreateInvitations.php b/app/Services/PurchaseOrder/CreateInvitations.php index 12bdfc60cf01..9813f13ba6a2 100644 --- a/app/Services/PurchaseOrder/CreateInvitations.php +++ b/app/Services/PurchaseOrder/CreateInvitations.php @@ -41,7 +41,11 @@ class CreateInvitations extends AbstractService public function run() { - $contacts = $this->purchase_order?->vendor?->contacts()->get(); + + if(!$this->purchase_order->vendor) + return $this->purchase_order; + + $contacts = $this->purchase_order->vendor->contacts()->get(); if ($contacts->count() == 0) { $this->createBlankContact(); diff --git a/app/Services/PurchaseOrder/MarkSent.php b/app/Services/PurchaseOrder/MarkSent.php index c56b89317302..c357684be697 100644 --- a/app/Services/PurchaseOrder/MarkSent.php +++ b/app/Services/PurchaseOrder/MarkSent.php @@ -11,19 +11,15 @@ namespace App\Services\PurchaseOrder; -use App\Models\PurchaseOrder; +use App\Models\Vendor; use App\Models\Webhook; +use App\Models\PurchaseOrder; class MarkSent { - private $vendor; - - private $purchase_order; - - public function __construct($vendor, $purchase_order) + + public function __construct(public Vendor $vendor, public PurchaseOrder $purchase_order) { - $this->vendor = $vendor; - $this->purchase_order = $purchase_order; } public function run() diff --git a/app/Services/Quote/MarkApproved.php b/app/Services/Quote/MarkApproved.php deleted file mode 100644 index 0bb44115d929..000000000000 --- a/app/Services/Quote/MarkApproved.php +++ /dev/null @@ -1,40 +0,0 @@ -client = $client; - } - - public function run($quote) - { - /* Return immediately if status is not draft */ - if ($quote->status_id != Quote::STATUS_SENT) { - return $quote; - } - - $quote->service()->setStatus(Quote::STATUS_APPROVED)->applyNumber()->save(); - - event(new QuoteWasMarkedApproved($quote, $quote->company, Ninja::eventVars())); - - return $quote; - } -} diff --git a/app/Services/Quote/UpdateReminder.php b/app/Services/Quote/UpdateReminder.php index 9cf39da12871..e4af99b70594 100644 --- a/app/Services/Quote/UpdateReminder.php +++ b/app/Services/Quote/UpdateReminder.php @@ -171,39 +171,39 @@ class UpdateReminder extends AbstractService return $this->quote; } - private function addTimeInterval($date, $endless_reminder_frequency_id): ?Carbon - { - if (! $date) { - return null; - } + // private function addTimeInterval($date, $endless_reminder_frequency_id): ?Carbon + // { + // if (! $date) { + // return null; + // } - switch ($endless_reminder_frequency_id) { - case RecurringInvoice::FREQUENCY_DAILY: - return Carbon::parse($date)->addDay()->startOfDay(); - case RecurringInvoice::FREQUENCY_WEEKLY: - return Carbon::parse($date)->addWeek()->startOfDay(); - case RecurringInvoice::FREQUENCY_TWO_WEEKS: - return Carbon::parse($date)->addWeeks(2)->startOfDay(); - case RecurringInvoice::FREQUENCY_FOUR_WEEKS: - return Carbon::parse($date)->addWeeks(4)->startOfDay(); - case RecurringInvoice::FREQUENCY_MONTHLY: - return Carbon::parse($date)->addMonthNoOverflow()->startOfDay(); - case RecurringInvoice::FREQUENCY_TWO_MONTHS: - return Carbon::parse($date)->addMonthsNoOverflow(2)->startOfDay(); - case RecurringInvoice::FREQUENCY_THREE_MONTHS: - return Carbon::parse($date)->addMonthsNoOverflow(3)->startOfDay(); - case RecurringInvoice::FREQUENCY_FOUR_MONTHS: - return Carbon::parse($date)->addMonthsNoOverflow(4)->startOfDay(); - case RecurringInvoice::FREQUENCY_SIX_MONTHS: - return Carbon::parse($date)->addMonthsNoOverflow(6)->startOfDay(); - case RecurringInvoice::FREQUENCY_ANNUALLY: - return Carbon::parse($date)->addYear()->startOfDay(); - case RecurringInvoice::FREQUENCY_TWO_YEARS: - return Carbon::parse($date)->addYears(2)->startOfDay(); - case RecurringInvoice::FREQUENCY_THREE_YEARS: - return Carbon::parse($date)->addYears(3)->startOfDay(); - default: - return null; - } - } + // switch ($endless_reminder_frequency_id) { + // case RecurringInvoice::FREQUENCY_DAILY: + // return Carbon::parse($date)->addDay()->startOfDay(); + // case RecurringInvoice::FREQUENCY_WEEKLY: + // return Carbon::parse($date)->addWeek()->startOfDay(); + // case RecurringInvoice::FREQUENCY_TWO_WEEKS: + // return Carbon::parse($date)->addWeeks(2)->startOfDay(); + // case RecurringInvoice::FREQUENCY_FOUR_WEEKS: + // return Carbon::parse($date)->addWeeks(4)->startOfDay(); + // case RecurringInvoice::FREQUENCY_MONTHLY: + // return Carbon::parse($date)->addMonthNoOverflow()->startOfDay(); + // case RecurringInvoice::FREQUENCY_TWO_MONTHS: + // return Carbon::parse($date)->addMonthsNoOverflow(2)->startOfDay(); + // case RecurringInvoice::FREQUENCY_THREE_MONTHS: + // return Carbon::parse($date)->addMonthsNoOverflow(3)->startOfDay(); + // case RecurringInvoice::FREQUENCY_FOUR_MONTHS: + // return Carbon::parse($date)->addMonthsNoOverflow(4)->startOfDay(); + // case RecurringInvoice::FREQUENCY_SIX_MONTHS: + // return Carbon::parse($date)->addMonthsNoOverflow(6)->startOfDay(); + // case RecurringInvoice::FREQUENCY_ANNUALLY: + // return Carbon::parse($date)->addYear()->startOfDay(); + // case RecurringInvoice::FREQUENCY_TWO_YEARS: + // return Carbon::parse($date)->addYears(2)->startOfDay(); + // case RecurringInvoice::FREQUENCY_THREE_YEARS: + // return Carbon::parse($date)->addYears(3)->startOfDay(); + // default: + // return null; + // } + // } } diff --git a/app/Services/Recurring/UpdatePrice.php b/app/Services/Recurring/UpdatePrice.php index 6b390eb71297..ddca95bd190c 100644 --- a/app/Services/Recurring/UpdatePrice.php +++ b/app/Services/Recurring/UpdatePrice.php @@ -33,7 +33,7 @@ class UpdatePrice extends AbstractService ->where('is_deleted', 0) ->first(); - if ($product) { + if ($product) { //@phpstan-ignore-line $line_items[$key]->cost = floatval($product->price); } } diff --git a/app/Services/Report/ProfitLoss.php b/app/Services/Report/ProfitLoss.php index e3b9fc4e1db6..09d392435a12 100644 --- a/app/Services/Report/ProfitLoss.php +++ b/app/Services/Report/ProfitLoss.php @@ -183,17 +183,17 @@ class ProfitLoss return $this; } - private function getForeignIncome(): array - { - return $this->foreign_income; - } + // private function getForeignIncome(): array + // { + // return $this->foreign_income; + // } - private function filterPaymentIncome() - { - $payments = $this->paymentIncome(); + // private function filterPaymentIncome() + // { + // $payments = $this->paymentIncome(); - return $this; - } + // return $this; + // } /* //returns an array of objects @@ -427,26 +427,26 @@ class ProfitLoss +"payments_converted": "12260.870000000000", +"currency_id": 1, */ - private function paymentIncome() - { - return \DB::select(' - SELECT - SUM(coalesce(payments.amount - payments.refunded,0)) as payments, - SUM(coalesce(payments.amount - payments.refunded,0)) * IFNULL(payments.exchange_rate ,1) as payments_converted, - payments.currency_id as currency_id - FROM clients - INNER JOIN - payments ON - clients.id=payments.client_id - WHERE payments.status_id IN (1,4,5,6) - AND clients.is_deleted = false - AND payments.is_deleted = false - AND payments.company_id = :company_id - AND (payments.date BETWEEN :start_date AND :end_date) - GROUP BY currency_id - ORDER BY currency_id; - ', ['company_id' => $this->company->id, 'start_date' => $this->start_date, 'end_date' => $this->end_date]); - } + // private function paymentIncome() + // { + // return \DB::select(' + // SELECT + // SUM(coalesce(payments.amount - payments.refunded,0)) as payments, + // SUM(coalesce(payments.amount - payments.refunded,0)) * IFNULL(payments.exchange_rate ,1) as payments_converted, + // payments.currency_id as currency_id + // FROM clients + // INNER JOIN + // payments ON + // clients.id=payments.client_id + // WHERE payments.status_id IN (1,4,5,6) + // AND clients.is_deleted = false + // AND payments.is_deleted = false + // AND payments.company_id = :company_id + // AND (payments.date BETWEEN :start_date AND :end_date) + // GROUP BY currency_id + // ORDER BY currency_id; + // ', ['company_id' => $this->company->id, 'start_date' => $this->start_date, 'end_date' => $this->end_date]); + // } private function expenseData() { @@ -544,18 +544,18 @@ class ProfitLoss return round(($amount * $exchange_rate), 2); } - private function expenseCalcWithTax() - { - return \DB::select(' - SELECT sum(expenses.amount) as amount, - IFNULL(expenses.currency_id, :company_currency) as currency_id - FROM expenses - WHERE expenses.is_deleted = 0 - AND expenses.company_id = :company_id - AND (expenses.date BETWEEN :start_date AND :end_date) - GROUP BY currency_id - ', ['company_currency' => $this->company->settings->currency_id, 'company_id' => $this->company->id, 'start_date' => $this->start_date, 'end_date' => $this->end_date]); - } + // private function expenseCalcWithTax() + // { + // return \DB::select(' + // SELECT sum(expenses.amount) as amount, + // IFNULL(expenses.currency_id, :company_currency) as currency_id + // FROM expenses + // WHERE expenses.is_deleted = 0 + // AND expenses.company_id = :company_id + // AND (expenses.date BETWEEN :start_date AND :end_date) + // GROUP BY currency_id + // ', ['company_currency' => $this->company->settings->currency_id, 'company_id' => $this->company->id, 'start_date' => $this->start_date, 'end_date' => $this->end_date]); + // } private function setBillingReportType() { diff --git a/app/Services/Scheduler/EmailStatementService.php b/app/Services/Scheduler/EmailStatementService.php index 84b5be63ce19..64da20836793 100644 --- a/app/Services/Scheduler/EmailStatementService.php +++ b/app/Services/Scheduler/EmailStatementService.php @@ -23,8 +23,6 @@ class EmailStatementService use MakesHash; use MakesDates; - private Client $client; - public function __construct(public Scheduler $scheduler) { } @@ -45,9 +43,6 @@ class EmailStatementService $query->cursor() ->each(function ($_client) { - /**@var \App\Models\Client $_client */ - $this->client = $_client; - //work out the date range $statement_properties = $this->calculateStatementProperties($_client); diff --git a/app/Services/Subscription/SubscriptionCalculator.php b/app/Services/Subscription/SubscriptionCalculator.php index 0179f35b6147..22b427172ff2 100644 --- a/app/Services/Subscription/SubscriptionCalculator.php +++ b/app/Services/Subscription/SubscriptionCalculator.php @@ -102,7 +102,7 @@ class SubscriptionCalculator $line_item->quantity = (float) $item['quantity']; $line_item->cost = (float) $item['product']['price']; $line_item->notes = $item['product']['notes']; - $line_item->tax_id = (string)$item['product']['tax_id'] ?? '1'; + $line_item->tax_id = (string)$item['product']['tax_id'] ?? '1'; //@phpstan-ignore-line $items[] = $line_item; } diff --git a/app/Services/Subscription/SubscriptionService.php b/app/Services/Subscription/SubscriptionService.php index 1cc177b68573..9e97aee3c990 100644 --- a/app/Services/Subscription/SubscriptionService.php +++ b/app/Services/Subscription/SubscriptionService.php @@ -145,7 +145,7 @@ class SubscriptionService /* 06-04-2022 */ /* We may not be in a state where the user is present */ - if (auth()->guard('contact')) { + if (auth()->guard('contact')->user()) { return $this->handleRedirect('/client/invoices/'.$this->encodePrimaryKey($payment_hash->fee_invoice_id)); } } @@ -200,7 +200,7 @@ class SubscriptionService $license->first_name = $contact ? $contact->first_name : ' '; $license->last_name = $contact ? $contact->last_name : ' '; $license->is_claimed = 1; - $license->transaction_reference = $payment_hash?->payment?->transaction_reference ?: ' '; + $license->transaction_reference = $payment_hash?->payment?->transaction_reference ?: ' '; //@phpstan-ignore-line $license->product_id = self::WHITE_LABEL; $license->recurring_invoice_id = $recurring_invoice->id; diff --git a/app/Services/Template/TemplateService.php b/app/Services/Template/TemplateService.php index 2a7149d6af61..a286d05bbb9b 100644 --- a/app/Services/Template/TemplateService.php +++ b/app/Services/Template/TemplateService.php @@ -1327,6 +1327,7 @@ class TemplateService { $entity_string = ''; + //@phpstan-ignore-next-line match($this->entity) { ($this->entity instanceof Invoice) => $entity_string = 'invoice', ($this->entity instanceof Quote) => $entity_string = 'quote', diff --git a/phpstan.neon b/phpstan.neon index 5066456a20bb..df2082796c5b 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -31,4 +31,10 @@ parameters: - '#Access to protected property#' - '#Call to undefined method .*#' - '#Argument of an invalid type stdClass supplied for foreach, only iterables are supported.#' - - '#Comparison operation ">=" between int<1, max> and 1 is always true#' \ No newline at end of file + - '#Comparison operation ">=" between int<1, max> and 1 is always true#' + - '#Negated boolean expression is always#' + - '#Ternary operator condition#' + - '#Expression on left side of ?? is not nullable.#' + - '#Left side of && is always true.#' + - '#Right side of && is always true.#' + \ No newline at end of file From dd1fc3da823be850e31000b3ceae62bfe522993e Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 29 Jun 2024 07:42:45 +1000 Subject: [PATCH 07/16] Updates for country selector --- app/Http/Controllers/ChartController.php | 13 +- .../Chart/ShowCalculatedFieldRequest.php | 78 ++++++++ app/Services/Chart/ChartCalculations.php | 173 ++++++++++++++++++ app/Services/Chart/ChartService.php | 47 ++++- app/Utils/SystemHealth.php | 1 + app/Utils/Traits/MakesDates.php | 34 +++- .../portal/ninja2020/auth/register.blade.php | 2 +- 7 files changed, 344 insertions(+), 4 deletions(-) create mode 100644 app/Http/Requests/Chart/ShowCalculatedFieldRequest.php create mode 100644 app/Services/Chart/ChartCalculations.php diff --git a/app/Http/Controllers/ChartController.php b/app/Http/Controllers/ChartController.php index 1ad2d1423155..394e762d9749 100644 --- a/app/Http/Controllers/ChartController.php +++ b/app/Http/Controllers/ChartController.php @@ -11,8 +11,9 @@ namespace App\Http\Controllers; -use App\Http\Requests\Chart\ShowChartRequest; use App\Services\Chart\ChartService; +use App\Http\Requests\Chart\ShowChartRequest; +use App\Http\Requests\Chart\ShowCalculatedFieldRequest; class ChartController extends BaseController { @@ -65,5 +66,15 @@ class ChartController extends BaseController return response()->json($cs->chart_summary($request->input('start_date'), $request->input('end_date')), 200); } + public function calculatedField(ShowCalculatedFieldRequest $request) + { + /** @var \App\Models\User auth()->user() */ + $user = auth()->user(); + $cs = new ChartService($user->company(), $user, $user->isAdmin()); + $result = $cs->getCalculatedField($request->all()); + + return response()->json($result, 200); + + } } diff --git a/app/Http/Requests/Chart/ShowCalculatedFieldRequest.php b/app/Http/Requests/Chart/ShowCalculatedFieldRequest.php new file mode 100644 index 000000000000..0980dcd3173c --- /dev/null +++ b/app/Http/Requests/Chart/ShowCalculatedFieldRequest.php @@ -0,0 +1,78 @@ +user */ + $user = auth()->user(); + + return $user->isAdmin() || $user->hasPermission('view_dashboard'); + } + + public function rules() + { + return [ + 'date_range' => 'bail|sometimes|string|in:last7_days,last30_days,last365_days,this_month,last_month,this_quarter,last_quarter,this_year,last_year,all_time,custom', + 'start_date' => 'bail|sometimes|date', + 'end_date' => 'bail|sometimes|date', + 'field' => 'required|bail|in:active_invoices, outstanding_invoices, completed_payments, refunded_payments, active_quotes, unapproved_quotes, logged_tasks, invoiced_tasks, paid_tasks, logged_expenses, pending_expenses, invoiced_expenses, invoice_paid_expenses', + 'calculation' => 'required|bail|in:sum,avg,count', + 'period' => 'required|bail|in:current,previous,total', + 'format' => 'sometimes|bail|in:time,money', + ]; + } + + public function prepareForValidation() + { + + /**@var \App\Models\User auth()->user */ + $user = auth()->user(); + + $input = $this->all(); + + if(isset($input['date_range'])) { + $dates = $this->calculateStartAndEndDates($input, $user->company()); + $input['start_date'] = $dates[0]; + $input['end_date'] = $dates[1]; + } + + if (! isset($input['start_date'])) { + $input['start_date'] = now()->subDays(20)->format('Y-m-d'); + } + + if (! isset($input['end_date'])) { + $input['end_date'] = now()->format('Y-m-d'); + } + + if(isset($input['period']) && $input['period'] == 'previous') + { + $dates = $this->calculatePreviousPeriodStartAndEndDates($input, $user->company()); + $input['start_date'] = $dates[0]; + $input['end_date'] = $dates[1]; + } + + $this->replace($input); + } +} diff --git a/app/Services/Chart/ChartCalculations.php b/app/Services/Chart/ChartCalculations.php new file mode 100644 index 000000000000..92cbbd93c1fc --- /dev/null +++ b/app/Services/Chart/ChartCalculations.php @@ -0,0 +1,173 @@ +withTrashed() + ->where('company_id', $this->company->id) + ->where('is_deleted', 0) + ->whereIn('status_id', [2,3,4]); + + if(in_array($data['period'],['current,previous'])) + $q->whereBetween('date', [$data['start_date'], $data['end_date']]); + + match ($data['calculation']) { + 'sum' => $result = $q->sum('amount'), + 'avg' => $result = $q->avg('amount'), + 'count' => $result = $q->count(), + default => $result = 0, + }; + + return $result; + + } + + public function getOutstandingInvoices($data): int|float + { + $result = 0; + + $q = Invoice::query() + ->withTrashed() + ->where('company_id', $this->company->id) + ->where('is_deleted', 0) + ->whereIn('status_id', [2,3]); + + if(in_array($data['period'],['current,previous'])) + $q->whereBetween('date', [$data['start_date'], $data['end_date']]); + + match ($data['calculation']) { + 'sum' => $result = $q->sum('balance'), + 'avg' => $result = $q->avg('balance'), + 'count' => $result = $q->count(), + default => $result = 0, + }; + + return $result; + + } + + public function getCompletedPayments($data): int|float + { + $result = 0; + + $q = Payment::query() + ->withTrashed() + ->where('company_id', $this->company->id) + ->where('is_deleted', 0) + ->where('status_id', 4); + + if(in_array($data['period'],['current,previous'])) + $q->whereBetween('date', [$data['start_date'], $data['end_date']]); + + match ($data['calculation']) { + 'sum' => $result = $q->sum('amount'), + 'avg' => $result = $q->avg('amount'), + 'count' => $result = $q->count(), + default => $result = 0, + }; + + return $result; + + } + + public function getRefundedPayments($data): int|float + { + $result = 0; + + $q = Payment::query() + ->withTrashed() + ->where('company_id', $this->company->id) + ->where('is_deleted', 0) + ->whereIn('status_id', [5,6]); + + if(in_array($data['period'],['current,previous'])) + $q->whereBetween('date', [$data['start_date'], $data['end_date']]); + + match ($data['calculation']) { + 'sum' => $result = $q->sum('refunded'), + 'avg' => $result = $q->avg('refunded'), + 'count' => $result = $q->count(), + default => $result = 0, + }; + + return $result; + + } + + public function getActiveQuotes($data): int|float + { + $result = 0; + + $q = Quote::query() + ->withTrashed() + ->where('company_id', $this->company->id) + ->where('is_deleted', 0) + ->whereIn('status_id', [2,3]) + ->where(function ($qq){ + $qq->where('due_date', '>=', now()->toDateString())->orWhereNull('due_date'); + }); + + if(in_array($data['period'],['current,previous'])) + $q->whereBetween('date', [$data['start_date'], $data['end_date']]); + + match ($data['calculation']) { + 'sum' => $result = $q->sum('refunded'), + 'avg' => $result = $q->avg('refunded'), + 'count' => $result = $q->count(), + default => $result = 0, + }; + + return $result; + + } + + public function getUnapprovedQuotes($data): int|float + { + $result = 0; + + $q = Quote::query() + ->withTrashed() + ->where('company_id', $this->company->id) + ->where('is_deleted', 0) + ->whereIn('status_id', [2]) + ->where(function ($qq){ + $qq->where('due_date', '>=', now()->toDateString())->orWhereNull('due_date'); + }); + + if(in_array($data['period'],['current,previous'])) + $q->whereBetween('date', [$data['start_date'], $data['end_date']]); + + match ($data['calculation']) { + 'sum' => $result = $q->sum('refunded'), + 'avg' => $result = $q->avg('refunded'), + 'count' => $result = $q->count(), + default => $result = 0, + }; + + return $result; + + } +} \ No newline at end of file diff --git a/app/Services/Chart/ChartService.php b/app/Services/Chart/ChartService.php index 479f28e13a22..4bf080f950e6 100644 --- a/app/Services/Chart/ChartService.php +++ b/app/Services/Chart/ChartService.php @@ -14,12 +14,17 @@ namespace App\Services\Chart; use App\Models\Client; use App\Models\Company; use App\Models\Expense; +use App\Models\Invoice; +use App\Models\Payment; +use App\Models\Quote; +use App\Models\Task; use App\Models\User; use Illuminate\Support\Facades\Cache; class ChartService { use ChartQueries; + use ChartCalculations; public function __construct(public Company $company, private User $user, private bool $is_admin) { @@ -71,7 +76,7 @@ class ChartService return $final_currencies; } - + /* Chart Data */ public function chart_summary($start_date, $end_date): array { @@ -207,4 +212,44 @@ class ChartService return ''; } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * calculatedField + * + * @param array $data - + * + * field - list of fields for calculation + * period - current/previous + * calculation - sum/count/avg + * + * date_range - this_month + * or + * start_date - end_date + */ + public function getCalculatedField(array $data) + { + $results = 0; + + match($data['field']){ + 'active_invoices' => $results = $this->getActiveInvoices($data), + 'outstanding_invoices' => $results = 0, + 'completed_payments' => $results = 0, + 'refunded_payments' => $results = 0, + 'active_quotes' => $results = 0, + 'unapproved_quotes' => $results = 0, + 'logged_tasks' => $results = 0, + 'invoiced_tasks' => $results = 0, + 'paid_tasks' => $results = 0, + 'logged_expenses' => $results = 0, + 'pending_expenses' => $results = 0, + 'invoiced_expenses' => $results = 0, + 'invoice_paid_expenses' => $results = 0, + default => $results = 0, + }; + + return $results; + } + } diff --git a/app/Utils/SystemHealth.php b/app/Utils/SystemHealth.php index 2cbbe30313fa..46aac5fa4abb 100644 --- a/app/Utils/SystemHealth.php +++ b/app/Utils/SystemHealth.php @@ -85,6 +85,7 @@ class SystemHealth 'file_permissions' => (string) self::checkFileSystem(), 'exchange_rate_api_not_configured' => (bool)self::checkCurrencySanity(), 'api_version' => (string) config('ninja.app_version'), + 'is_docker' => (bool) config('ninja.is_docker'), ]; } diff --git a/app/Utils/Traits/MakesDates.php b/app/Utils/Traits/MakesDates.php index 25bec419a744..1e7b551ad6a3 100644 --- a/app/Utils/Traits/MakesDates.php +++ b/app/Utils/Traits/MakesDates.php @@ -146,7 +146,6 @@ trait MakesDates } - return match ($data['date_range']) { EmailStatement::LAST7 => [now()->startOfDay()->subDays(7)->format('Y-m-d'), now()->startOfDay()->format('Y-m-d')], EmailStatement::LAST30 => [now()->startOfDay()->subDays(30)->format('Y-m-d'), now()->startOfDay()->format('Y-m-d')], @@ -162,4 +161,37 @@ trait MakesDates }; } + public function calculatePreviousPeriodStartAndEndDates(array $data, ?Company $company = null): array + { + + //override for financial years + if($data['date_range'] == 'this_year') { + + $first_month_of_year = $company ? $company?->first_month_of_year : 1; + $fin_year_start = now()->createFromDate(now()->year, $first_month_of_year, 1); + + $fin_year_start->subYearNoOverflow(); + + if(now()->subYear()->lt($fin_year_start)) { + $fin_year_start->subYearNoOverflow(); + } + + } + + return match ($data['date_range']) { + EmailStatement::LAST7 => [now()->startOfDay()->subDays(14)->format('Y-m-d'), now()->subDays(7)->startOfDay()->format('Y-m-d')], + EmailStatement::LAST30 => [now()->startOfDay()->subDays(60)->format('Y-m-d'), now()->subDays(30)->startOfDay()->format('Y-m-d')], + EmailStatement::LAST365 => [now()->startOfDay()->subDays(739)->format('Y-m-d'), now()->subDays(365)->startOfDay()->format('Y-m-d')], + EmailStatement::THIS_MONTH => [now()->startOfDay()->subMonthNoOverflow()->firstOfMonth()->format('Y-m-d'), now()->startOfDay()->subMonthNoOverflow()->lastOfMonth()->format('Y-m-d')], + EmailStatement::LAST_MONTH => [now()->startOfDay()->subMonthsNoOverflow(2)->firstOfMonth()->format('Y-m-d'), now()->startOfDay()->subMonthNoOverflow()->lastOfMonth()->format('Y-m-d')], + EmailStatement::THIS_QUARTER => [now()->startOfDay()->subQuarterNoOverflow()->startOfQuarter()->format('Y-m-d'), now()->startOfDay()->subQuarterNoOverflow()->endOfQuarter()->format('Y-m-d')], + EmailStatement::LAST_QUARTER => [now()->startOfDay()->subQuartersNoOverflow(2)->startOfQuarter()->format('Y-m-d'), now()->startOfDay()->subQuartersNoOverflow(2)->endOfQuarter()->format('Y-m-d')], + EmailStatement::THIS_YEAR => [$fin_year_start->subYear()->format('Y-m-d'), $fin_year_start->copy()->subDay()->format('Y-m-d')], + EmailStatement::LAST_YEAR => [$fin_year_start->subYear(2)->format('Y-m-d'), $fin_year_start->copy()->subYear()->subDay()->format('Y-m-d')], + EmailStatement::CUSTOM_RANGE => [$data['start_date'], $data['end_date']], + default => [now()->startOfDay()->firstOfMonth()->format('Y-m-d'), now()->startOfDay()->lastOfMonth()->format('Y-m-d')], + }; + + } + } diff --git a/resources/views/portal/ninja2020/auth/register.blade.php b/resources/views/portal/ninja2020/auth/register.blade.php index f18b63a7e012..0dc41c225a32 100644 --- a/resources/views/portal/ninja2020/auth/register.blade.php +++ b/resources/views/portal/ninja2020/auth/register.blade.php @@ -81,7 +81,7 @@ name="country_id"> @foreach(App\Utils\TranslationHelper::getCountries() as $country) - From 7240f4f1e71ba86dcfe253d3fc67f33e31fed8f1 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 29 Jun 2024 08:21:57 +1000 Subject: [PATCH 08/16] Query optimization --- app/Filters/QueryFilters.php | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/app/Filters/QueryFilters.php b/app/Filters/QueryFilters.php index 7f98a1d14e93..143c96e1d7cc 100644 --- a/app/Filters/QueryFilters.php +++ b/app/Filters/QueryFilters.php @@ -273,11 +273,21 @@ abstract class QueryFilters public function filter_deleted_clients($value) { - if ($value == 'true') { - return $this->builder->whereHas('client', function (Builder $query) { - $query->where('is_deleted', 0); + // if ($value == 'true') { + // return $this->builder->whereHas('client', function (Builder $query) { + // $query->where('is_deleted', 0); + // }); + // } + + if($value == 'true') + { + return $this->builder->leftJoin('clients', function($join) { + $join->on('invoices.client_id', '=', 'clients.id') + ->where('clients.is_deleted', 0) + ->whereNull('clients.deleted_at'); }); - } + + } return $this->builder; } From f1ac238917b08807b3a49e4e4e47e93b153a6f1c Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 30 Jun 2024 14:42:57 +1000 Subject: [PATCH 09/16] Fixes for tests --- app/Filters/QueryFilters.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Filters/QueryFilters.php b/app/Filters/QueryFilters.php index 143c96e1d7cc..d9b7877d1170 100644 --- a/app/Filters/QueryFilters.php +++ b/app/Filters/QueryFilters.php @@ -308,7 +308,7 @@ abstract class QueryFilters { return $this->builder->where(function ($query) { $query->whereHas('client', function ($sub_query) { - $sub_query->where('is_deleted', 0)->where('deleted_at', null); + $sub_query->where('is_deleted', 0); })->orWhere('client_id', null); }); } From 3cd1d7767fc055526739e113684e98d0f38341a1 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 30 Jun 2024 14:45:59 +1000 Subject: [PATCH 10/16] Fixes for query name --- app/Filters/QueryFilters.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/Filters/QueryFilters.php b/app/Filters/QueryFilters.php index d9b7877d1170..e5380da3eed6 100644 --- a/app/Filters/QueryFilters.php +++ b/app/Filters/QueryFilters.php @@ -282,9 +282,8 @@ abstract class QueryFilters if($value == 'true') { return $this->builder->leftJoin('clients', function($join) { - $join->on('invoices.client_id', '=', 'clients.id') - ->where('clients.is_deleted', 0) - ->whereNull('clients.deleted_at'); + $join->on("{$this->builder->getQuery()->from}.client_id", '=', 'clients.id') + ->where('clients.is_deleted', 0); }); } From ab23592b96eb052d8e1fbc4d8e18fc076f9a3606 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 30 Jun 2024 17:37:44 +1000 Subject: [PATCH 11/16] Revert refactor for whereHas --- app/Filters/InvoiceFilters.php | 22 ++--- app/Filters/QueryFilters.php | 19 +--- app/Http/Controllers/BaseController.php | 4 +- app/Jobs/Util/ReminderJob.php | 2 +- app/Models/BaseModel.php | 2 +- app/Models/Quote.php | 1 - tests/Feature/ClientModelTest.php | 120 +++++++++++++++++++++++- 7 files changed, 140 insertions(+), 30 deletions(-) diff --git a/app/Filters/InvoiceFilters.php b/app/Filters/InvoiceFilters.php index 0343402a37b2..a9fa3c165dda 100644 --- a/app/Filters/InvoiceFilters.php +++ b/app/Filters/InvoiceFilters.php @@ -152,22 +152,22 @@ class InvoiceFilters extends QueryFilters { return $this->builder->where(function ($query) { - $query->whereIn('status_id', [Invoice::STATUS_PARTIAL, Invoice::STATUS_SENT]) - ->where('is_deleted', 0) - ->where('balance', '>', 0) - ->where(function ($query) { + $query->whereIn('invoices.status_id', [Invoice::STATUS_PARTIAL, Invoice::STATUS_SENT]) + ->where('invoices.is_deleted', 0) + ->where('invoices.balance', '>', 0) + ->orWhere(function ($query) { - $query->whereNull('due_date') + $query->whereNull('invoices.due_date') ->orWhere(function ($q) { - $q->where('due_date', '>=', now()->startOfDay()->subSecond())->where('partial', 0); + $q->where('invoices.due_date', '>=', now()->startOfDay()->subSecond())->where('invoices.partial', 0); }) ->orWhere(function ($q) { - $q->where('partial_due_date', '>=', now()->startOfDay()->subSecond())->where('partial', '>', 0); + $q->where('invoices.partial_due_date', '>=', now()->startOfDay()->subSecond())->where('invoices.partial', '>', 0); }); }) - ->orderByRaw('ISNULL(due_date), due_date ' . 'desc') - ->orderByRaw('ISNULL(partial_due_date), partial_due_date ' . 'desc'); + ->orderByRaw('ISNULL(invoices.due_date), invoices.due_date ' . 'desc') + ->orderByRaw('ISNULL(invoices.partial_due_date), invoices.partial_due_date ' . 'desc'); }); } @@ -337,10 +337,10 @@ class InvoiceFilters extends QueryFilters // return $this->builder->orderByRaw('CAST(number AS UNSIGNED), number ' . $dir); // return $this->builder->orderByRaw("number REGEXP '^[A-Za-z]+$',CAST(number as SIGNED INTEGER),CAST(REPLACE(number,'-','')AS SIGNED INTEGER) ,number"); // return $this->builder->orderByRaw('ABS(number) ' . $dir); - return $this->builder->orderByRaw("REGEXP_REPLACE(number,'[^0-9]+','')+0 " . $dir); + return $this->builder->orderByRaw("REGEXP_REPLACE(invoices.number,'[^0-9]+','')+0 " . $dir); } - return $this->builder->orderBy($sort_col[0], $dir); + return $this->builder->orderBy("{$this->builder->getQuery()->from}.".$sort_col[0], $dir); } /** diff --git a/app/Filters/QueryFilters.php b/app/Filters/QueryFilters.php index e5380da3eed6..7f98a1d14e93 100644 --- a/app/Filters/QueryFilters.php +++ b/app/Filters/QueryFilters.php @@ -273,20 +273,11 @@ abstract class QueryFilters public function filter_deleted_clients($value) { - // if ($value == 'true') { - // return $this->builder->whereHas('client', function (Builder $query) { - // $query->where('is_deleted', 0); - // }); - // } - - if($value == 'true') - { - return $this->builder->leftJoin('clients', function($join) { - $join->on("{$this->builder->getQuery()->from}.client_id", '=', 'clients.id') - ->where('clients.is_deleted', 0); + if ($value == 'true') { + return $this->builder->whereHas('client', function (Builder $query) { + $query->where('is_deleted', 0); }); - - } + } return $this->builder; } @@ -307,7 +298,7 @@ abstract class QueryFilters { return $this->builder->where(function ($query) { $query->whereHas('client', function ($sub_query) { - $sub_query->where('is_deleted', 0); + $sub_query->where('is_deleted', 0)->where('deleted_at', null); })->orWhere('client_id', null); }); } diff --git a/app/Http/Controllers/BaseController.php b/app/Http/Controllers/BaseController.php index dbd7545e9dc1..74934925da28 100644 --- a/app/Http/Controllers/BaseController.php +++ b/app/Http/Controllers/BaseController.php @@ -937,7 +937,9 @@ class BaseController extends Controller } elseif (in_array($this->entity_type, [Design::class, GroupSetting::class, PaymentTerm::class, TaskStatus::class])) { // nlog($this->entity_type); } else { - $query->where('user_id', '=', $user->id)->orWhere('assigned_user_id', $user->id); + $query->where(function ($q) use ($user){ //grouping these together improves query performance significantly) + $q->where('user_id', '=', $user->id)->orWhere('assigned_user_id', $user->id); + }); } } diff --git a/app/Jobs/Util/ReminderJob.php b/app/Jobs/Util/ReminderJob.php index 38b2009c4b2f..330b29c301ac 100644 --- a/app/Jobs/Util/ReminderJob.php +++ b/app/Jobs/Util/ReminderJob.php @@ -71,7 +71,7 @@ class ReminderJob implements ShouldQueue ->whereHas('company', function ($query) { $query->where('is_disabled', 0); }) - ->with('invitations')->chunk(50, function ($invoices) { + ->with('invitations')->chunk(200, function ($invoices) { foreach ($invoices as $invoice) { $this->sendReminderForInvoice($invoice); } diff --git a/app/Models/BaseModel.php b/app/Models/BaseModel.php index 065e3c577cb2..8da00b9043da 100644 --- a/app/Models/BaseModel.php +++ b/app/Models/BaseModel.php @@ -129,7 +129,7 @@ class BaseModel extends Model /** @var \App\Models\User $user */ $user = auth()->user(); - $query->where('company_id', $user->companyId()); + $query->where("{$query->getQuery()->from}.company_id", $user->companyId()); return $query; } diff --git a/app/Models/Quote.php b/app/Models/Quote.php index f751590cc42e..4e3209843944 100644 --- a/app/Models/Quote.php +++ b/app/Models/Quote.php @@ -107,7 +107,6 @@ use Laracasts\Presenter\PresentableTrait; * @property-read \Illuminate\Database\Eloquent\Collection $documents * @property-read \Illuminate\Database\Eloquent\Collection $history * @property-read \Illuminate\Database\Eloquent\Collection $invitations - * @method static \Illuminate\Database\Eloquent\Builder|BaseModel company() * @mixin \Eloquent * @mixin \Illuminate\Database\Eloquent\Builder */ diff --git a/tests/Feature/ClientModelTest.php b/tests/Feature/ClientModelTest.php index d82db842aa33..60421d6afa1b 100644 --- a/tests/Feature/ClientModelTest.php +++ b/tests/Feature/ClientModelTest.php @@ -11,7 +11,9 @@ namespace Tests\Feature; +use App\Models\Client; use App\Models\CompanyGateway; +use App\Models\Invoice; use Illuminate\Foundation\Testing\DatabaseTransactions; use Tests\MockAccountData; use Tests\TestCase; @@ -44,6 +46,122 @@ class ClientModelTest extends TestCase } + public function testNewWithoutAndDeletedClientFilters() + { + + $this->invoice->amount = 10; + $this->invoice->balance = 10; + $this->invoice->status_id=2; + $this->invoice->date = now()->subDays(2); + $this->invoice->due_date = now()->addDays(2); + $this->invoice->save(); + + $cd = Client::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + ]); + + + $cd2 = Client::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + ]); + + $invoice_count = Invoice::where('company_id', $this->company->id)->count(); + + $this->assertGreaterThan(0, $invoice_count); + + $i = Invoice::factory()->create([ + 'client_id' => $cd->id, + 'user_id' => $this->user->id, + 'company_id' => $this->company->id, + 'status_id' => 2, + 'amount' => 10, + 'balance' => 10, + 'date' => now()->subDays(2)->format('Y-m-d'), + 'due_date' => now()->addDays(5)->format('Y-m-d'), + ]); + + + $i2 = Invoice::factory()->create([ + 'client_id' => $cd2->id, + 'user_id' => $this->user->id, + 'company_id' => $this->company->id, + 'status_id' => 2, + 'amount' => 10, + 'balance' => 10, + 'date' => now()->subDays(2)->format('Y-m-d'), + 'due_date' => now()->addDays(5)->format('Y-m-d'), + ]); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->get('/api/v1/invoices?status=active'); + + $response->assertStatus(200); + $arr = $response->json(); + + $this->assertEquals($invoice_count+2, count($arr['data'])); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->get('/api/v1/invoices?upcoming=true&status=active&include=client'); + + $response->assertStatus(200); + $arr = $response->json(); + + $this->assertEquals($invoice_count + 2, count($arr['data'])); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->get('/api/v1/invoices?upcoming=true&status=active&without_deleted_clients=true'); + + $response->assertStatus(200); + $arr = $response->json(); + + $this->assertEquals($invoice_count + 2, count($arr['data'])); + + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->get('/api/v1/invoices?upcoming=true&status=active&filter_deleted_clients=true'); + + $response->assertStatus(200); + $arr = $response->json(); + + $this->assertEquals($invoice_count + 2, count($arr['data'])); + + $cd2->is_deleted = true; + $cd2->save(); + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->get('/api/v1/invoices?upcoming=true&status=active&without_deleted_clients=true'); + + $response->assertStatus(200); + $arr = $response->json(); + + $this->assertEquals($invoice_count + 1, count($arr['data'])); + + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->get('/api/v1/invoices?upcoming=true&status=active&filter_deleted_clients=true'); + + $response->assertStatus(200); + $arr = $response->json(); + + $this->assertEquals($invoice_count + 1, count($arr['data'])); + + + } + public function testPaymentMethodsWithCreditsEnforced() { @@ -51,6 +169,6 @@ class ClientModelTest extends TestCase $this->assertGreaterThan(0, CompanyGateway::count()); - $this->assertEquals(1, count($payment_methods)); + $this->assertEquals(2, count($payment_methods)); } } From b8be425d4d1b50b7164bcf84d069f7ec7035dfbb Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 30 Jun 2024 18:50:51 +1000 Subject: [PATCH 12/16] Increase reminder chunk size --- app/Jobs/Util/ReminderJob.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Jobs/Util/ReminderJob.php b/app/Jobs/Util/ReminderJob.php index 330b29c301ac..5de7e4835b3b 100644 --- a/app/Jobs/Util/ReminderJob.php +++ b/app/Jobs/Util/ReminderJob.php @@ -99,7 +99,7 @@ class ReminderJob implements ShouldQueue ->whereHas('company', function ($query) { $query->where('is_disabled', 0); }) - ->with('invitations')->chunk(50, function ($invoices) { + ->with('invitations')->chunk(200, function ($invoices) { foreach ($invoices as $invoice) { $this->sendReminderForInvoice($invoice); From 81f67a0f1e34973f295cb37f22d430fdcdd6cb85 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 30 Jun 2024 19:01:23 +1000 Subject: [PATCH 13/16] Checks for task array --- app/Jobs/Cron/UpdateCalculatedFields.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/Jobs/Cron/UpdateCalculatedFields.php b/app/Jobs/Cron/UpdateCalculatedFields.php index 5f8bbc31a2bc..465108c96800 100644 --- a/app/Jobs/Cron/UpdateCalculatedFields.php +++ b/app/Jobs/Cron/UpdateCalculatedFields.php @@ -86,6 +86,9 @@ class UpdateCalculatedFields foreach(json_decode($task->time_log) as $log) { + if(!is_array($log)) + continue; + $start_time = $log[0]; $end_time = $log[1] == 0 ? time() : $log[1]; From e0a3126e88e648b1fff09993e379fb0122ad9f68 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 30 Jun 2024 19:02:29 +1000 Subject: [PATCH 14/16] Fixes for zoho --- app/Import/Transformer/Zoho/InvoiceTransformer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Import/Transformer/Zoho/InvoiceTransformer.php b/app/Import/Transformer/Zoho/InvoiceTransformer.php index bf70fb235a0e..0f5bfcc4d824 100644 --- a/app/Import/Transformer/Zoho/InvoiceTransformer.php +++ b/app/Import/Transformer/Zoho/InvoiceTransformer.php @@ -47,7 +47,7 @@ class InvoiceTransformer extends BaseTransformer 'due_date' => isset($invoice_data['Due Date']) ? $this->parseDate($invoice_data['Due Date']) : null, 'po_number' => $this->getString($invoice_data, 'PurchaseOrder'), 'public_notes' => $this->getString($invoice_data, 'Notes'), - 'currency_id' => $this->getCurrencyByCode($invoice_data, 'Currency'), + // 'currency_id' => $this->getCurrencyByCode($invoice_data, 'Currency'), 'amount' => $this->getFloat($invoice_data, 'Total'), 'balance' => $this->getFloat($invoice_data, 'Balance'), 'status_id' => $invoiceStatusMap[$status = From 52e4931b68270176369275859358b35dba4bb5b3 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 1 Jul 2024 08:40:57 +1000 Subject: [PATCH 15/16] Invalidate sessions if DB cannot be set --- app/Http/Middleware/SetDomainNameDb.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/Http/Middleware/SetDomainNameDb.php b/app/Http/Middleware/SetDomainNameDb.php index 83ec5decc7e1..f6e378689850 100644 --- a/app/Http/Middleware/SetDomainNameDb.php +++ b/app/Http/Middleware/SetDomainNameDb.php @@ -56,7 +56,8 @@ class SetDomainNameDb return response()->json($error, 403); } else { MultiDB::setDb('db-ninja-01'); - nlog('I could not set the DB - defaulting to DB1'); + nlog('SetDomainNameDb:: I could not set the DB - defaulting to DB1'); + $request->session()->invalidate(); //abort(400, 'Domain not found'); } } @@ -73,7 +74,8 @@ class SetDomainNameDb return response()->json($error, 403); } else { MultiDB::setDb('db-ninja-01'); - nlog('I could not set the DB - defaulting to DB1'); + nlog('SetDomainNameDb:: I could not set the DB - defaulting to DB1'); + $request->session()->invalidate(); } } } From bb232412916f2a9726010754ab92c7eb5bdf9c87 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Tue, 2 Jul 2024 10:21:34 +1000 Subject: [PATCH 16/16] Fixes for expense reports --- app/Export/CSV/ExpenseExport.php | 11 +++++++++-- app/Repositories/TaskRepository.php | 2 +- tests/Feature/TaskApiTest.php | 16 ++++++++++++++++ 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/app/Export/CSV/ExpenseExport.php b/app/Export/CSV/ExpenseExport.php index 76f49d997b5b..0af4d3faf74d 100644 --- a/app/Export/CSV/ExpenseExport.php +++ b/app/Export/CSV/ExpenseExport.php @@ -259,10 +259,17 @@ class ExpenseExport extends BaseExport { $precision = $expense->currency->precision ?? 2; - $entity['expense.net_amount'] = round($expense->amount, $precision); - if($expense->calculate_tax_by_amount) { + $total_tax_amount = round($expense->tax_amount1 + $expense->tax_amount2 + $expense->tax_amount3, $precision); + + if($expense->uses_inclusive_taxes) { + $entity['expense.net_amount'] = round($expense->amount, $precision) - $total_tax_amount; + } + else { + $entity['expense.net_amount'] = round($expense->amount, $precision); + } + } else { if($expense->uses_inclusive_taxes) { diff --git a/app/Repositories/TaskRepository.php b/app/Repositories/TaskRepository.php index 9f880c92026e..5269ca541e69 100644 --- a/app/Repositories/TaskRepository.php +++ b/app/Repositories/TaskRepository.php @@ -261,7 +261,7 @@ class TaskRepository extends BaseRepository public function roundTimeLog(int $start_time, int $end_time): int { - if($this->task_round_to_nearest == 1 || $end_time == 0) { + if(in_array($this->task_round_to_nearest, [0,1]) || $end_time == 0) { return $end_time; } diff --git a/tests/Feature/TaskApiTest.php b/tests/Feature/TaskApiTest.php index 5a82a3b63781..801201b5876a 100644 --- a/tests/Feature/TaskApiTest.php +++ b/tests/Feature/TaskApiTest.php @@ -189,6 +189,22 @@ class TaskApiTest extends TestCase } + public function testTaskDivisionByZero() + { + $data = [ + "rate" => 0, + "time_log" => '[[1719350900,1719352700,"",true]]', + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->postJson("/api/v1/tasks", $data); + + $response->assertStatus(200); + + } + public function testRequestRuleParsing() {