Support rolling back converted status on a quote when the invoice has been deleted

This commit is contained in:
David Bomba 2024-07-22 13:05:40 +10:00
parent 25d3668050
commit cd2b45edc9
8 changed files with 76 additions and 41 deletions

View File

@ -46,7 +46,7 @@ class StorePaymentRequest extends Request
$rules = [
'client_id' => ['bail','required',Rule::exists('clients', 'id')->where('company_id', $user->company()->id)->where('is_deleted', 0)],
'invoices' => ['bail','sometimes', 'nullable', 'array', new ValidPayableInvoicesRule()],
'invoices' => ['bail', 'sometimes', 'nullable', 'array', new ValidPayableInvoicesRule()],
'invoices.*.amount' => ['bail','required'],
'invoices.*.invoice_id' => ['bail','required','distinct', new ValidInvoicesRules($this->all()),Rule::exists('invoices', 'id')->where('company_id', $user->company()->id)->where('client_id', $this->client_id)],
'credits.*.credit_id' => ['bail','required','distinct', new ValidCreditsRules($this->all()),Rule::exists('credits', 'id')->where('company_id', $user->company()->id)->where('client_id', $this->client_id)],

View File

@ -85,11 +85,12 @@ class ValidInvoicesRules implements Rule
//catch here nothing to do - we need this to prevent the last elseif triggering
} elseif ($inv->status_id == Invoice::STATUS_DRAFT && floatval($invoice['amount']) > floatval($inv->amount)) {
$this->error_msg = 'Amount cannot be greater than invoice balance';
return false;
} elseif (floatval($invoice['amount']) > floatval($inv->balance)) {
$this->error_msg = ctrans('texts.amount_greater_than_balance_v5');
return false;
} elseif($inv->is_deleted){
$this->error_msg = 'One or more invoices in this request have since been deleted';
return false;
}
}

View File

