mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-06-22 16:50:56 -04:00
Updates
This commit is contained in:
commit
1adbd3907e
@ -259,10 +259,17 @@ class ExpenseExport extends BaseExport
|
|||||||
{
|
{
|
||||||
$precision = $expense->currency->precision ?? 2;
|
$precision = $expense->currency->precision ?? 2;
|
||||||
|
|
||||||
$entity['expense.net_amount'] = round($expense->amount, $precision);
|
|
||||||
|
|
||||||
if($expense->calculate_tax_by_amount) {
|
if($expense->calculate_tax_by_amount) {
|
||||||
|
|
||||||
$total_tax_amount = round($expense->tax_amount1 + $expense->tax_amount2 + $expense->tax_amount3, $precision);
|
$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 {
|
} else {
|
||||||
|
|
||||||
if($expense->uses_inclusive_taxes) {
|
if($expense->uses_inclusive_taxes) {
|
||||||
|
@ -152,22 +152,22 @@ class InvoiceFilters extends QueryFilters
|
|||||||
{
|
{
|
||||||
|
|
||||||
return $this->builder->where(function ($query) {
|
return $this->builder->where(function ($query) {
|
||||||
$query->whereIn('status_id', [Invoice::STATUS_PARTIAL, Invoice::STATUS_SENT])
|
$query->whereIn('invoices.status_id', [Invoice::STATUS_PARTIAL, Invoice::STATUS_SENT])
|
||||||
->where('is_deleted', 0)
|
->where('invoices.is_deleted', 0)
|
||||||
->where('balance', '>', 0)
|
->where('invoices.balance', '>', 0)
|
||||||
->where(function ($query) {
|
->orWhere(function ($query) {
|
||||||
|
|
||||||
$query->whereNull('due_date')
|
$query->whereNull('invoices.due_date')
|
||||||
->orWhere(function ($q) {
|
->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) {
|
->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(invoices.due_date), invoices.due_date ' . 'desc')
|
||||||
->orderByRaw('ISNULL(partial_due_date), partial_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('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("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('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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -273,22 +273,10 @@ abstract class QueryFilters
|
|||||||
|
|
||||||
public function filter_deleted_clients($value)
|
public function filter_deleted_clients($value)
|
||||||
{
|
{
|
||||||
// if ($value == 'true') {
|
if ($value == 'true') {
|
||||||
// return $this->builder->whereHas('client', function (Builder $query) {
|
return $this->builder->whereHas('client', function (Builder $query) {
|
||||||
// $query->where('is_deleted', 0);
|
$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)
|
|
||||||
->whereNull('clients.deleted_at');
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->builder;
|
return $this->builder;
|
||||||
|
@ -115,13 +115,8 @@ class AccountController extends BaseController
|
|||||||
|
|
||||||
public function update(UpdateAccountRequest $request, Account $account)
|
public function update(UpdateAccountRequest $request, Account $account)
|
||||||
{
|
{
|
||||||
$fi = new \FilesystemIterator(public_path('react'), \FilesystemIterator::SKIP_DOTS);
|
|
||||||
|
|
||||||
if (iterator_count($fi) < 30) {
|
$account->set_react_as_default_ap = $request->input('set_react_as_default_ap');
|
||||||
return response()->json(['message' => 'React App Not Installed, Please install the React app before attempting to switch.'], 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
$account->fill($request->all());
|
|
||||||
$account->save();
|
$account->save();
|
||||||
|
|
||||||
$this->entity_type = Account::class;
|
$this->entity_type = Account::class;
|
||||||
|
@ -937,7 +937,9 @@ class BaseController extends Controller
|
|||||||
} elseif (in_array($this->entity_type, [Design::class, GroupSetting::class, PaymentTerm::class, TaskStatus::class])) {
|
} elseif (in_array($this->entity_type, [Design::class, GroupSetting::class, PaymentTerm::class, TaskStatus::class])) {
|
||||||
// nlog($this->entity_type);
|
// nlog($this->entity_type);
|
||||||
} else {
|
} 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);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +56,8 @@ class SetDomainNameDb
|
|||||||
return response()->json($error, 403);
|
return response()->json($error, 403);
|
||||||
} else {
|
} else {
|
||||||
MultiDB::setDb('db-ninja-01');
|
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');
|
//abort(400, 'Domain not found');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -73,7 +74,8 @@ class SetDomainNameDb
|
|||||||
return response()->json($error, 403);
|
return response()->json($error, 403);
|
||||||
} else {
|
} else {
|
||||||
MultiDB::setDb('db-ninja-01');
|
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ class InvoiceTransformer extends BaseTransformer
|
|||||||
'due_date' => isset($invoice_data['Due Date']) ? $this->parseDate($invoice_data['Due Date']) : null,
|
'due_date' => isset($invoice_data['Due Date']) ? $this->parseDate($invoice_data['Due Date']) : null,
|
||||||
'po_number' => $this->getString($invoice_data, 'PurchaseOrder'),
|
'po_number' => $this->getString($invoice_data, 'PurchaseOrder'),
|
||||||
'public_notes' => $this->getString($invoice_data, 'Notes'),
|
'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'),
|
'amount' => $this->getFloat($invoice_data, 'Total'),
|
||||||
'balance' => $this->getFloat($invoice_data, 'Balance'),
|
'balance' => $this->getFloat($invoice_data, 'Balance'),
|
||||||
'status_id' => $invoiceStatusMap[$status =
|
'status_id' => $invoiceStatusMap[$status =
|
||||||
|
@ -86,6 +86,9 @@ class UpdateCalculatedFields
|
|||||||
|
|
||||||
foreach(json_decode($task->time_log) as $log) {
|
foreach(json_decode($task->time_log) as $log) {
|
||||||
|
|
||||||
|
if(!is_array($log))
|
||||||
|
continue;
|
||||||
|
|
||||||
$start_time = $log[0];
|
$start_time = $log[0];
|
||||||
$end_time = $log[1] == 0 ? time() : $log[1];
|
$end_time = $log[1] == 0 ? time() : $log[1];
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ class TaskAssigned implements ShouldQueue
|
|||||||
|
|
||||||
$company_user = $this->task->assignedCompanyUser();
|
$company_user = $this->task->assignedCompanyUser();
|
||||||
|
|
||||||
if($this->findEntityAssignedNotification($company_user, 'task'))
|
if($company_user && $this->findEntityAssignedNotification($company_user, 'task'))
|
||||||
{
|
{
|
||||||
$mo = new EmailObject();
|
$mo = new EmailObject();
|
||||||
$mo->subject = ctrans('texts.task_assigned_subject', ['task' => $this->task->number, 'date' => now()->setTimeZone($this->task->company->timezone()->name)->format($this->task->company->date_format()) ]);
|
$mo->subject = ctrans('texts.task_assigned_subject', ['task' => $this->task->number, 'date' => now()->setTimeZone($this->task->company->timezone()->name)->format($this->task->company->date_format()) ]);
|
||||||
|
@ -59,28 +59,19 @@ class ReminderJob implements ShouldQueue
|
|||||||
nrlog("Sending invoice reminders on ".now()->format('Y-m-d h:i:s'));
|
nrlog("Sending invoice reminders on ".now()->format('Y-m-d h:i:s'));
|
||||||
|
|
||||||
Invoice::query()
|
Invoice::query()
|
||||||
->where('invoices.is_deleted', 0)
|
->where('is_deleted', 0)
|
||||||
->whereIn('invoices.status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
|
->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
|
||||||
->whereNull('invoices.deleted_at')
|
->whereNull('deleted_at')
|
||||||
->where('invoices.balance', '>', 0)
|
->where('balance', '>', 0)
|
||||||
->where('invoices.next_send_date', '<=', now()->toDateTimeString())
|
->where('next_send_date', '<=', now()->toDateTimeString())
|
||||||
// ->whereHas('client', function ($query) {
|
->whereHas('client', function ($query) {
|
||||||
// $query->where('is_deleted', 0)
|
$query->where('is_deleted', 0)
|
||||||
// ->where('deleted_at', null);
|
->where('deleted_at', null);
|
||||||
// })
|
|
||||||
// ->whereHas('company', function ($query) {
|
|
||||||
// $query->where('is_disabled', 0);
|
|
||||||
// })
|
|
||||||
->leftJoin('clients', function ($join) {
|
|
||||||
$join->on('invoices.client_id', '=', 'clients.id')
|
|
||||||
->where('clients.is_deleted', 0)
|
|
||||||
->whereNull('clients.deleted_at');
|
|
||||||
})
|
})
|
||||||
->leftJoin('companies', function ($join) {
|
->whereHas('company', function ($query) {
|
||||||
$join->on('invoices.company_id', '=', 'companies.id')
|
$query->where('is_disabled', 0);
|
||||||
->where('companies.is_disabled', 0);
|
|
||||||
})
|
})
|
||||||
->with('invitations')->chunk(50, function ($invoices) {
|
->with('invitations')->chunk(200, function ($invoices) {
|
||||||
foreach ($invoices as $invoice) {
|
foreach ($invoices as $invoice) {
|
||||||
$this->sendReminderForInvoice($invoice);
|
$this->sendReminderForInvoice($invoice);
|
||||||
}
|
}
|
||||||
@ -96,28 +87,19 @@ class ReminderJob implements ShouldQueue
|
|||||||
nrlog("Sending invoice reminders on db {$db} ".now()->format('Y-m-d h:i:s'));
|
nrlog("Sending invoice reminders on db {$db} ".now()->format('Y-m-d h:i:s'));
|
||||||
|
|
||||||
Invoice::query()
|
Invoice::query()
|
||||||
->where('invoices.is_deleted', 0)
|
->where('is_deleted', 0)
|
||||||
->whereIn('invoices.status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
|
->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
|
||||||
->whereNull('invoices.deleted_at')
|
->whereNull('deleted_at')
|
||||||
->where('invoices.balance', '>', 0)
|
->where('balance', '>', 0)
|
||||||
->where('invoices.next_send_date', '<=', now()->toDateTimeString())
|
->where('next_send_date', '<=', now()->toDateTimeString())
|
||||||
// ->whereHas('client', function ($query) {
|
->whereHas('client', function ($query) {
|
||||||
// $query->where('is_deleted', 0)
|
$query->where('is_deleted', 0)
|
||||||
// ->where('deleted_at', null);
|
->where('deleted_at', null);
|
||||||
// })
|
|
||||||
// ->whereHas('company', function ($query) {
|
|
||||||
// $query->where('is_disabled', 0);
|
|
||||||
// })
|
|
||||||
->leftJoin('clients', function ($join) {
|
|
||||||
$join->on('invoices.client_id', '=', 'clients.id')
|
|
||||||
->where('clients.is_deleted', 0)
|
|
||||||
->whereNull('clients.deleted_at');
|
|
||||||
})
|
})
|
||||||
->leftJoin('companies', function ($join) {
|
->whereHas('company', function ($query) {
|
||||||
$join->on('invoices.company_id', '=', 'companies.id')
|
$query->where('is_disabled', 0);
|
||||||
->where('companies.is_disabled', 0);
|
|
||||||
})
|
})
|
||||||
->with('invitations')->chunk(50, function ($invoices) {
|
->with('invitations')->chunk(200, function ($invoices) {
|
||||||
|
|
||||||
foreach ($invoices as $invoice) {
|
foreach ($invoices as $invoice) {
|
||||||
$this->sendReminderForInvoice($invoice);
|
$this->sendReminderForInvoice($invoice);
|
||||||
|
@ -134,18 +134,6 @@ class BaseModel extends Model
|
|||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function scopeWithoutDeletedClients($query)
|
|
||||||
{
|
|
||||||
|
|
||||||
$query->leftJoin('clients', function ($join) use ($query){
|
|
||||||
$join->on("{$query->getQuery()->from}.client_id", '=', 'clients.id')
|
|
||||||
->where('clients.is_deleted', 0)
|
|
||||||
->whereNull('clients.deleted_at');
|
|
||||||
});
|
|
||||||
|
|
||||||
return $query;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated version
|
* @deprecated version
|
||||||
*/
|
*/
|
||||||
|
@ -107,7 +107,6 @@ use Laracasts\Presenter\PresentableTrait;
|
|||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Backup> $history
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Backup> $history
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\QuoteInvitation> $invitations
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\QuoteInvitation> $invitations
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel company()
|
|
||||||
* @mixin \Eloquent
|
* @mixin \Eloquent
|
||||||
* @mixin \Illuminate\Database\Eloquent\Builder
|
* @mixin \Illuminate\Database\Eloquent\Builder
|
||||||
*/
|
*/
|
||||||
|
@ -261,7 +261,7 @@ class TaskRepository extends BaseRepository
|
|||||||
|
|
||||||
public function roundTimeLog(int $start_time, int $end_time): int
|
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;
|
return $end_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@ class ZugferdEDocument extends AbstractService {
|
|||||||
*/
|
*/
|
||||||
public function run(): Expense
|
public function run(): Expense
|
||||||
{
|
{
|
||||||
|
/** @var \App\Models\User $user */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
$this->document = ZugferdDocumentReader::readAndGuessFromContent($this->tempdocument);
|
$this->document = ZugferdDocumentReader::readAndGuessFromContent($this->tempdocument);
|
||||||
$this->document->getDocumentInformation($documentno, $documenttypecode, $documentdate, $invoiceCurrency, $taxCurrency, $documentname, $documentlanguage, $effectiveSpecifiedPeriod);
|
$this->document->getDocumentInformation($documentno, $documenttypecode, $documentdate, $invoiceCurrency, $taxCurrency, $documentname, $documentlanguage, $effectiveSpecifiedPeriod);
|
||||||
@ -102,13 +103,13 @@ class ZugferdEDocument extends AbstractService {
|
|||||||
if ($taxid != null) {
|
if ($taxid != null) {
|
||||||
$vendor->vat_number = $taxid;
|
$vendor->vat_number = $taxid;
|
||||||
}
|
}
|
||||||
$vendor->currency_id = Currency::whereCode($invoiceCurrency)->first()->id;
|
$vendor->currency_id = Currency::query()->where('code', $invoiceCurrency)->first()->id;
|
||||||
$vendor->phone = $contact_phone;
|
$vendor->phone = $contact_phone;
|
||||||
$vendor->address1 = $address_1;
|
$vendor->address1 = $address_1;
|
||||||
$vendor->address2 = $address_2;
|
$vendor->address2 = $address_2;
|
||||||
$vendor->city = $city;
|
$vendor->city = $city;
|
||||||
$vendor->postal_code = $postcode;
|
$vendor->postal_code = $postcode;
|
||||||
$vendor->country_id = Country::where('iso_3166_2', $country)->first()->id;
|
$vendor->country_id = Country::query()->where('iso_3166_2', $country)->first()->id;
|
||||||
|
|
||||||
$vendor->save();
|
$vendor->save();
|
||||||
$expense->vendor_id = $vendor->id;
|
$expense->vendor_id = $vendor->id;
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
namespace App\Utils;
|
namespace App\Utils;
|
||||||
|
|
||||||
|
use Illuminate\Http\File;
|
||||||
|
use Illuminate\Http\UploadedFile;
|
||||||
class TempFile
|
class TempFile
|
||||||
{
|
{
|
||||||
public static function path($url): string
|
public static function path($url): string
|
||||||
@ -34,4 +36,61 @@ class TempFile
|
|||||||
|
|
||||||
return $file_path;
|
return $file_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function UploadedFileFromRaw(string $fileData, string|null $fileName = null, string|null $mimeType = null): UploadedFile
|
||||||
|
{
|
||||||
|
// Create temp file and get its absolute path
|
||||||
|
$tempFile = tmpfile();
|
||||||
|
$tempFilePath = stream_get_meta_data($tempFile)['uri'];
|
||||||
|
|
||||||
|
// Save file data in file
|
||||||
|
file_put_contents($tempFilePath, $fileData);
|
||||||
|
|
||||||
|
$tempFileObject = new File($tempFilePath);
|
||||||
|
$file = new UploadedFile(
|
||||||
|
$tempFileObject->getPathname(),
|
||||||
|
$fileName ?: $tempFileObject->getFilename(),
|
||||||
|
$mimeType ?: $tempFileObject->getMimeType(),
|
||||||
|
0,
|
||||||
|
true // Mark it as test, since the file isn't from real HTTP POST.
|
||||||
|
);
|
||||||
|
|
||||||
|
// Close this file after response is sent.
|
||||||
|
// Closing the file will cause to remove it from temp director!
|
||||||
|
app()->terminating(function () use ($tempFile) {
|
||||||
|
fclose($tempFile);
|
||||||
|
});
|
||||||
|
|
||||||
|
// return UploadedFile object
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create a tmp file from a raw string: https://gist.github.com/waska14/8b3bcebfad1f86f7fcd3b82927576e38*/
|
||||||
|
public static function UploadedFileFromUrl(string $url, string|null $fileName = null, string|null $mimeType = null): UploadedFile
|
||||||
|
{
|
||||||
|
// Create temp file and get its absolute path
|
||||||
|
$tempFile = tmpfile();
|
||||||
|
$tempFilePath = stream_get_meta_data($tempFile)['uri'];
|
||||||
|
|
||||||
|
// Save file data in file
|
||||||
|
file_put_contents($tempFilePath, file_get_contents($url));
|
||||||
|
|
||||||
|
$tempFileObject = new File($tempFilePath);
|
||||||
|
$file = new UploadedFile(
|
||||||
|
$tempFileObject->getPathname(),
|
||||||
|
$fileName ?: $tempFileObject->getFilename(),
|
||||||
|
$mimeType ?: $tempFileObject->getMimeType(),
|
||||||
|
0,
|
||||||
|
true // Mark it as test, since the file isn't from real HTTP POST.
|
||||||
|
);
|
||||||
|
|
||||||
|
// Close this file after response is sent.
|
||||||
|
// Closing the file will cause to remove it from temp director!
|
||||||
|
app()->terminating(function () use ($tempFile) {
|
||||||
|
fclose($tempFile);
|
||||||
|
});
|
||||||
|
|
||||||
|
// return UploadedFile object
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
6
public/flutter_service_worker.js
vendored
6
public/flutter_service_worker.js
vendored
@ -16,9 +16,9 @@ const RESOURCES = {"icons/Icon-512.png": "0f9aff01367f0a0c69773d25ca16ef35",
|
|||||||
"canvaskit/canvaskit.js": "c86fbd9e7b17accae76e5ad116583dc4",
|
"canvaskit/canvaskit.js": "c86fbd9e7b17accae76e5ad116583dc4",
|
||||||
"canvaskit/canvaskit.wasm": "3d2a2d663e8c5111ac61a46367f751ac",
|
"canvaskit/canvaskit.wasm": "3d2a2d663e8c5111ac61a46367f751ac",
|
||||||
"canvaskit/skwasm.wasm": "e42815763c5d05bba43f9d0337fa7d84",
|
"canvaskit/skwasm.wasm": "e42815763c5d05bba43f9d0337fa7d84",
|
||||||
"version.json": "1592dbbd49cf08963e29ab3a85640d96",
|
"version.json": "f789e711f61e122f41a7eda7522a1fba",
|
||||||
"favicon.png": "dca91c54388f52eded692718d5a98b8b",
|
"favicon.png": "dca91c54388f52eded692718d5a98b8b",
|
||||||
"main.dart.js": "0512d8a34cb5c2d5d565a27c3666d9f9",
|
"main.dart.js": "bb6cfbe200a5c6a0d8857eaffd21b759",
|
||||||
"assets/NOTICES": "412b336cf9e33e70058d612857effae1",
|
"assets/NOTICES": "412b336cf9e33e70058d612857effae1",
|
||||||
"assets/AssetManifest.bin": "bf3be26e7055ad9a32f66b3a56138224",
|
"assets/AssetManifest.bin": "bf3be26e7055ad9a32f66b3a56138224",
|
||||||
"assets/assets/images/logo_light.png": "e5f46d5a78e226e7a9553d4ca6f69219",
|
"assets/assets/images/logo_light.png": "e5f46d5a78e226e7a9553d4ca6f69219",
|
||||||
@ -307,7 +307,7 @@ const RESOURCES = {"icons/Icon-512.png": "0f9aff01367f0a0c69773d25ca16ef35",
|
|||||||
"assets/FontManifest.json": "087fb858dc3cbfbf6baf6a30004922f1",
|
"assets/FontManifest.json": "087fb858dc3cbfbf6baf6a30004922f1",
|
||||||
"assets/fonts/MaterialIcons-Regular.otf": "a57618538ab8b4c4081d4491870ac333",
|
"assets/fonts/MaterialIcons-Regular.otf": "a57618538ab8b4c4081d4491870ac333",
|
||||||
"assets/AssetManifest.json": "759f9ef9973f7e26c2a51450b55bb9fa",
|
"assets/AssetManifest.json": "759f9ef9973f7e26c2a51450b55bb9fa",
|
||||||
"/": "a53ace1edfc2ce12fc50cbbade610be3",
|
"/": "e847f898173e2b358dcf6efc58032f91",
|
||||||
"favicon.ico": "51636d3a390451561744c42188ccd628",
|
"favicon.ico": "51636d3a390451561744c42188ccd628",
|
||||||
"manifest.json": "ef43d90e57aa7682d7e2cfba2f484a40"};
|
"manifest.json": "ef43d90e57aa7682d7e2cfba2f484a40"};
|
||||||
// The application shell files that are downloaded before a service worker can
|
// The application shell files that are downloaded before a service worker can
|
||||||
|
271459
public/main.dart.js
vendored
271459
public/main.dart.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
269785
public/main.foss.dart.js
vendored
269785
public/main.foss.dart.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
17645
public/main.profile.dart.js
vendored
17645
public/main.profile.dart.js
vendored
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
|||||||
{"app_name":"invoiceninja_flutter","version":"5.0.160","build_number":"160","package_name":"invoiceninja_flutter"}
|
{"app_name":"invoiceninja_flutter","version":"5.0.161","build_number":"161","package_name":"invoiceninja_flutter"}
|
@ -11,7 +11,9 @@
|
|||||||
|
|
||||||
namespace Tests\Feature;
|
namespace Tests\Feature;
|
||||||
|
|
||||||
|
use App\Models\Client;
|
||||||
use App\Models\CompanyGateway;
|
use App\Models\CompanyGateway;
|
||||||
|
use App\Models\Invoice;
|
||||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
use Tests\MockAccountData;
|
use Tests\MockAccountData;
|
||||||
use Tests\TestCase;
|
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()
|
public function testPaymentMethodsWithCreditsEnforced()
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -51,6 +169,6 @@ class ClientModelTest extends TestCase
|
|||||||
|
|
||||||
$this->assertGreaterThan(0, CompanyGateway::count());
|
$this->assertGreaterThan(0, CompanyGateway::count());
|
||||||
|
|
||||||
$this->assertEquals(1, count($payment_methods));
|
$this->assertEquals(2, count($payment_methods));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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()
|
public function testRequestRuleParsing()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user