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

Merge pull request #9191 from turbo124/v5-develop

Prevent reminder fees being taxes in DE region
This commit is contained in:
David Bomba 2024-01-24 14:46:49 +11:00 committed by GitHub
commit f325370986
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 92 additions and 35 deletions

View File

@ -890,6 +890,40 @@ class CheckData extends Command
$this->logMessage("Fixing country for # {$client->id}");
});
Client::query()->whereNull("settings->currency_id")->cursor()->each(function ($client){
$settings = $client->settings;
$settings->currency_id = (string)$client->company->settings->currency_id;
$client->settings = $settings;
$client->saveQuietly();
$this->logMessage("Fixing currency_id for # {$client->id}");
});
Payment::withTrashed()->where('exchange_rate', 0)->cursor()->each(function ($payment){
$payment->exchange_rate = 1;
$payment->saveQuietly();
$this->logMessage("Fixing exchange rate for # {$payment->id}");
});
Payment::withTrashed()
->whereHas("client", function ($query) {
$query->whereColumn("settings->currency_id", "!=", "payments.currency_id");
})
->cursor()
->each(function ($p) {
$p->currency_id = $p->client->settings->currency_id;
$p->saveQuietly();
$this->logMessage("Fixing currency for # {$p->id}");
});
}
}

View File