@ -35,7 +35,7 @@ class ValidPayableInvoicesRule implements Rule
$invoices = [];
if (is_array($value)) {
$invoices = Invoice::query()->whereIn('id', array_column($value, 'invoice_id'))->company()->get();
$invoices = Invoice::query()->withTrashed()->whereIn('id', array_column($value, 'invoice_id'))->company()->get();
}
foreach ($invoices as $invoice) {

View File

@ -371,6 +371,14 @@ class Invoice extends BaseModel
return $this->hasOne(Task::class);
}
/**
* @return \Illuminate\Database\Eloquent\Relations\HasOne<Quote>
*/
public function quote(): \Illuminate\Database\Eloquent\Relations\HasOne
{
return $this->hasOne(Quote::class);
}
public function expenses(): \Illuminate\Database\Eloquent\Relations\HasMany
{
return $this->hasMany(Expense::class);
@ -423,7 +431,9 @@ class Invoice extends BaseModel
public function isPayable(): bool
{
if ($this->status_id == self::STATUS_DRAFT && $this->is_deleted == false) {
if($this->is_deleted)
return false;
elseif ($this->status_id == self::STATUS_DRAFT && $this->is_deleted == false) {
return true;
} elseif ($this->status_id == self::STATUS_SENT && $this->is_deleted == false) {
return true;

View File

@ -48,11 +48,9 @@ class Storecove {
//config('ninja.storecove_api_key');
//https://app.storecove.com/en/docs#_test_identifiers
//check if identifier is able to send on the network.
//response = { "code": "OK", "email": false}
public function discovery($identifier, $scheme, $network = 'peppol')
{

View File

@ -47,6 +47,8 @@ use InvoiceNinja\EInvoice\Models\Peppol\TaxCategoryType\ClassifiedTaxCategory;
use InvoiceNinja\EInvoice\Models\Peppol\CustomerPartyType\AccountingCustomerParty;
use InvoiceNinja\EInvoice\Models\Peppol\SupplierPartyType\AccountingSupplierParty;
use InvoiceNinja\EInvoice\Models\Peppol\FinancialAccountType\PayeeFinancialAccount;
use InvoiceNinja\EInvoice\Models\Peppol\IdentifierType\ID;
use InvoiceNinja\EInvoice\Models\Peppol\PartyIdentification;
class Peppol extends AbstractService
{
@ -115,6 +117,7 @@ class Peppol extends AbstractService
// ->setPaymentMeansCode($invoice->custom_value1)
// ->setPayeeFinancialAccount($payeeFinancialAccount);
// $ubl_invoice->setPaymentMeans($paymentMeans);
return $this;
}
@ -464,6 +467,19 @@ $tax_amount->amount = $this->invoice->uses_inclusive_taxes ? $this->calcInclusiv
$party = new Party();
if(strlen($this->invoice->client->vat_number ?? '') > 1) {
$pi = new PartyIdentification;
$vatID = new ID;
$vatID->schemeID = 'IT:VAT';
$vatID->value = $this->invoice->client->vat_number;
$pi->ID = $vatID;
$party->PartyIdentification[] = $pi;
}
$party_name = new PartyName();
$party_name->Name = $this->invoice->client->present()->name();
$party->PartyName[] = $party_name;

View File

@ -13,6 +13,7 @@ namespace App\Services\Invoice;
use App\Jobs\Inventory\AdjustProductInventory;
use App\Models\Invoice;
use App\Models\Quote;
use App\Services\AbstractService;
use App\Utils\Traits\GeneratesCounter;
@ -45,7 +46,8 @@ class MarkInvoiceDeleted extends AbstractService
->deletePaymentables()
->adjustPayments()
->adjustPaidToDateAndBalance()
->adjustLedger();
->adjustLedger()
->triggeredActions();
return $this->invoice;
}
@ -182,4 +184,15 @@ class MarkInvoiceDeleted extends AbstractService
return $this;
}
private function triggeredActions(): self
{
if($this->invoice->quote){
$this->invoice->quote->invoice_id = null;
$this->invoice->quote->status_id = Quote::STATUS_SENT;
$this->invoice->pushQuietly();
}
return $this;
}
}

View File

@ -31,46 +31,44 @@ class StorecoveTest extends TestCase
$this->markTestSkipped("do not run in CI");
}
public function testCreateLegalEntity()
{
// public function testCreateLegalEntity()
// {
$data = [
'acts_as_receiver' => true,
'acts_as_sender' => true,
'advertisements' => ['invoice'],
'city' => $this->company->settings->city,
'country' => 'DE',
'county' => $this->company->settings->state,
'line1' => $this->company->settings->address1,
'line2' => $this->company->settings->address2,
'party_name' => $this->company->present()->name(),
'tax_registered' => true,
'tenant_id' => $this->company->company_key,
'zip' => $this->company->settings->postal_code,
'peppol_identifiers' => [
'scheme' => 'DE:VAT',
'id' => 'DE:VAT'
],
];
// $data = [
// 'acts_as_receiver' => true,
// 'acts_as_sender' => true,
// 'advertisements' => ['invoice'],
// 'city' => $this->company->settings->city,
// 'country' => 'DE',
// 'county' => $this->company->settings->state,
// 'line1' => $this->company->settings->address1,
// 'line2' => $this->company->settings->address2,
// 'party_name' => $this->company->present()->name(),
// 'tax_registered' => true,
// 'tenant_id' => $this->company->company_key,
// 'zip' => $this->company->settings->postal_code,
// 'peppol_identifiers' => [
// 'scheme' => 'DE:VAT',
// 'id' => 'DE:VAT'
// ],
// ];
$sc = new \App\Services\EDocument\Gateway\Storecove\Storecove();
$r = $sc->createLegalEntity($data, $this->company);
// $sc = new \App\Services\EDocument\Gateway\Storecove\Storecove();
// $r = $sc->createLegalEntity($data, $this->company);
$this->assertIsArray($r);
// $this->assertIsArray($r);
}
// }
public function tesXAddPeppolIdentifier()
{
// public function testAddPeppolIdentifier()
// {
$sc = new \App\Services\EDocument\Gateway\Storecove\Storecove();
$r = $sc->addIdentifier(290868, "DE923356489", "DE:VAT");
// $sc = new \App\Services\EDocument\Gateway\Storecove\Storecove();
// $r = $sc->addIdentifier(290868, "DE923356489", "DE:VAT");
// nlog($r->body());
// $this->assertIsArray($r);
nlog($r);
// nlog($r);
}
// }
// public function testUpdateLegalEntity()
// {
@ -91,7 +89,6 @@ class StorecoveTest extends TestCase
public function testGetLegalEntity()
{
$sc = new \App\Services\EDocument\Gateway\Storecove\Storecove();
$r = $sc->getLegalEntity(290868);