mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-08 12:12:48 +01:00
Merge pull request #9842 from turbo124/v5-develop
Fixes for bank transaction filters / number formatting
This commit is contained in:
commit
4b73672861
2
.env.ci
2
.env.ci
@ -24,4 +24,4 @@ PHANTOMJS_PDF_GENERATION=false
|
||||
CACHE_DRIVER=redis
|
||||
QUEUE_CONNECTION=redis
|
||||
SESSION_DRIVER=redis
|
||||
PDF_GENERATOR=hosted_ninja
|
||||
PDF_GENERATOR=snappdf
|
@ -17,7 +17,7 @@ class TaxModel
|
||||
public string $seller_subregion = 'CA';
|
||||
|
||||
/** @var string $version */
|
||||
public string $version = 'alpha';
|
||||
public string $version = 'beta';
|
||||
|
||||
/** @var object $regions */
|
||||
public object $regions;
|
||||
@ -28,17 +28,40 @@ class TaxModel
|
||||
* @param TaxModel $model
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(public ?TaxModel $model = null)
|
||||
public function __construct(public mixed $model = null)
|
||||
{
|
||||
|
||||
if(!$this->model) {
|
||||
if(!$model) {
|
||||
$this->regions = $this->init();
|
||||
} else {
|
||||
$this->regions = $model;
|
||||
|
||||
//@phpstan-ignore-next-line
|
||||
foreach($model as $key => $value) {
|
||||
$this->{$key} = $value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$this->migrate();
|
||||
}
|
||||
|
||||
public function migrate(): self
|
||||
{
|
||||
|
||||
if($this->version == 'alpha')
|
||||
{
|
||||
$this->regions->EU->subregions->PL = new \stdClass();
|
||||
$this->regions->EU->subregions->PL->tax_rate = 23;
|
||||
$this->regions->EU->subregions->PL->tax_name = 'VAT';
|
||||
$this->regions->EU->subregions->PL->reduced_tax_rate = 8;
|
||||
$this->regions->EU->subregions->PL->apply_tax = false;
|
||||
|
||||
$this->version = 'beta';
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the rules and builds any required data.
|
||||
*
|
||||
|
@ -155,11 +155,13 @@ class BankTransactionFilters extends QueryFilters
|
||||
$dir = ($sort_col[1] == 'asc') ? 'asc' : 'desc';
|
||||
|
||||
if ($sort_col[0] == 'deposit') {
|
||||
return $this->builder->where('base_type', 'CREDIT')->orderBy('amount', $dir);
|
||||
return $this->builder->orderByRaw("(CASE WHEN base_type = 'CREDIT' THEN amount END) $dir")->orderBy('amount', $dir);
|
||||
// return $this->builder->where('base_type', 'CREDIT')->orderBy('amount', $dir);
|
||||
}
|
||||
|
||||
if ($sort_col[0] == 'withdrawal') {
|
||||
return $this->builder->where('base_type', 'DEBIT')->orderBy('amount', $dir);
|
||||
return $this->builder->orderByRaw("(CASE WHEN base_type = 'DEBIT' THEN amount END) $dir")->orderBy('amount', $dir);
|
||||
// return $this->builder->where('base_type', 'DEBIT')->orderBy('amount', $dir);
|
||||
}
|
||||
|
||||
if ($sort_col[0] == 'status') {
|
||||
|
@ -41,7 +41,7 @@ class ClientFilters extends QueryFilters
|
||||
*/
|
||||
public function balance(string $balance = ''): Builder
|
||||
{
|
||||
if (strlen($balance) == 0) {
|
||||
if (strlen($balance) == 0 || count(explode(":", $balance)) < 2) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
|
@ -11,16 +11,17 @@
|
||||
|
||||
namespace App\Helpers\Invoice;
|
||||
|
||||
use App\DataMapper\BaseSettings;
|
||||
use App\DataMapper\InvoiceItem;
|
||||
use App\DataMapper\Tax\RuleInterface;
|
||||
use App\Models\Quote;
|
||||
use App\Utils\Number;
|
||||
use App\Models\Client;
|
||||
use App\Models\Credit;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\PurchaseOrder;
|
||||
use App\Models\Quote;
|
||||
use App\Models\RecurringInvoice;
|
||||
use App\Models\RecurringQuote;
|
||||
use App\DataMapper\InvoiceItem;
|
||||
use App\DataMapper\BaseSettings;
|
||||
use App\Models\RecurringInvoice;
|
||||
use App\DataMapper\Tax\RuleInterface;
|
||||
use App\Utils\Traits\NumberFormatter;
|
||||
|
||||
class InvoiceItemSum
|
||||
@ -313,7 +314,7 @@ class InvoiceItemSum
|
||||
|
||||
$key = str_replace(' ', '', $tax_name.$tax_rate);
|
||||
|
||||
$group_tax = ['key' => $key, 'total' => $tax_total, 'tax_name' => $tax_name.' '.floatval($tax_rate).'%'];
|
||||
$group_tax = ['key' => $key, 'total' => $tax_total, 'tax_name' => $tax_name.' '.Number::formatValueNoTrailingZeroes(floatval($tax_rate), $this->client).'%'];
|
||||
|
||||
$this->tax_collection->push(collect($group_tax));
|
||||
}
|
||||
|
@ -11,14 +11,15 @@
|
||||
|
||||
namespace App\Helpers\Invoice;
|
||||
|
||||
use App\DataMapper\Tax\RuleInterface;
|
||||
use App\Models\Quote;
|
||||
use App\Utils\Number;
|
||||
use App\Models\Client;
|
||||
use App\Models\Credit;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\PurchaseOrder;
|
||||
use App\Models\Quote;
|
||||
use App\Models\RecurringInvoice;
|
||||
use App\Models\RecurringQuote;
|
||||
use App\Models\RecurringInvoice;
|
||||
use App\DataMapper\Tax\RuleInterface;
|
||||
use App\Utils\Traits\NumberFormatter;
|
||||
|
||||
class InvoiceItemSumInclusive
|
||||
@ -265,7 +266,7 @@ class InvoiceItemSumInclusive
|
||||
|
||||
$key = str_replace(' ', '', $tax_name.$tax_rate);
|
||||
|
||||
$group_tax = ['key' => $key, 'total' => $tax_total, 'tax_name' => $tax_name.' '.$tax_rate.'%'];
|
||||
$group_tax = ['key' => $key, 'total' => $tax_total, 'tax_name' => $tax_name.' '.Number::formatValueNoTrailingZeroes(floatval($tax_rate), $this->client).'%'];
|
||||
|
||||
$this->tax_collection->push(collect($group_tax));
|
||||
}
|
||||
|
@ -131,7 +131,7 @@ class InvoiceSum
|
||||
$tax += $this->getSurchargeTaxTotalForKey($this->invoice->tax_name1, $this->invoice->tax_rate1);
|
||||
|
||||
$this->total_taxes += $tax;
|
||||
$this->total_tax_map[] = ['name' => $this->invoice->tax_name1.' '.floatval($this->invoice->tax_rate1).'%', 'total' => $tax];
|
||||
$this->total_tax_map[] = ['name' => $this->invoice->tax_name1.' '.Number::formatValueNoTrailingZeroes(floatval($this->invoice->tax_rate1), $this->invoice->client).'%', 'total' => $tax];
|
||||
}
|
||||
|
||||
if (is_string($this->invoice->tax_name2) && strlen($this->invoice->tax_name2) >= 2) {
|
||||
@ -139,7 +139,7 @@ class InvoiceSum
|
||||
$tax += $this->getSurchargeTaxTotalForKey($this->invoice->tax_name2, $this->invoice->tax_rate2);
|
||||
|
||||
$this->total_taxes += $tax;
|
||||
$this->total_tax_map[] = ['name' => $this->invoice->tax_name2.' '.floatval($this->invoice->tax_rate2).'%', 'total' => $tax];
|
||||
$this->total_tax_map[] = ['name' => $this->invoice->tax_name2.' '.Number::formatValueNoTrailingZeroes(floatval($this->invoice->tax_rate2), $this->invoice->client).'%', 'total' => $tax];
|
||||
}
|
||||
|
||||
if (is_string($this->invoice->tax_name3) && strlen($this->invoice->tax_name3) >= 2) {
|
||||
@ -147,7 +147,7 @@ class InvoiceSum
|
||||
$tax += $this->getSurchargeTaxTotalForKey($this->invoice->tax_name3, $this->invoice->tax_rate3);
|
||||
|
||||
$this->total_taxes += $tax;
|
||||
$this->total_tax_map[] = ['name' => $this->invoice->tax_name3.' '.floatval($this->invoice->tax_rate3).'%', 'total' => $tax];
|
||||
$this->total_tax_map[] = ['name' => $this->invoice->tax_name3.' '.Number::formatValueNoTrailingZeroes(floatval($this->invoice->tax_rate3), $this->invoice->client).'%', 'total' => $tax];
|
||||
}
|
||||
|
||||
return $this;
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace App\Helpers\Invoice;
|
||||
|
||||
use App\Models\Quote;
|
||||
use App\Utils\Number;
|
||||
use App\Models\Credit;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\PurchaseOrder;
|
||||
@ -157,19 +158,19 @@ class InvoiceSumInclusive
|
||||
$tax = $this->calcInclusiveLineTax($this->invoice->tax_rate1, $amount);
|
||||
$this->total_taxes += $tax;
|
||||
|
||||
$this->total_tax_map[] = ['name' => $this->invoice->tax_name1.' '.floatval($this->invoice->tax_rate1).'%', 'total' => $tax];
|
||||
$this->total_tax_map[] = ['name' => $this->invoice->tax_name1.' '.Number::formatValueNoTrailingZeroes(floatval($this->invoice->tax_rate1), $this->invoice->client).'%', 'total' => $tax];
|
||||
}
|
||||
|
||||
if (is_string($this->invoice->tax_name2) && strlen($this->invoice->tax_name2) > 1) {
|
||||
$tax = $this->calcInclusiveLineTax($this->invoice->tax_rate2, $amount);
|
||||
$this->total_taxes += $tax;
|
||||
$this->total_tax_map[] = ['name' => $this->invoice->tax_name2.' '.floatval($this->invoice->tax_rate2).'%', 'total' => $tax];
|
||||
$this->total_tax_map[] = ['name' => $this->invoice->tax_name2.' '.Number::formatValueNoTrailingZeroes(floatval($this->invoice->tax_rate2), $this->invoice->client).'%', 'total' => $tax];
|
||||
}
|
||||
|
||||
if (is_string($this->invoice->tax_name3) && strlen($this->invoice->tax_name3) > 1) {
|
||||
$tax = $this->calcInclusiveLineTax($this->invoice->tax_rate3, $amount);
|
||||
$this->total_taxes += $tax;
|
||||
$this->total_tax_map[] = ['name' => $this->invoice->tax_name3.' '.floatval($this->invoice->tax_rate3).'%', 'total' => $tax];
|
||||
$this->total_tax_map[] = ['name' => $this->invoice->tax_name3.' '.Number::formatValueNoTrailingZeroes(floatval($this->invoice->tax_rate3), $this->invoice->client).'%', 'total' => $tax];
|
||||
}
|
||||
|
||||
return $this;
|
||||
|
@ -35,7 +35,7 @@ class MailgunWebhookController extends BaseController
|
||||
}
|
||||
|
||||
if(\hash_equals(\hash_hmac('sha256', $input['signature']['timestamp'] . $input['signature']['token'], config('services.mailgun.webhook_signing_key')), $input['signature']['signature'])) {
|
||||
ProcessMailgunWebhook::dispatch($request->all())->delay(10);
|
||||
ProcessMailgunWebhook::dispatch($request->all())->delay(rand(2,10));
|
||||
}
|
||||
|
||||
return response()->json(['message' => 'Success.'], 200);
|
||||
|
@ -65,6 +65,9 @@ class StoreCreditRequest extends Request
|
||||
|
||||
$rules['client_id'] = 'required|exists:clients,id,company_id,'.$user->company()->id;
|
||||
|
||||
$rules['invitations'] = 'sometimes|bail|array';
|
||||
$rules['invitations.*.client_contact_id'] = 'bail|required|distinct';
|
||||
|
||||
// $rules['number'] = new UniqueCreditNumberRule($this->all());
|
||||
$rules['number'] = ['nullable', Rule::unique('credits')->where('company_id', $user->company()->id)];
|
||||
$rules['discount'] = 'sometimes|numeric|max:99999999999999';
|
||||
|
@ -66,6 +66,9 @@ class UpdateCreditRequest extends Request
|
||||
|
||||
$rules['client_id'] = ['bail', 'sometimes',Rule::in([$this->credit->client_id])];
|
||||
|
||||
$rules['invitations'] = 'sometimes|bail|array';
|
||||
$rules['invitations.*.client_contact_id'] = 'bail|required|distinct';
|
||||
|
||||
$rules['line_items'] = 'array';
|
||||
|
||||
$rules['date'] = 'bail|sometimes|date:Y-m-d';
|
||||
|
@ -38,11 +38,14 @@ class StoreInvoiceRequest extends Request
|
||||
|
||||
public function rules()
|
||||
{
|
||||
$rules = [];
|
||||
|
||||
/** @var \App\Models\User $user */
|
||||
$user = auth()->user();
|
||||
|
||||
$rules = [];
|
||||
|
||||
$rules['client_id'] = ['required', 'bail', Rule::exists('clients', 'id')->where('company_id', $user->company()->id)->where('is_deleted', 0)];
|
||||
|
||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||
$rules['documents.*'] = $this->fileValidation();
|
||||
} elseif ($this->file('documents')) {
|
||||
@ -57,16 +60,16 @@ class StoreInvoiceRequest extends Request
|
||||
$rules['file'] = $this->fileValidation();
|
||||
}
|
||||
|
||||
$rules['client_id'] = 'bail|required|exists:clients,id,company_id,'.$user->company()->id.',is_deleted,0';
|
||||
|
||||
$rules['invitations.*.client_contact_id'] = 'distinct';
|
||||
|
||||
$rules['number'] = ['bail', 'nullable', Rule::unique('invoices')->where('company_id', $user->company()->id)];
|
||||
|
||||
$rules['invitations'] = 'sometimes|bail|array';
|
||||
$rules['invitations.*.client_contact_id'] = 'bail|required|distinct';
|
||||
|
||||
$rules['project_id'] = ['bail', 'sometimes', new ValidProjectForClient($this->all())];
|
||||
$rules['is_amount_discount'] = ['boolean'];
|
||||
|
||||
$rules['date'] = 'bail|sometimes|date:Y-m-d';
|
||||
$rules['due_date'] = ['bail', 'sometimes', 'nullable', 'after:partial_due_date', Rule::requiredIf(fn () => strlen($this->partial_due_date ?? '') > 1), 'date'];
|
||||
|
||||
$rules['line_items'] = 'array';
|
||||
$rules['discount'] = 'sometimes|numeric|max:99999999999999';
|
||||
@ -79,18 +82,17 @@ class StoreInvoiceRequest extends Request
|
||||
$rules['exchange_rate'] = 'bail|sometimes|numeric';
|
||||
$rules['partial'] = 'bail|sometimes|nullable|numeric|gte:0';
|
||||
$rules['partial_due_date'] = ['bail', 'sometimes', 'nullable', 'exclude_if:partial,0', 'date', 'before:due_date', 'after_or_equal:date'];
|
||||
$rules['due_date'] = ['bail', 'sometimes', 'nullable', 'after:partial_due_date', Rule::requiredIf(fn () => strlen($this->partial_due_date ?? '') > 1), 'date'];
|
||||
|
||||
$rules['amount'] = ['sometimes', 'bail', 'numeric', 'max:99999999999999'];
|
||||
|
||||
// $rules['amount'] = ['sometimes', 'bail', 'max:99999999999999'];
|
||||
// $rules['due_date'] = ['bail', 'sometimes', 'nullable', 'after:partial_due_date', Rule::requiredIf(fn () => strlen($this->partial_due_date) > 1), 'date'];
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
public function prepareForValidation()
|
||||
{
|
||||
|
||||
/** @var \App\Models\User $user */
|
||||
$user = auth()->user();
|
||||
|
||||
$input = $this->all();
|
||||
|
||||
$input = $this->decodePrimaryKeys($input);
|
||||
@ -102,24 +104,24 @@ class StoreInvoiceRequest extends Request
|
||||
$input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : [];
|
||||
$input['amount'] = $this->entityTotalAmount($input['line_items']);
|
||||
}
|
||||
|
||||
if(isset($input['partial']) && $input['partial'] == 0) {
|
||||
$input['partial_due_date'] = null;
|
||||
}
|
||||
|
||||
if (array_key_exists('tax_rate1', $input) && is_null($input['tax_rate1'])) {
|
||||
if (!isset($input['tax_rate1'])) {
|
||||
$input['tax_rate1'] = 0;
|
||||
}
|
||||
if (array_key_exists('tax_rate2', $input) && is_null($input['tax_rate2'])) {
|
||||
if (!isset($input['tax_rate2'])) {
|
||||
$input['tax_rate2'] = 0;
|
||||
}
|
||||
if (array_key_exists('tax_rate3', $input) && is_null($input['tax_rate3'])) {
|
||||
if (!isset($input['tax_rate3'])) {
|
||||
$input['tax_rate3'] = 0;
|
||||
}
|
||||
if (array_key_exists('exchange_rate', $input) && is_null($input['exchange_rate'])) {
|
||||
$input['exchange_rate'] = 1;
|
||||
}
|
||||
|
||||
if(!isset($input['date'])) {
|
||||
$input['date'] = now()->addSeconds($user->company()->utc_offset())->format('Y-m-d');
|
||||
}
|
||||
//handles edge case where we need for force set the due date of the invoice.
|
||||
if((isset($input['partial_due_date']) && strlen($input['partial_due_date']) > 1) && (!array_key_exists('due_date', $input) || (empty($input['due_date']) && empty($this->invoice->due_date)))) {
|
||||
$client = \App\Models\Client::withTrashed()->find($input['client_id']);
|
||||
|
@ -67,6 +67,9 @@ class UpdateInvoiceRequest extends Request
|
||||
$rules['client_id'] = ['bail', 'sometimes', Rule::in([$this->invoice->client_id])];
|
||||
$rules['line_items'] = 'array';
|
||||
|
||||
$rules['invitations'] = 'sometimes|bail|array';
|
||||
$rules['invitations.*.client_contact_id'] = 'bail|required|distinct';
|
||||
|
||||
$rules['discount'] = 'sometimes|numeric|max:99999999999999';
|
||||
$rules['project_id'] = ['bail', 'sometimes', new ValidProjectForClient($this->all())];
|
||||
$rules['tax_rate1'] = 'bail|sometimes|numeric';
|
||||
|
@ -50,6 +50,10 @@ class StorePurchaseOrderRequest extends Request
|
||||
|
||||
$rules['number'] = ['nullable', Rule::unique('purchase_orders')->where('company_id', $user->company()->id)];
|
||||
|
||||
|
||||
$rules['invitations'] = 'sometimes|bail|array';
|
||||
$rules['invitations.*.vendor_contact_id'] = 'bail|required|distinct';
|
||||
|
||||
$rules['discount'] = 'sometimes|numeric|max:99999999999999';
|
||||
$rules['is_amount_discount'] = ['boolean'];
|
||||
$rules['line_items'] = 'array';
|
||||
|
@ -53,6 +53,9 @@ class UpdatePurchaseOrderRequest extends Request
|
||||
|
||||
$rules['line_items'] = 'array';
|
||||
|
||||
$rules['invitations'] = 'sometimes|bail|array';
|
||||
$rules['invitations.*.vendor_contact_id'] = 'bail|required|distinct';
|
||||
|
||||
$rules['discount'] = 'sometimes|numeric|max:99999999999999';
|
||||
$rules['is_amount_discount'] = ['boolean'];
|
||||
|
||||
|
@ -11,12 +11,13 @@
|
||||
|
||||
namespace App\Http\Requests\Quote;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Http\ValidationRules\Quote\UniqueQuoteNumberRule;
|
||||
use App\Models\Quote;
|
||||
use App\Utils\Traits\CleanLineItems;
|
||||
use App\Http\Requests\Request;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Validation\Rule;
|
||||
use App\Utils\Traits\CleanLineItems;
|
||||
use App\Http\ValidationRules\Quote\UniqueQuoteNumberRule;
|
||||
use App\Http\ValidationRules\Project\ValidProjectForClient;
|
||||
|
||||
class StoreQuoteRequest extends Request
|
||||
{
|
||||
@ -43,7 +44,7 @@ class StoreQuoteRequest extends Request
|
||||
|
||||
$rules = [];
|
||||
|
||||
$rules['client_id'] = ['required', 'bail', Rule::exists('clients', 'id')->where('company_id', $user->company()->id)];
|
||||
$rules['client_id'] = ['required', 'bail', Rule::exists('clients', 'id')->where('company_id', $user->company()->id)->where('is_deleted',0)];
|
||||
|
||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||
$rules['documents.*'] = $this->fileValidation();
|
||||
@ -59,15 +60,28 @@ class StoreQuoteRequest extends Request
|
||||
$rules['file'] = $this->fileValidation();
|
||||
}
|
||||
|
||||
$rules['number'] = ['nullable', Rule::unique('quotes')->where('company_id', $user->company()->id)];
|
||||
$rules['number'] = ['bail','nullable', Rule::unique('quotes')->where('company_id', $user->company()->id)];
|
||||
|
||||
$rules['invitations'] = 'sometimes|bail|array';
|
||||
$rules['invitations.*.client_contact_id'] = 'bail|required|distinct';
|
||||
|
||||
$rules['project_id'] = ['bail', 'sometimes', new ValidProjectForClient($this->all())];
|
||||
$rules['is_amount_discount'] = ['boolean'];
|
||||
$rules['date'] = 'bail|sometimes|date:Y-m-d';
|
||||
$rules['due_date'] = ['bail', 'sometimes', 'nullable', 'after:partial_due_date', Rule::requiredIf(fn () => strlen($this->partial_due_date ?? '') > 1), 'date'];
|
||||
$rules['line_items'] = 'array';
|
||||
|
||||
$rules['discount'] = 'sometimes|numeric|max:99999999999999';
|
||||
$rules['is_amount_discount'] = ['boolean'];
|
||||
$rules['tax_rate1'] = 'bail|sometimes|numeric';
|
||||
$rules['tax_rate2'] = 'bail|sometimes|numeric';
|
||||
$rules['tax_rate3'] = 'bail|sometimes|numeric';
|
||||
$rules['tax_name1'] = 'bail|sometimes|string|nullable';
|
||||
$rules['tax_name2'] = 'bail|sometimes|string|nullable';
|
||||
$rules['tax_name3'] = 'bail|sometimes|string|nullable';
|
||||
$rules['exchange_rate'] = 'bail|sometimes|numeric';
|
||||
$rules['line_items'] = 'array';
|
||||
$rules['date'] = 'bail|sometimes|date:Y-m-d';
|
||||
|
||||
$rules['partial'] = 'bail|sometimes|nullable|numeric|gte:0';
|
||||
$rules['partial_due_date'] = ['bail', 'sometimes', 'nullable', 'exclude_if:partial,0', 'date', 'before:due_date', 'after_or_equal:date'];
|
||||
$rules['due_date'] = ['bail', 'sometimes', 'nullable', 'after:partial_due_date', Rule::requiredIf(fn () => strlen($this->partial_due_date ?? '') > 1), 'date'];
|
||||
$rules['amount'] = ['sometimes', 'bail', 'numeric', 'max:99999999999999'];
|
||||
|
||||
return $rules;
|
||||
@ -89,19 +103,24 @@ class StoreQuoteRequest extends Request
|
||||
$input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : [];
|
||||
$input['amount'] = $this->entityTotalAmount($input['line_items']);
|
||||
}
|
||||
|
||||
if (array_key_exists('exchange_rate', $input) && is_null($input['exchange_rate'])) {
|
||||
$input['exchange_rate'] = 1;
|
||||
}
|
||||
|
||||
if(isset($input['partial']) && $input['partial'] == 0) {
|
||||
$input['partial_due_date'] = null;
|
||||
}
|
||||
|
||||
if (!isset($input['tax_rate1'])) {
|
||||
$input['tax_rate1'] = 0;
|
||||
}
|
||||
if (!isset($input['tax_rate2'])) {
|
||||
$input['tax_rate2'] = 0;
|
||||
}
|
||||
if (!isset($input['tax_rate3'])) {
|
||||
$input['tax_rate3'] = 0;
|
||||
}
|
||||
if (!isset($input['exchange_rate'])) {
|
||||
$input['exchange_rate'] = 1;
|
||||
}
|
||||
if(!isset($input['date'])) {
|
||||
$input['date'] = now()->addSeconds($user->company()->utc_offset())->format('Y-m-d');
|
||||
}
|
||||
|
||||
if(isset($input['partial_due_date']) && (!isset($input['due_date']) || strlen($input['due_date']) <= 1)) {
|
||||
$client = \App\Models\Client::withTrashed()->find($input['client_id']);
|
||||
$valid_days = ($client && strlen($client->getSetting('valid_until')) >= 1) ? $client->getSetting('valid_until') : 7;
|
||||
|
@ -56,6 +56,9 @@ class UpdateQuoteRequest extends Request
|
||||
$rules['file'] = $this->fileValidation();
|
||||
}
|
||||
|
||||
$rules['invitations'] = 'sometimes|bail|array';
|
||||
$rules['invitations.*.client_contact_id'] = 'bail|required|distinct';
|
||||
|
||||
$rules['number'] = ['bail', 'sometimes', 'nullable', Rule::unique('quotes')->where('company_id', $user->company()->id)->ignore($this->quote->id)];
|
||||
$rules['client_id'] = ['bail', 'sometimes', Rule::in([$this->quote->client_id])];
|
||||
$rules['line_items'] = 'array';
|
||||
|
@ -61,7 +61,8 @@ class StoreRecurringInvoiceRequest extends Request
|
||||
|
||||
$rules['client_id'] = 'required|exists:clients,id,company_id,'.$user->company()->id;
|
||||
|
||||
$rules['invitations.*.client_contact_id'] = 'distinct';
|
||||
$rules['invitations'] = 'sometimes|bail|array';
|
||||
$rules['invitations.*.client_contact_id'] = 'bail|required|distinct';
|
||||
|
||||
$rules['frequency_id'] = 'required|integer|digits_between:1,12';
|
||||
|
||||
|
@ -60,6 +60,8 @@ class UpdateRecurringInvoiceRequest extends Request
|
||||
|
||||
$rules['number'] = ['bail', 'sometimes', Rule::unique('recurring_invoices')->where('company_id', $user->company()->id)->ignore($this->recurring_invoice->id)];
|
||||
|
||||
$rules['invitations'] = 'sometimes|bail|array';
|
||||
$rules['invitations.*.client_contact_id'] = 'bail|required|distinct';
|
||||
|
||||
$rules['client_id'] = ['bail', 'sometimes', Rule::in([$this->recurring_invoice->client_id])];
|
||||
|
||||
|
@ -297,12 +297,13 @@ class NinjaMailerJob implements ShouldQueue
|
||||
$t->replace(Ninja::transformTranslations($this->nmo->settings));
|
||||
|
||||
/** Force free/trials onto specific mail driver */
|
||||
// if(Ninja::isHosted() && !$this->company->account->isPaid())
|
||||
// {
|
||||
// $this->mailer = 'mailgun';
|
||||
// $this->setHostedMailgunMailer();
|
||||
// return $this;
|
||||
// }
|
||||
|
||||
if($this->mailer == 'default' && $this->company->account->isNewHostedAccount()) {
|
||||
$this->mailer = 'mailgun';
|
||||
$this->setHostedMailgunMailer();
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
if (Ninja::isHosted() && $this->company->account->isPaid() && $this->nmo->settings->email_sending_method == 'default') {
|
||||
//check if outlook.
|
||||
@ -391,7 +392,7 @@ class NinjaMailerJob implements ShouldQueue
|
||||
$smtp_username = $company->smtp_username ?? '';
|
||||
$smtp_password = $company->smtp_password ?? '';
|
||||
$smtp_encryption = $company->smtp_encryption ?? 'tls';
|
||||
$smtp_local_domain = strlen($company->smtp_local_domain) > 2 ? $company->smtp_local_domain : null;
|
||||
$smtp_local_domain = strlen($company->smtp_local_domain ?? '') > 2 ? $company->smtp_local_domain : null;
|
||||
$smtp_verify_peer = $company->smtp_verify_peer ?? true;
|
||||
|
||||
if(strlen($smtp_host) <= 1 ||
|
||||
|
@ -181,7 +181,7 @@ class ProcessMailgunWebhook implements ShouldQueue
|
||||
$sl = $this->getSystemLog($this->request['MessageID']);
|
||||
|
||||
/** Prevents Gmail tracking from firing inappropriately */
|
||||
if($this->request['signature']['timestamp'] < $sl->log['signature']['timestamp'] + 3) {
|
||||
if(!$sl || $this->request['signature']['timestamp'] < $sl->log['signature']['timestamp'] + 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,7 @@ class CleanStaleInvoiceOrder implements ShouldQueue
|
||||
Invoice::query()
|
||||
->withTrashed()
|
||||
->where('is_proforma', 1)
|
||||
->whereBetween('created_at', [now()->subHours(1), now()->subMinutes(10)])
|
||||
->where('created_at', '<', now()->subHour())
|
||||
->cursor()
|
||||
->each(function ($invoice) use ($repo) {
|
||||
$invoice->is_proforma = false;
|
||||
|
@ -364,16 +364,19 @@ class Account extends BaseModel
|
||||
return $this->isProClient() && $this->isPaid();
|
||||
}
|
||||
|
||||
public function isNewHostedAccount()
|
||||
{
|
||||
return Ninja::isHosted() && Carbon::createFromTimestamp($this->created_at)->diffInWeeks() <= 2;
|
||||
}
|
||||
|
||||
public function isTrial(): bool
|
||||
{
|
||||
if (!Ninja::isNinja()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//@27-01-2024 - updates for logic around trials
|
||||
return !$this->plan_paid && $this->trial_started && Carbon::parse($this->trial_started)->addDays(14)->gte(now()->subHours(12));
|
||||
// $plan_details = $this->getPlanDetails();
|
||||
// return $plan_details && $plan_details['trial'];
|
||||
|
||||
}
|
||||
|
||||
public function startTrial($plan): void
|
||||
|
@ -153,7 +153,7 @@ class BrowserPay implements MethodInterface
|
||||
$this->stripe->client->company,
|
||||
);
|
||||
|
||||
return redirect()->route('client.payments.show', ['payment' => $this->stripe->encodePrimaryKey($payment->id)]);
|
||||
return redirect()->route('client.payments.show', ['payment' => $payment->hashed_id]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -160,7 +160,7 @@ class CreditCard
|
||||
}
|
||||
}
|
||||
|
||||
return redirect()->route('client.payments.show', ['payment' => $this->stripe->encodePrimaryKey($payment->id)]);
|
||||
return redirect()->route('client.payments.show', ['payment' => $payment->hashed_id]);
|
||||
}
|
||||
|
||||
public function processUnsuccessfulPayment($server_response)
|
||||
|
@ -48,6 +48,7 @@ use InvoiceNinja\EInvoice\Models\Peppol\CustomerPartyType\AccountingCustomerPart
|
||||
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\Party as PeppolParty;
|
||||
use InvoiceNinja\EInvoice\Models\Peppol\PartyIdentification;
|
||||
|
||||
class Peppol extends AbstractService
|
||||
@ -185,6 +186,8 @@ class Peppol extends AbstractService
|
||||
$this->p_invoice->TaxTotal = $this->getTotalTaxes();
|
||||
$this->p_invoice->LegalMonetaryTotal = $this->getLegalMonetaryTotal();
|
||||
|
||||
$this->countryLevelMutators();
|
||||
|
||||
// $this->p_invoice->PaymentMeans = $this->getPaymentMeans();
|
||||
|
||||
// $payeeFinancialAccount = (new PayeeFinancialAccount())
|
||||
@ -573,6 +576,8 @@ $tax_amount->amount = $this->invoice->uses_inclusive_taxes ? $this->calcInclusiv
|
||||
|
||||
$contact = new Contact();
|
||||
$contact->ElectronicMail = $this->invoice->company->owner()->email ?? 'owner@gmail.com';
|
||||
$contact->Telephone = '';
|
||||
$contact->Name = '';
|
||||
|
||||
$party->Contact = $contact;
|
||||
|
||||
@ -695,6 +700,7 @@ $tax_amount->amount = $this->invoice->uses_inclusive_taxes ? $this->calcInclusiv
|
||||
'PaymentTerms' => 7,
|
||||
];
|
||||
|
||||
//only scans for top level props
|
||||
foreach($settings as $prop => $visibility){
|
||||
|
||||
if($prop_value = PropertyResolver::resolve($this->invoice->client->e_invoice, $prop))
|
||||
@ -707,4 +713,249 @@ $tax_amount->amount = $this->invoice->uses_inclusive_taxes ? $this->calcInclusiv
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSetting(object $e_invoice, string $property_path): mixed
|
||||
{
|
||||
return PropertyResolver::resolve($e_invoice, $property_path);
|
||||
}
|
||||
|
||||
public function countryLevelMutators():self
|
||||
{
|
||||
|
||||
if(method_exists($this, $this->invoice->company->country()->iso_3166_2))
|
||||
$this->{$this->invoice->company->country()->iso_3166_2}();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function DE(): self
|
||||
{
|
||||
// accountingsupplierparty.party.contact MUST be set - Name / Telephone / Electronic Mail
|
||||
// this is forced by default.
|
||||
|
||||
// ONE payment means MUST be set
|
||||
|
||||
//
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function CH(): self
|
||||
{
|
||||
//if QR-Bill support required - then special flow required.... optional.
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function AT(): self
|
||||
{
|
||||
//special fields for sending to AT:GOV
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function AU(): self
|
||||
{
|
||||
|
||||
//if payment means are included, they must be the same `type`
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function ES(): self
|
||||
{
|
||||
|
||||
// For B2B, provide an ES:DIRE routing identifier and an ES:VAT tax identifier.
|
||||
// both sender and receiver must be an ES company;
|
||||
// you must have a "credit_transfer" PaymentMean;
|
||||
// the "dueDate" property is mandatory.
|
||||
|
||||
// For B2G, provide three ES:FACE identifiers in the routing object,
|
||||
// as well as the ES:VAT tax identifier in the accountingCustomerParty.publicIdentifiers.
|
||||
// The invoice will then be routed through the FACe network. The three required ES:FACE identifiers are as follows:
|
||||
// "routing": {
|
||||
// "eIdentifiers":[
|
||||
// {
|
||||
// "scheme": "ES:FACE",
|
||||
// "id": "L01234567",
|
||||
// "role": "ES-01-FISCAL"
|
||||
// },
|
||||
// {
|
||||
// "scheme": "ES:FACE",
|
||||
// "id": "L01234567",
|
||||
// "role": "ES-02-RECEPTOR"
|
||||
// },
|
||||
// {
|
||||
// "scheme": "ES:FACE",
|
||||
// "id": "L01234567",
|
||||
// "role": "ES-03-PAGADOR"
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function FI(): self
|
||||
{
|
||||
|
||||
// For Finvoice, provide an FI:OPID routing identifier and an FI:OVT legal identifier.
|
||||
// An FI:VAT is recommended. In many cases (depending on the sender/receiver country and the type of service/goods)
|
||||
// an FI:VAT is required. So we recommend always including this.
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function FR(): self
|
||||
{
|
||||
// When sending invoices to the French government (Chorus Pro):
|
||||
|
||||
// All invoices have to be routed to SIRET 0009:11000201100044. There is no test environment for sending to public entities.
|
||||
|
||||
// The SIRET / 0009 identifier of the final recipient is to be included in the invoice.accountingCustomerParty.publicIdentifiers array.
|
||||
|
||||
// The service code must be sent in invoice.buyerReference (deprecated) or the invoice.references array (documentType buyer_reference)
|
||||
|
||||
// The commitment number must be sent in the invoice.orderReference (deprecated) or the invoice.references array (documentType purchase_order).
|
||||
|
||||
// Invoices to companies (SIRET / 0009 or SIRENE / 0002) are routed directly to that identifier.
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function IT(): self
|
||||
{
|
||||
// IT Sender, IT Receiver, B2B/B2G
|
||||
// Provide the receiver IT:VAT and the receiver IT:CUUO (codice destinatario)
|
||||
|
||||
// IT Sender, IT Receiver, B2C
|
||||
// Provide the receiver IT:CF and the receiver IT:CUUO (codice destinatario)
|
||||
|
||||
// IT Sender, non-IT Receiver
|
||||
// Provide the receiver tax identifier and any routing identifier applicable to the receiving country (see Receiver Identifiers).
|
||||
|
||||
// non-IT Sender, IT Receiver, B2B/B2G
|
||||
// Provide the receiver IT:VAT and the receiver IT:CUUO (codice destinatario)
|
||||
|
||||
// non-IT Sender, IT Receiver, B2C
|
||||
// Provide the receiver IT:CF and an optional email. The invoice will be eReported and sent via email. Note that this cannot be a PEC email address.
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function MY(): self
|
||||
{
|
||||
//way too much to digest here, delayed.
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function NL(): self
|
||||
{
|
||||
|
||||
// When sending to public entities, the invoice.accountingSupplierParty.party.contact.email is mandatory.
|
||||
|
||||
// Dutch senders and receivers require a legal identifier. For companies, this is NL:KVK, for public entities this is NL:OINO.
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function NZ(): self
|
||||
{
|
||||
// New Zealand uses a GLN to identify businesses. In addition, when sending invoices to a New Zealand customer, make sure you include the pseudo identifier NZ:GST as their tax identifier.
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function PL(): self
|
||||
{
|
||||
|
||||
// Because using this network is not yet mandatory, the default workflow is to not use this network. Therefore, you have to force its use, as follows:
|
||||
|
||||
// "routing": {
|
||||
// "eIdentifiers": [
|
||||
// {
|
||||
// "scheme": "PL:VAT",
|
||||
// "id": "PL0101010101"
|
||||
// }
|
||||
// ],
|
||||
// "networks": [
|
||||
// {
|
||||
// "application": "pl-ksef",
|
||||
// "settings": {
|
||||
// "enabled": true
|
||||
// }
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// Note this will only work if your LegalEntity has been setup for this network.
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function RO(): self
|
||||
{
|
||||
// Because using this network is not yet mandatory, the default workflow is to not use this network. Therefore, you have to force its use, as follows:
|
||||
|
||||
// "routing": {
|
||||
// "eIdentifiers": [
|
||||
// {
|
||||
// "scheme": "RO:VAT",
|
||||
// "id": "RO010101010"
|
||||
// }
|
||||
// ],
|
||||
// "networks": [
|
||||
// {
|
||||
// "application": "ro-anaf",
|
||||
// "settings": {
|
||||
// "enabled": true
|
||||
// }
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// Note this will only work if your LegalEntity has been setup for this network.
|
||||
// The county field for a Romania address must use the ISO3166-2:RO codes, e.g. "RO-AB, RO-AR". Don’t omit the country prefix!
|
||||
// The city field for county RO-B must be SECTOR1 - SECTOR6.
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function SG(): self
|
||||
{
|
||||
//delayed - stage 2
|
||||
return $this;
|
||||
}
|
||||
|
||||
//Sweden
|
||||
private function SE(): self
|
||||
{
|
||||
// Deliver invoices to the "Svefaktura" co-operation of local Swedish service providers.
|
||||
// Routing is through the SE:ORGNR together with a network specification:
|
||||
|
||||
// "routing": {
|
||||
// "eIdentifiers": [
|
||||
// {
|
||||
// "scheme": "SE:ORGNR",
|
||||
// "id": "0012345678"
|
||||
// }
|
||||
// ],
|
||||
// "networks": [
|
||||
// {
|
||||
// "application": "svefaktura",
|
||||
// "settings": {
|
||||
// "enabled": true
|
||||
// }
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// Use of the "Svefaktura" co-operation can also be induced by specifying an operator id, as follows:
|
||||
|
||||
// "routing": {
|
||||
// "eIdentifiers": [
|
||||
// {
|
||||
// "scheme": "SE:ORGNR",
|
||||
// "id": "0012345678"
|
||||
// },
|
||||
// {
|
||||
// "scheme": "SE:OPID",
|
||||
// "id": "1234567890"
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@ -526,11 +526,11 @@ class Email implements ShouldQueue
|
||||
{
|
||||
|
||||
/** Force free/trials onto specific mail driver */
|
||||
// if(Ninja::isHosted() && !$this->company->account->isPaid()) {
|
||||
// $this->mailer = 'mailgun';
|
||||
// $this->setHostedMailgunMailer();
|
||||
// return $this;
|
||||
// }
|
||||
if($this->mailer == 'default' && $this->company->account->isNewHostedAccount()) {
|
||||
$this->mailer = 'mailgun';
|
||||
$this->setHostedMailgunMailer();
|
||||
return $this;
|
||||
}
|
||||
|
||||
if (Ninja::isHosted() && $this->company->account->isPaid() && $this->email_object->settings->email_sending_method == 'default') {
|
||||
|
||||
@ -619,7 +619,7 @@ class Email implements ShouldQueue
|
||||
$smtp_username = $company->smtp_username ?? '';
|
||||
$smtp_password = $company->smtp_password ?? '';
|
||||
$smtp_encryption = $company->smtp_encryption ?? 'tls';
|
||||
$smtp_local_domain = strlen($company->smtp_local_domain) > 2 ? $company->smtp_local_domain : null;
|
||||
$smtp_local_domain = strlen($company->smtp_local_domain ?? '') > 2 ? $company->smtp_local_domain : null;
|
||||
$smtp_verify_peer = $company->smtp_verify_peer ?? true;
|
||||
|
||||
if(strlen($smtp_host) <= 1 ||
|
||||
|
@ -739,7 +739,7 @@ class PdfBuilder
|
||||
if ($item->is_amount_discount) {
|
||||
$data[$key][$table_type.'.discount'] = $this->service->config->formatMoney($item->discount);
|
||||
} else {
|
||||
$data[$key][$table_type.'.discount'] = floatval($item->discount).'%';
|
||||
$data[$key][$table_type.'.discount'] = $this->service->config->formatValueNoTrailingZeroes(floatval($item->discount)).'%';
|
||||
}
|
||||
} else {
|
||||
$data[$key][$table_type.'.discount'] = '';
|
||||
@ -749,17 +749,17 @@ class PdfBuilder
|
||||
// but that's no longer necessary.
|
||||
|
||||
if (isset($item->tax_rate1)) {
|
||||
$data[$key][$table_type.'.tax_rate1'] = floatval($item->tax_rate1).'%';
|
||||
$data[$key][$table_type.'.tax_rate1'] = $this->service->config->formatValueNoTrailingZeroes(floatval($item->tax_rate1)).'%';
|
||||
$data[$key][$table_type.'.tax1'] = &$data[$key][$table_type.'.tax_rate1'];
|
||||
}
|
||||
|
||||
if (isset($item->tax_rate2)) {
|
||||
$data[$key][$table_type.'.tax_rate2'] = floatval($item->tax_rate2).'%';
|
||||
$data[$key][$table_type.'.tax_rate2'] = $this->service->config->formatValueNoTrailingZeroes(floatval($item->tax_rate2)).'%';
|
||||
$data[$key][$table_type.'.tax2'] = &$data[$key][$table_type.'.tax_rate2'];
|
||||
}
|
||||
|
||||
if (isset($item->tax_rate3)) {
|
||||
$data[$key][$table_type.'.tax_rate3'] = floatval($item->tax_rate3).'%';
|
||||
$data[$key][$table_type.'.tax_rate3'] = $this->service->config->formatValueNoTrailingZeroes(floatval($item->tax_rate3)).'%';
|
||||
$data[$key][$table_type.'.tax3'] = &$data[$key][$table_type.'.tax_rate3'];
|
||||
}
|
||||
|
||||
|
46
composer.lock
generated
46
composer.lock
generated
@ -535,16 +535,16 @@
|
||||
},
|
||||
{
|
||||
"name": "aws/aws-sdk-php",
|
||||
"version": "3.316.3",
|
||||
"version": "3.316.10",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/aws/aws-sdk-php.git",
|
||||
"reference": "e832e594b3c213760e067e15ef2739f77505e832"
|
||||
"reference": "eeb8df6ff6caa428e8bcd631ad2a96430900a249"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/e832e594b3c213760e067e15ef2739f77505e832",
|
||||
"reference": "e832e594b3c213760e067e15ef2739f77505e832",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/eeb8df6ff6caa428e8bcd631ad2a96430900a249",
|
||||
"reference": "eeb8df6ff6caa428e8bcd631ad2a96430900a249",
|
||||
"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.316.3"
|
||||
"source": "https://github.com/aws/aws-sdk-php/tree/3.316.10"
|
||||
},
|
||||
"time": "2024-07-12T18:07:23+00:00"
|
||||
"time": "2024-07-30T18:10:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "bacon/bacon-qr-code",
|
||||
@ -4552,16 +4552,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/framework",
|
||||
"version": "v11.18.1",
|
||||
"version": "v11.19.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/framework.git",
|
||||
"reference": "b19ba518c56852567e99fbae9321bc436c2cc5a8"
|
||||
"reference": "5e103d499e9ee5bcfc184412d034c4e516b87085"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/b19ba518c56852567e99fbae9321bc436c2cc5a8",
|
||||
"reference": "b19ba518c56852567e99fbae9321bc436c2cc5a8",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/5e103d499e9ee5bcfc184412d034c4e516b87085",
|
||||
"reference": "5e103d499e9ee5bcfc184412d034c4e516b87085",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -4754,7 +4754,7 @@
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"time": "2024-07-26T10:39:29+00:00"
|
||||
"time": "2024-07-30T15:22:41+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/pint",
|
||||
@ -16199,16 +16199,16 @@
|
||||
},
|
||||
{
|
||||
"name": "friendsofphp/php-cs-fixer",
|
||||
"version": "v3.60.0",
|
||||
"version": "v3.61.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
|
||||
"reference": "e595e4e070d17c5d42ed8c4206f630fcc5f401a4"
|
||||
"reference": "94a87189f55814e6cabca2d9a33b06de384a2ab8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/e595e4e070d17c5d42ed8c4206f630fcc5f401a4",
|
||||
"reference": "e595e4e070d17c5d42ed8c4206f630fcc5f401a4",
|
||||
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/94a87189f55814e6cabca2d9a33b06de384a2ab8",
|
||||
"reference": "94a87189f55814e6cabca2d9a33b06de384a2ab8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -16290,7 +16290,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.60.0"
|
||||
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.61.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -16298,7 +16298,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-07-25T09:26:51+00:00"
|
||||
"time": "2024-07-31T14:33:15+00:00"
|
||||
},
|
||||
{
|
||||
"name": "hamcrest/hamcrest-php",
|
||||
@ -17347,16 +17347,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "10.5.28",
|
||||
"version": "10.5.29",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "ff7fb85cdf88131b83e721fb2a327b664dbed275"
|
||||
"reference": "8e9e80872b4e8064401788ee8a32d40b4455318f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/ff7fb85cdf88131b83e721fb2a327b664dbed275",
|
||||
"reference": "ff7fb85cdf88131b83e721fb2a327b664dbed275",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/8e9e80872b4e8064401788ee8a32d40b4455318f",
|
||||
"reference": "8e9e80872b4e8064401788ee8a32d40b4455318f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -17428,7 +17428,7 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.28"
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.29"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -17444,7 +17444,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-07-18T14:54:16+00:00"
|
||||
"time": "2024-07-30T11:08:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "react/cache",
|
||||
|
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Company;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Company::whereNotNull('tax_data')
|
||||
->cursor()
|
||||
->each(function($company){
|
||||
|
||||
if($company->tax_data?->version == 'alpha')
|
||||
{
|
||||
|
||||
$company->update(['tax_data' => new \App\DataMapper\Tax\TaxModel($company->tax_data)]);
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
//
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue
Block a user