1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-10 05:02:36 +01:00

Fixes for reminders with partial due dates

This commit is contained in:
David Bomba 2023-09-24 14:54:24 +10:00
parent 1ad4c10538
commit 18d0a39386
11 changed files with 285 additions and 194 deletions

View File

@ -497,8 +497,8 @@ class PreviewController extends BaseController
'variables' => $html->generateLabelsAndValues(),
'process_markdown' => $invoice->client->company->markdown_enabled,
'options' => [
'client' => $invitation->invoice->client,
'entity' => $invitation->invoice,
'client' => $invoice->client,
'entity' => $invoice,
]
];

View File

@ -73,6 +73,8 @@ class StoreInvoiceRequest extends Request
$rules['tax_name2'] = 'bail|sometimes|string|nullable';
$rules['tax_name3'] = 'bail|sometimes|string|nullable';
$rules['exchange_rate'] = 'bail|sometimes|numeric';
$rules['partial'] = 'bail|sometimes|nullable|numeric';
$rules['partial_due_date'] = 'bail|sometimes|required_if:partial,>0|date';
return $rules;
}

View File

@ -76,6 +76,8 @@ class UpdateInvoiceRequest extends Request
$rules['tax_name3'] = 'bail|sometimes|string|nullable';
$rules['status_id'] = 'bail|sometimes|not_in:5'; //do not allow cancelled invoices to be modfified.
$rules['exchange_rate'] = 'bail|sometimes|numeric';
$rules['partial'] = 'bail|sometimes|nullable|numeric';
$rules['partial_due_date'] = 'bail|sometimes|required_if:partial,>0|date';
return $rules;
}

View File