@ -319,6 +319,7 @@ class BaseRule implements RuleInterface
Product::PRODUCT_TYPE_EXEMPT => $this->taxExempt($item),
Product::PRODUCT_TYPE_REDUCED_TAX => $this->taxReduced($item),
Product::PRODUCT_TYPE_OVERRIDE_TAX => $this->override($item),
Product::PRODUCT_TYPE_ZERO_RATED => $this->zeroRated($item),
default => $this->defaultForeign(),
};
@ -327,6 +328,14 @@ class BaseRule implements RuleInterface
}
public function zeroRated($item): self
{
$this->tax_rate1 = 0;
$this->tax_name1 = ctrans('texts.zero_rated');
return $this;
}
public function taxByType(mixed $type): self
{
return $this;

View File

@ -11,6 +11,7 @@
namespace App\DataMapper\Tax\DE;
use App\DataMapper\InvoiceItem;
use App\DataMapper\Tax\BaseRule;
use App\DataMapper\Tax\RuleInterface;
use App\Models\Product;
@ -63,7 +64,7 @@ class Rule extends BaseRule implements RuleInterface
public function taxByType($item): self
{
if ($this->client->is_tax_exempt || !property_exists($item, 'tax_id')) {
if ($this->client->is_tax_exempt || !property_exists($item, 'tax_id') || (isset($item->type_id) && $item->type_id == '5')) {
return $this->taxExempt($item);
}

View File

@ -399,8 +399,7 @@ class QuoteController extends BaseController
$quote->service()
->triggeredActions($request);
// ->deletePdf();
event(new QuoteWasUpdated($quote, $quote->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
return $this->itemResponse($quote);

View File

@ -51,10 +51,6 @@ class NinjaMailerJob implements ShouldQueue
public $deleteWhenMissingModels = true;
public $nmo;
public $override;
/** @var null|\App\Models\Company $company **/
public ?Company $company;
@ -67,11 +63,8 @@ class NinjaMailerJob implements ShouldQueue
protected $client_mailgun_domain = false;
public function __construct(NinjaMailerObject $nmo, bool $override = false)
public function __construct(public ?NinjaMailerObject $nmo, public bool $override = false)
{
$this->nmo = $nmo;
$this->override = $override;
}
public function backoff()
@ -106,7 +99,10 @@ class NinjaMailerJob implements ShouldQueue
}
$this->nmo->mailable->replyTo($this->nmo->settings->reply_to_email, $reply_to_name);
} else {
}elseif(isset($this->nmo->invitation->user)){
$this->nmo->mailable->replyTo($this->nmo->invitation->user->email, $this->nmo->invitation->user->present()->name());
}
else {
$this->nmo->mailable->replyTo($this->company->owner()->email, $this->company->owner()->present()->name());
}

View File

@ -16,6 +16,8 @@ namespace App\Jobs\Mail;
*/
class NinjaMailerObject
{
/* @var Illuminate\Mail\Mailable */
public $mailable;
/* @var Company $company */
@ -32,7 +34,7 @@ class NinjaMailerObject
/* Variable for cascading notifications */
public $entity_string = false;
/* @var bool | App\Models\InvoiceInvitation | App\Models\QuoteInvitation | App\Models\CreditInvitation | App\Models\RecurringInvoiceInvitation | App\Models\PurchaseOrderInvitation $invitation*/
/* @var App\Models\InvoiceInvitation | App\Models\QuoteInvitation | App\Models\CreditInvitation | App\Models\RecurringInvoiceInvitation | App\Models\PurchaseOrderInvitation | \bool $invitation*/
public $invitation = false;
public $template = false;

View File

@ -69,8 +69,11 @@ class UpdateOrCreateProduct implements ShouldQueue
* we do NOT update the product details this short block we
* check for the presence of a task_id and/or expense_id
*/
$expense_count = count(array_column((array) $this->products, 'expense_id'));
$task_count = count(array_column((array) $this->products, 'task_id'));
// $expense_count = count(array_column((array) $this->products, 'expense_id'));
// $task_count = count(array_column((array) $this->products, 'task_id'));
$task_count = implode("", array_column((array) $this->products, 'task_id'));
$expense_count = implode("", array_column((array) $this->products, 'expense_id'));
if ($task_count >= 1 || $expense_count >= 1) {
return;

View File

@ -44,7 +44,7 @@ use Laracasts\Presenter\PresentableTrait;
* @property string|null $po_number
* @property string|null $date
* @property string|null $last_sent_date
* @property string|null $due_date
* @property string|null|Carbon $due_date
* @property string|null $next_send_date
* @property bool $is_deleted
* @property object|null $line_items
@ -164,7 +164,7 @@ class Quote extends BaseModel
protected $casts = [
// 'date' => 'date:Y-m-d',
// 'due_date' => 'date:Y-m-d',
'due_date' => 'date:Y-m-d',
// 'partial_due_date' => 'date:Y-m-d',
'line_items' => 'object',
'backup' => 'object',
@ -197,7 +197,7 @@ class Quote extends BaseModel
public function getDueDateAttribute($value)
{
return $this->dateMutator($value);
return $value ? $this->dateMutator($value) : null;
}
public function getPartialDueDateAttribute($value)

View File

@ -437,7 +437,7 @@ class PayPalPPCPPaymentDriver extends BaseDriver
if($shipping = $this->getShippingAddress()) {
$order['purchase_units'][0] = $shipping;
$order['purchase_units'][0]["shipping"] = $shipping;
}
$r = $this->gatewayRequest('/v2/checkout/orders', 'post', $order);
@ -465,8 +465,7 @@ class PayPalPPCPPaymentDriver extends BaseDriver
{
return $this->company_gateway->require_shipping_address ?
[
"shipping" => [
"address" =>
"address" =>
[
"address_line_1" => $this->client->shipping_address1,
"address_line_2" => $this->client->shipping_address2,
@ -475,8 +474,8 @@ class PayPalPPCPPaymentDriver extends BaseDriver
"postal_code" => $this->client->shipping_postal_code,
"country_code" => $this->client->present()->shipping_country_code(),
],
]
]
: null;
}

View File

@ -208,9 +208,22 @@ class EmailDefaults
*/
private function setReplyTo(): self
{
$reply_to_email = str_contains($this->email->email_object->settings->reply_to_email, "@") ? $this->email->email_object->settings->reply_to_email : $this->email->company->owner()->email;
$reply_to_email = $this->email->company->owner()->email;
$reply_to_name = $this->email->company->owner()->present()->name();
$reply_to_name = strlen($this->email->email_object->settings->reply_to_name) > 3 ? $this->email->email_object->settings->reply_to_name : $this->email->company->owner()->present()->name();
if(str_contains($this->email->email_object->settings->reply_to_email, "@")){
$reply_to_email = $this->email->email_object->settings->reply_to_email;
}
elseif(isset($this->email->email_object->invitation->user)) {
$reply_to_email = $this->email->email_object->invitation->user->email;
}
if(strlen($this->email->email_object->settings->reply_to_name) > 3) {
$reply_to_name =$this->email->email_object->settings->reply_to_name;
}
elseif(isset($this->email->email_object->invitation->user)) {
$reply_to_name = $this->email->email_object->invitation->user->present()->name();
}
$this->email->email_object->reply_to = array_merge($this->email->email_object->reply_to, [new Address($reply_to_email, $reply_to_name)]);

View File

@ -42,7 +42,6 @@ class MarkSent
->service()
->setStatus(Quote::STATUS_SENT)
->applyNumber()
// ->deletePdf()
->save();
event(new QuoteWasMarkedSent($this->quote, $this->quote->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));

View File

@ -28,20 +28,22 @@ return new class extends Migration
$line_items = $invoice->line_items;
foreach ($line_items as $key => $item)
if(is_array($line_items))
{
if($product = Product::where('company_id', $invoice->company_id)->where('product_key', $item->product_key)->where('cost', '>', 0)->first())
foreach ($line_items as $key => $item)
{
if((property_exists($item, 'product_cost') && $item->product_cost == 0) || !property_exists($item, 'product_cost'))
$line_items[$key]->product_cost = (float)$product->cost;
if($product = Product::where('company_id', $invoice->company_id)->where('product_key', $item->product_key)->where('cost', '>', 0)->first())
{
if((property_exists($item, 'product_cost') && $item->product_cost == 0) || !property_exists($item, 'product_cost'))
$line_items[$key]->product_cost = (float)$product->cost;
}
}
$invoice->line_items = $line_items;
$invoice->saveQuietly();
}
$invoice->line_items = $line_items;
$invoice->saveQuietly();
});
}