@ -139,11 +139,8 @@ class PaymentRepository extends BaseRepository
$invoices = Invoice::withTrashed()->whereIn('id', array_column($data['invoices'], 'invoice_id'))->get();
// $payment->invoices()->saveMany($invoices); //25-06-2023
//todo optimize this into a single query
foreach ($data['invoices'] as $paid_invoice) {
// $invoice = Invoice::withTrashed()->whereId($paid_invoice['invoice_id'])->first();
$invoice = $invoices->firstWhere('id', $paid_invoice['invoice_id']);
if ($invoice) {

View File

@ -47,8 +47,17 @@ class ApplyPayment extends AbstractService
$amount_paid = $this->payment_amount * -1;
$this->invoice->service()->clearPartial()->setDueDate()->setStatus(Invoice::STATUS_PARTIAL)->updateBalance($amount_paid)->save();
$this->invoice
->service()
->clearPartial()
->setDueDate()
->setStatus(Invoice::STATUS_PARTIAL)
->updateBalance($amount_paid)
->save();
}
$this->invoice->service()->checkReminderStatus()->save();
} else {
if ($this->payment_amount == $this->invoice->balance) {
$amount_paid = $this->payment_amount * -1;
@ -84,9 +93,6 @@ class ApplyPayment extends AbstractService
/* Update Pivot Record amount */
$this->payment->invoices->each(function ($inv) use ($amount_paid) {
if ($inv->id == $this->invoice->id) {
// $inv->pivot->amount = ($amount_paid * -1);
// $inv->pivot->save();
//25-06-2023
$inv->paid_to_date += floatval($amount_paid * -1);
$inv->save();
}
@ -96,7 +102,6 @@ class ApplyPayment extends AbstractService
->service()
->applyNumber()
->workFlow()
// ->deletePdf()
->save();
return $this->invoice;

View File

@ -31,7 +31,7 @@ class ApplyPaymentAmount extends AbstractService
}
public function run()
{
{nlog("apply payment amount");
if ($this->invoice->status_id == Invoice::STATUS_DRAFT) {
$this->invoice = $this->invoice->service()->markSent()->save();
}
@ -65,15 +65,28 @@ class ApplyPaymentAmount extends AbstractService
'amount' => $payment->amount,
]);
$this->invoice->next_send_date = null;
$this->invoice->service()
$has_partial = $this->invoice->hasPartial();
$invoice_service = $this->invoice->service()
->setExchangeRate()
->updateBalance($payment->amount * -1)
->updatePaidToDate($payment->amount)
->setCalculatedStatus()
->applyNumber()
->save();
->applyNumber();
nlog("check for partials");
if ($has_partial) {
nlog("has partial");
$invoice_service->checkReminderStatus();
}
if($this->invoice->balance == 0){
$this->invoice->next_send_date = null;
}
$this->invoice = $invoice_service->save();
$this->invoice
->client

View File

@ -290,6 +290,31 @@ class InvoiceService
return $this;
}
/**
* Reset the reminders if only the
* partial has been paid.
*
* We can _ONLY_ call this _IF_ a partial
* amount has been paid, otherwise we end up wiping
* all reminders regardless
*
* @return self
*/
public function checkReminderStatus(): self
{
if($this->invoice->partial == 0 && $this->invoice->balance > 0)
{
$this->invoice->reminder1_sent = null;
$this->invoice->reminder2_sent = null;
$this->invoice->reminder3_sent = null;
$this->setReminder();
}
return $this;
}
public function setReminder($settings = null)
{

View File

@ -49,27 +49,32 @@ class UpdateReminder extends AbstractService
$this->settings->schedule_reminder1 == 'after_invoice_date') {
$reminder_date = Carbon::parse($this->invoice->date)->startOfDay()->addDays($this->settings->num_days_reminder1);
if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date))) {
if ($reminder_date->gt(now())) {
$date_collection->push($reminder_date);
}
}
if (is_null($this->invoice->reminder1_sent) &&
$this->invoice->due_date &&
($this->invoice->partial_due_date || $this->invoice->due_date) &&
$this->settings->schedule_reminder1 == 'before_due_date') {
$reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->subDays($this->settings->num_days_reminder1);
$partial_or_due_date = ($this->invoice->partial > 0 && isset($this->invoice->partial_due_date)) ? $this->invoice->partial_due_date : $this->invoice->due_date;
$reminder_date = Carbon::parse($partial_or_due_date)->startOfDay()->subDays($this->settings->num_days_reminder1);
// nlog("1. {$reminder_date->format('Y-m-d')}");
if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date))) {
if ($reminder_date->gt(now())) {
$date_collection->push($reminder_date);
}
}
if (is_null($this->invoice->reminder1_sent) &&
$this->invoice->due_date &&
($this->invoice->partial_due_date || $this->invoice->due_date) &&
$this->settings->schedule_reminder1 == 'after_due_date') {
$reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->addDays($this->settings->num_days_reminder1);
$partial_or_due_date = ($this->invoice->partial > 0 && isset($this->invoice->partial_due_date)) ? $this->invoice->partial_due_date : $this->invoice->due_date;
$reminder_date = Carbon::parse($partial_or_due_date)->startOfDay()->addDays($this->settings->num_days_reminder1);
// nlog("2. {$reminder_date->format('Y-m-d')}");
if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date))) {
if ($reminder_date->gt(now())) {
$date_collection->push($reminder_date);
}
}
@ -78,27 +83,33 @@ class UpdateReminder extends AbstractService
$this->settings->schedule_reminder2 == 'after_invoice_date') {
$reminder_date = Carbon::parse($this->invoice->date)->startOfDay()->addDays($this->settings->num_days_reminder2);
if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date))) {
if ($reminder_date->gt(now())) {
$date_collection->push($reminder_date);
}
}
if (is_null($this->invoice->reminder2_sent) &&
$this->invoice->due_date &&
($this->invoice->partial_due_date || $this->invoice->due_date) &&
$this->settings->schedule_reminder2 == 'before_due_date') {
$reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->subDays($this->settings->num_days_reminder2);
if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date))) {
$partial_or_due_date = ($this->invoice->partial > 0 && isset($this->invoice->partial_due_date)) ? $this->invoice->partial_due_date : $this->invoice->due_date;
$reminder_date = Carbon::parse($partial_or_due_date)->startOfDay()->subDays($this->settings->num_days_reminder2);
// nlog("3. {$reminder_date->format('Y-m-d')}");
if ($reminder_date->gt(now())) {
$date_collection->push($reminder_date);
}
}
if (is_null($this->invoice->reminder2_sent) &&
$this->invoice->due_date &&
($this->invoice->partial_due_date || $this->invoice->due_date) &&
$this->settings->schedule_reminder2 == 'after_due_date') {
$reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->addDays($this->settings->num_days_reminder2);
$partial_or_due_date = ($this->invoice->partial > 0 && isset($this->invoice->partial_due_date)) ? $this->invoice->partial_due_date : $this->invoice->due_date;
$reminder_date = Carbon::parse($partial_or_due_date)->startOfDay()->addDays($this->settings->num_days_reminder2);
// nlog("4. {$reminder_date->format('Y-m-d')}");
if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date))) {
if ($reminder_date->gt(now())) {
$date_collection->push($reminder_date);
}
}
@ -107,27 +118,33 @@ class UpdateReminder extends AbstractService
$this->settings->schedule_reminder3 == 'after_invoice_date') {
$reminder_date = Carbon::parse($this->invoice->date)->startOfDay()->addDays($this->settings->num_days_reminder3);
if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date))) {
if ($reminder_date->gt(now())) {
$date_collection->push($reminder_date);
}
}
if (is_null($this->invoice->reminder3_sent) &&
$this->invoice->due_date &&
($this->invoice->partial_due_date || $this->invoice->due_date) &&
$this->settings->schedule_reminder3 == 'before_due_date') {
$reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->subDays($this->settings->num_days_reminder3);
$partial_or_due_date = ($this->invoice->partial > 0 && isset($this->invoice->partial_due_date)) ? $this->invoice->partial_due_date : $this->invoice->due_date;
$reminder_date = Carbon::parse($partial_or_due_date)->startOfDay()->subDays($this->settings->num_days_reminder3);
// nlog("5. {$reminder_date->format('Y-m-d')}");
if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date))) {
if ($reminder_date->gt(now())) {
$date_collection->push($reminder_date);
}
}
if (is_null($this->invoice->reminder3_sent) &&
$this->invoice->due_date &&
($this->invoice->partial_due_date || $this->invoice->due_date) &&
$this->settings->schedule_reminder3 == 'after_due_date') {
$reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->addDays($this->settings->num_days_reminder3);
$partial_or_due_date = ($this->invoice->partial > 0 && isset($this->invoice->partial_due_date)) ? $this->invoice->partial_due_date : $this->invoice->due_date;
$reminder_date = Carbon::parse($partial_or_due_date)->startOfDay()->addDays($this->settings->num_days_reminder3);
// nlog("6. {$reminder_date->format('Y-m-d')}");
if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date))) {
if ($reminder_date->gt(now())) {
$date_collection->push($reminder_date);
}
}
@ -140,7 +157,7 @@ class UpdateReminder extends AbstractService
$reminder_date = $this->addTimeInterval($this->invoice->last_sent_date, (int) $this->settings->endless_reminder_frequency_id);
if ($reminder_date) {
if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date))) {
if ($reminder_date->gt(now())) {
$date_collection->push($reminder_date);
}
}

View File

@ -55,6 +55,8 @@ class UpdateInvoicePayment
$invoice->restore();
}
// $has_partial = $invoice->hasPartial();
if ($invoice->id == $this->payment_hash->fee_invoice_id) {
$paid_amount = $paid_invoice->amount + $this->payment_hash->fee_total;
} else {
@ -63,6 +65,8 @@ class UpdateInvoicePayment
$client->service()->updatePaidToDate($paid_amount); //always use the payment->amount
$has_partial = $invoice->hasPartial();
/* Need to determine here is we have an OVER payment - if YES only apply the max invoice amount */
if ($paid_amount > $invoice->partial && $paid_amount > $invoice->balance) {
$paid_amount = $invoice->balance;
@ -76,12 +80,16 @@ class UpdateInvoicePayment
$invoice->paid_to_date += $paid_amount;
$invoice->save();
$invoice = $invoice->service()
->clearPartial()
->updateStatus()
// ->deletePdf()
->workFlow()
->save();
$invoice_service = $invoice->service()
->clearPartial()
->updateStatus()
->workFlow();
if ($has_partial) {
$invoice_service->checkReminderStatus();
}
$invoice = $invoice_service->save();
if ($invoice->is_proforma) {
//keep proforma's hidden

230
composer.lock generated
View File

@ -6,46 +6,6 @@
],
"content-hash": "08bc4729962b495b68162a069269f74f",
"packages": [
{
"name": "adrienrn/php-mimetyper",
"version": "0.2.2",
"source": {
"type": "git",
"url": "https://github.com/adrienrn/php-mimetyper.git",
"reference": "702e00a604b4baed34d69730ce055e05c0f43932"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/adrienrn/php-mimetyper/zipball/702e00a604b4baed34d69730ce055e05c0f43932",
"reference": "702e00a604b4baed34d69730ce055e05c0f43932",
"shasum": ""
},
"require": {
"dflydev/apache-mime-types": "^1.0"
},
"type": "library",
"autoload": {
"psr-4": {
"MimeTyper\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Hussard",
"email": "adrien.ricartnoblet@gmail.com"
}
],
"description": "PHP mime type and extension mapping library: compatible with Symfony, powered by jshttp/mime-db",
"support": {
"issues": "https://github.com/adrienrn/php-mimetyper/issues",
"source": "https://github.com/adrienrn/php-mimetyper/tree/0.2.2"
},
"time": "2018-09-27T09:45:05+00:00"
},
{
"name": "afosto/yaac",
"version": "v1.5.2",
@ -525,16 +485,16 @@
},
{
"name": "aws/aws-sdk-php",
"version": "3.281.11",
"version": "3.281.12",
"source": {
"type": "git",
"url": "https://github.com/aws/aws-sdk-php.git",
"reference": "9d466efae67d5016ed132fd4ffa1566a7d4cab98"
"reference": "22a92f08758db2b152843ea0875eeee5a467d8ff"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/9d466efae67d5016ed132fd4ffa1566a7d4cab98",
"reference": "9d466efae67d5016ed132fd4ffa1566a7d4cab98",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/22a92f08758db2b152843ea0875eeee5a467d8ff",
"reference": "22a92f08758db2b152843ea0875eeee5a467d8ff",
"shasum": ""
},
"require": {
@ -614,9 +574,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.281.11"
"source": "https://github.com/aws/aws-sdk-php/tree/3.281.12"
},
"time": "2023-09-20T19:16:24+00:00"
"time": "2023-09-22T18:12:27+00:00"
},
{
"name": "bacon/bacon-qr-code",
@ -1147,65 +1107,6 @@
},
"time": "2023-08-25T16:18:39+00:00"
},
{
"name": "dflydev/apache-mime-types",
"version": "v1.0.1",
"source": {
"type": "git",
"url": "https://github.com/dflydev/dflydev-apache-mime-types.git",
"reference": "f30a57e59b7476e4c5270b6a0727d79c9c0eb861"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/dflydev/dflydev-apache-mime-types/zipball/f30a57e59b7476e4c5270b6a0727d79c9c0eb861",
"reference": "f30a57e59b7476e4c5270b6a0727d79c9c0eb861",
"shasum": ""
},
"require": {
"php": ">=5.3"
},
"require-dev": {
"twig/twig": "1.*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"psr-0": {
"Dflydev\\ApacheMimeTypes": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Dragonfly Development Inc.",
"email": "info@dflydev.com",
"homepage": "http://dflydev.com"
},
{
"name": "Beau Simensen",
"email": "beau@dflydev.com",
"homepage": "http://beausimensen.com"
}
],
"description": "Apache MIME Types",
"keywords": [
"apache",
"mime",
"mimetypes"
],
"support": {
"issues": "https://github.com/dflydev/dflydev-apache-mime-types/issues",
"source": "https://github.com/dflydev/dflydev-apache-mime-types/tree/v1.0.1"
},
"time": "2013-05-14T02:02:01+00:00"
},
{
"name": "dflydev/dot-access-data",
"version": "v3.0.2",
@ -1452,16 +1353,16 @@
},
{
"name": "doctrine/dbal",
"version": "3.6.6",
"version": "3.6.7",
"source": {
"type": "git",
"url": "https://github.com/doctrine/dbal.git",
"reference": "63646ffd71d1676d2f747f871be31b7e921c7864"
"reference": "8e0e268052b4a8974cb00215bb2892787021614f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/dbal/zipball/63646ffd71d1676d2f747f871be31b7e921c7864",
"reference": "63646ffd71d1676d2f747f871be31b7e921c7864",
"url": "https://api.github.com/repos/doctrine/dbal/zipball/8e0e268052b4a8974cb00215bb2892787021614f",
"reference": "8e0e268052b4a8974cb00215bb2892787021614f",
"shasum": ""
},
"require": {
@ -1477,9 +1378,9 @@
"doctrine/coding-standard": "12.0.0",
"fig/log-test": "^1",
"jetbrains/phpstorm-stubs": "2023.1",
"phpstan/phpstan": "1.10.29",
"phpstan/phpstan": "1.10.34",
"phpstan/phpstan-strict-rules": "^1.5",
"phpunit/phpunit": "9.6.9",
"phpunit/phpunit": "9.6.12",
"psalm/plugin-phpunit": "0.18.4",
"slevomat/coding-standard": "8.13.1",
"squizlabs/php_codesniffer": "3.7.2",
@ -1545,7 +1446,7 @@
],
"support": {
"issues": "https://github.com/doctrine/dbal/issues",
"source": "https://github.com/doctrine/dbal/tree/3.6.6"
"source": "https://github.com/doctrine/dbal/tree/3.6.7"
},
"funding": [
{
@ -1561,7 +1462,7 @@
"type": "tidelift"
}
],
"time": "2023-08-17T05:38:17+00:00"
"time": "2023-09-19T20:15:41+00:00"
},
{
"name": "doctrine/deprecations",
@ -3385,6 +3286,61 @@
},
"time": "2023-08-14T19:20:53+00:00"
},
{
"name": "horstoeko/mimedb",
"version": "v1.0.5",
"source": {
"type": "git",
"url": "https://github.com/horstoeko/mimedb.git",
"reference": "2790b61cbff7f94ae8f40565761b15beb7792fcb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/horstoeko/mimedb/zipball/2790b61cbff7f94ae8f40565761b15beb7792fcb",
"reference": "2790b61cbff7f94ae8f40565761b15beb7792fcb",
"shasum": ""
},
"require": {
"php": "^7.3|^7.4|^8.0|^8.1|^8.2|^8.3"
},
"require-dev": {
"pdepend/pdepend": "^2",
"phploc/phploc": "^7",
"phpmd/phpmd": "^2",
"phpstan/phpstan": "^1.8",
"phpunit/phpunit": "^9",
"sebastian/phpcpd": "^6",
"squizlabs/php_codesniffer": "^3"
},
"type": "package",
"autoload": {
"psr-4": {
"horstoeko\\mimedb\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Daniel Erling",
"email": "daniel@erling.com.de",
"role": "lead"
}
],
"description": "Get mimetypes by fileextensions and visa versa",
"homepage": "https://github.com/horstoeko/mimedb",
"keywords": [
"file extension",
"mimetype"
],
"support": {
"issues": "https://github.com/horstoeko/mimedb/issues",
"source": "https://github.com/horstoeko/mimedb/tree/v1.0.5"
},
"time": "2023-09-22T20:17:48+00:00"
},
{
"name": "horstoeko/stringmanagement",
"version": "v1.0.11",
@ -3441,22 +3397,22 @@
},
{
"name": "horstoeko/zugferd",
"version": "v1.0.28",
"version": "v1.0.29",
"source": {
"type": "git",
"url": "https://github.com/horstoeko/zugferd.git",
"reference": "be78b1b53a46e94a69b92dcff1e909180170583c"
"reference": "9fb81e2e9a16d10bec8bf655484aae11bdca1997"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/horstoeko/zugferd/zipball/be78b1b53a46e94a69b92dcff1e909180170583c",
"reference": "be78b1b53a46e94a69b92dcff1e909180170583c",
"url": "https://api.github.com/repos/horstoeko/zugferd/zipball/9fb81e2e9a16d10bec8bf655484aae11bdca1997",
"reference": "9fb81e2e9a16d10bec8bf655484aae11bdca1997",
"shasum": ""
},
"require": {
"adrienrn/php-mimetyper": "^0.2",
"ext-simplexml": "*",
"goetas-webservices/xsd2php-runtime": "^0.2.13",
"horstoeko/mimedb": "^1",
"horstoeko/stringmanagement": "^1",
"jms/serializer": "^3",
"php": "^7.3|^7.4|^8.0|^8.1",
@ -3508,9 +3464,9 @@
],
"support": {
"issues": "https://github.com/horstoeko/zugferd/issues",
"source": "https://github.com/horstoeko/zugferd/tree/v1.0.28"
"source": "https://github.com/horstoeko/zugferd/tree/v1.0.29"
},
"time": "2023-09-12T14:54:01+00:00"
"time": "2023-09-23T06:15:04+00:00"
},
{
"name": "http-interop/http-factory-guzzle",
@ -5227,16 +5183,16 @@
},
{
"name": "league/csv",
"version": "9.10.0",
"version": "9.11.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/csv.git",
"reference": "d24b0d484812313b07ab74b0fe4db9661606df6c"
"reference": "33149c4bea4949aa4fa3d03fb11ed28682168b39"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/csv/zipball/d24b0d484812313b07ab74b0fe4db9661606df6c",
"reference": "d24b0d484812313b07ab74b0fe4db9661606df6c",
"url": "https://api.github.com/repos/thephpleague/csv/zipball/33149c4bea4949aa4fa3d03fb11ed28682168b39",
"reference": "33149c4bea4949aa4fa3d03fb11ed28682168b39",
"shasum": ""
},
"require": {
@ -5311,7 +5267,7 @@
"type": "github"
}
],
"time": "2023-08-04T15:12:48+00:00"
"time": "2023-09-23T10:09:54+00:00"
},
{
"name": "league/flysystem",
@ -8531,16 +8487,16 @@
},
{
"name": "psr/http-client",
"version": "1.0.2",
"version": "1.0.3",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-client.git",
"reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31"
"reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-client/zipball/0955afe48220520692d2d09f7ab7e0f93ffd6a31",
"reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31",
"url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90",
"reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90",
"shasum": ""
},
"require": {
@ -8577,9 +8533,9 @@
"psr-18"
],
"support": {
"source": "https://github.com/php-fig/http-client/tree/1.0.2"
"source": "https://github.com/php-fig/http-client"
},
"time": "2023-04-10T20:12:12+00:00"
"time": "2023-09-23T14:17:50+00:00"
},
{
"name": "psr/http-factory",
@ -15152,16 +15108,16 @@
},
{
"name": "friendsofphp/php-cs-fixer",
"version": "v3.27.0",
"version": "v3.28.0",
"source": {
"type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
"reference": "e73ccaae1208f017bb7860986eebb3da48bd25d6"
"reference": "113e09fea3d2306319ffaa2423fe3de768b28cff"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/e73ccaae1208f017bb7860986eebb3da48bd25d6",
"reference": "e73ccaae1208f017bb7860986eebb3da48bd25d6",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/113e09fea3d2306319ffaa2423fe3de768b28cff",
"reference": "113e09fea3d2306319ffaa2423fe3de768b28cff",
"shasum": ""
},
"require": {
@ -15235,7 +15191,7 @@
],
"support": {
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.27.0"
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.28.0"
},
"funding": [
{
@ -15243,7 +15199,7 @@
"type": "github"
}
],
"time": "2023-09-17T14:37:54+00:00"
"time": "2023-09-22T20:43:40+00:00"
},
{
"name": "hamcrest/hamcrest-php",

View File

@ -158,6 +158,82 @@ class ReminderTest extends TestCase
}
public function testPartialDueDateReminder()
{
$settings = $this->company->settings;
$settings->enable_reminder1 = true;
$settings->schedule_reminder1 = 'before_due_date';
$settings->num_days_reminder1 = 1;
$settings->enable_reminder2 = true;
$settings->schedule_reminder2 = 'after_due_date';
$settings->num_days_reminder2 = 14;
$settings->enable_reminder3 = true;
$settings->schedule_reminder3 = 'after_due_date';
$settings->num_days_reminder3 = 30;
$settings->timezone_id = '29';
$settings->entity_send_time = 0;
$settings->endless_reminder_frequency_id = '';
$settings->enable_reminder_endless = false;
$this->buildData(($settings));
$this->invoice->reminder1_sent = null;
$this->invoice->reminder2_sent = null;
$this->invoice->reminder3_sent = null;
$this->invoice->date = now()->startOfDay();
$this->invoice->partial = 10;
$this->invoice->amount = 100;
$this->invoice->balance = 100;
$this->invoice->partial_due_date = now()->startOfDay()->addDays(7);
$this->invoice->due_date = now()->startOfDay()->addMonth();
$this->invoice->service()->setReminder($settings)->save();
$this->invoice = $this->invoice->fresh();
$this->assertEquals(now()->startOfDay()->addDays(6)->format('Y-m-d'), Carbon::parse($this->invoice->next_send_date)->format('Y-m-d'));
$this->assertTrue($this->invoice->hasPartial());
$data = [
'amount' => 10,
'client_id' => $this->client->hashed_id,
'invoices' => [
[
'invoice_id' => $this->invoice->hashed_id,
'amount' => 10,
]
]
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/payments/', $data);
$response->assertStatus(200);
$this->invoice = $this->invoice->fresh();
$this->assertEquals(0, $this->invoice->partial);
$this->assertNull($this->invoice->partial_due_date);
$this->assertNull($this->invoice->reminder1_sent);
$this->assertNull($this->invoice->reminder2_sent);
$this->assertNull($this->invoice->reminder3_sent);
$this->assertEquals(90, $this->invoice->balance);
$this->assertEquals(Carbon::parse($this->invoice->due_date)->startOfDay()->subDay()->format('Y-m-d'), Carbon::parse($this->invoice->next_send_date)->startOfDay()->format('Y-m-d'));
$this->travelTo(Carbon::parse($this->invoice->due_date)->startOfDay()->subDay()->addHour());
(new ReminderJob())->handle();
$this->invoice = $this->invoice->fresh();
$this->assertNotNull($this->invoice->reminder1_sent);
$this->assertEquals(Carbon::parse($this->invoice->due_date)->startOfDay()->addDays(14)->format('Y-m-d'), Carbon::parse($this->invoice->next_send_date)->format('Y-m-d'));
$this->travelBack();
}
public function testsForTranslationsInReminders()
{
@ -233,16 +309,6 @@ class ReminderTest extends TestCase
$this->assertEquals(103, $fee->cost);
$this->assertEquals('Fee added '.now()->format('d/M/Y'), $fee->notes);
// $this->travelTo(now()->addHours(1));
// }
$this->travelBack();
}
@ -391,8 +457,8 @@ class ReminderTest extends TestCase
$next_send_date = Carbon::parse($this->invoice->next_send_date);
$calculatedReminderDate = Carbon::parse($this->invoice->due_date)->subDays(4)->addSeconds($this->invoice->client->timezone_offset());
nlog($next_send_date->format('Y-m-d h:i:s'));
nlog($calculatedReminderDate->format('Y-m-d h:i:s'));
// nlog($next_send_date->format('Y-m-d h:i:s'));
// nlog($calculatedReminderDate->format('Y-m-d h:i:s'));
$this->travelTo($calculatedReminderDate);
@ -413,7 +479,7 @@ class ReminderTest extends TestCase
$next_send_date = Carbon::parse($this->invoice->next_send_date);
nlog($next_send_date->format('Y-m-d h:i:s'));
// nlog($next_send_date->format('Y-m-d h:i:s'));
$calculatedReminderDate = Carbon::parse($this->invoice->due_date)->subDays(2)->addSeconds($this->invoice->client->timezone_offset());
$this->assertTrue($next_send_date->eq($calculatedReminderDate));
@ -432,7 +498,7 @@ class ReminderTest extends TestCase
$calculatedReminderDate = Carbon::parse($this->invoice->due_date)->addDays(3)->addSeconds($this->invoice->client->timezone_offset());
$this->assertTrue($next_send_date->eq($calculatedReminderDate));
nlog($next_send_date->format('Y-m-d h:i:s'));
// nlog($next_send_date->format('Y-m-d h:i:s'));
}
public function testReminderQueryCatchesDate()