mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Merge pull request #9507 from turbo124/v5-develop
Cleanup for Stripe webhooks.
This commit is contained in:
commit
6524b0d955
2
.github/workflows/react_release.yml
vendored
2
.github/workflows/react_release.yml
vendored
@ -64,7 +64,7 @@ jobs:
|
||||
- name: Build project
|
||||
run: |
|
||||
shopt -s dotglob
|
||||
tar --exclude='public/storage' --exclude='.htaccess' --exclude='invoiceninja.zip' -zcvf /home/runner/work/invoiceninja/react-invoiceninja.tar *
|
||||
tar --exclude='public/storage' --exclude='./htaccess' --exclude='invoiceninja.zip' -zcvf /home/runner/work/invoiceninja/react-invoiceninja.tar *
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
|
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@ -74,7 +74,7 @@ jobs:
|
||||
run: |
|
||||
zip -r /home/runner/work/invoiceninja/invoiceninja.zip .* -x "../*"
|
||||
shopt -s dotglob
|
||||
tar --exclude='public/storage' --exclude='.htaccess' --exclude='invoiceninja.zip' -zcvf /home/runner/work/invoiceninja/invoiceninja.tar *
|
||||
tar --exclude='public/storage' --exclude='./htaccess' --exclude='invoiceninja.zip' -zcvf /home/runner/work/invoiceninja/invoiceninja.tar *
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
|
@ -1 +1 @@
|
||||
5.8.53
|
||||
5.8.54
|
@ -208,7 +208,7 @@ class CheckData extends Command
|
||||
->cursor()
|
||||
->each(function ($client) {
|
||||
if ($client->recurring_invoices()->where('is_deleted', 0)->where('deleted_at', null)->count() > 1) {
|
||||
$this->logMessage("Duplicate Recurring Invoice => {$client->custom_value1}");
|
||||
$this->logMessage("Duplicate Recurring Invoice => {$client->custom_value1} || {$client->id}}");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -11,11 +11,12 @@
|
||||
|
||||
namespace App\DataMapper\Tax;
|
||||
|
||||
use App\DataMapper\Tax\ZipTax\Response;
|
||||
use App\DataProviders\USStates;
|
||||
use App\Models\Quote;
|
||||
use App\Models\Client;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Product;
|
||||
use App\DataProviders\USStates;
|
||||
use App\DataMapper\Tax\ZipTax\Response;
|
||||
|
||||
class BaseRule implements RuleInterface
|
||||
{
|
||||
@ -210,7 +211,7 @@ class BaseRule implements RuleInterface
|
||||
}
|
||||
|
||||
/** Applies the tax data to the invoice */
|
||||
if($this->invoice instanceof Invoice && $tax_data) {
|
||||
if(($this->invoice instanceof Invoice || $this->invoice instanceof Quote) && $tax_data) {
|
||||
|
||||
$this->invoice->tax_data = $tax_data;
|
||||
|
||||
|
42
app/Events/Statement/StatementWasEmailed.php
Normal file
42
app/Events/Statement/StatementWasEmailed.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Events\Statement;
|
||||
|
||||
use App\Models\Client;
|
||||
use App\Models\Company;
|
||||
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class StatementWasEmailed.
|
||||
*/
|
||||
class StatementWasEmailed
|
||||
{
|
||||
use Dispatchable;
|
||||
use InteractsWithSockets;
|
||||
use SerializesModels;
|
||||
|
||||
public function __construct(public Client $client, public Company $company, public string $end_date, public array $event_vars)
|
||||
{
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Get the channels the event should broadcast on.
|
||||
// *
|
||||
// * @return Channel|array
|
||||
// */
|
||||
public function broadcastOn()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
@ -448,6 +448,7 @@ class BaseExport
|
||||
'custom_value4' => 'task.custom_value4',
|
||||
'status' => 'task.status_id',
|
||||
'project' => 'task.project_id',
|
||||
'billable' => 'task.billable',
|
||||
];
|
||||
|
||||
protected array $forced_client_fields = [
|
||||
|
@ -178,13 +178,13 @@ class SwissQrGenerator
|
||||
if(is_iterable($qrBill->getViolations())) {
|
||||
|
||||
foreach ($qrBill->getViolations() as $key => $violation) {
|
||||
nlog("qr");
|
||||
nlog($violation);
|
||||
// nlog("qr");
|
||||
// nlog($violation);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
nlog($e->getMessage());
|
||||
// nlog($e->getMessage());
|
||||
|
||||
return '';
|
||||
// return $e->getMessage();
|
||||
|
@ -37,18 +37,18 @@ class StripeConnectController extends BaseController
|
||||
|
||||
MultiDB::findAndSetDbByCompanyKey($request->getTokenContent()['company_key']);
|
||||
|
||||
$company_gateway = CompanyGateway::query()
|
||||
->where('gateway_key', 'd14dd26a47cecc30fdd65700bfb67b34')
|
||||
->where('company_id', $request->getCompany()->id)
|
||||
->first();
|
||||
// $company_gateway = CompanyGateway::query()
|
||||
// ->where('gateway_key', 'd14dd26a47cecc30fdd65700bfb67b34')
|
||||
// ->where('company_id', $request->getCompany()->id)
|
||||
// ->first();
|
||||
|
||||
if ($company_gateway) {
|
||||
$config = $company_gateway->getConfig();
|
||||
// if ($company_gateway) {
|
||||
// $config = $company_gateway->getConfig();
|
||||
|
||||
if (property_exists($config, 'account_id') && strlen($config->account_id) > 5) {
|
||||
return view('auth.connect.existing');
|
||||
}
|
||||
}
|
||||
// if (property_exists($config, 'account_id') && strlen($config->account_id) > 5) {
|
||||
// return view('auth.connect.existing');
|
||||
// }
|
||||
// }
|
||||
|
||||
$stripe_client_id = config('ninja.ninja_stripe_client_id');
|
||||
$redirect_uri = config('ninja.app_url').'/stripe/completed';
|
||||
@ -127,7 +127,6 @@ class StripeConnectController extends BaseController
|
||||
'refresh_token' => $response->refresh_token,
|
||||
'access_token' => $response->access_token,
|
||||
'appleDomainVerification' => '',
|
||||
// "statementDescriptor" => "",
|
||||
];
|
||||
|
||||
$company_gateway->setConfig($payload);
|
||||
@ -145,9 +144,6 @@ class StripeConnectController extends BaseController
|
||||
nlog("could not harvest stripe company name");
|
||||
}
|
||||
|
||||
// nlog("Stripe Connect Redirect URI = {$redirect_uri}");
|
||||
|
||||
// StripeWebhook::dispatch($company->company_key, $company_gateway->id);
|
||||
if(isset($request->getTokenContent()['is_react']) && $request->getTokenContent()['is_react']) {
|
||||
$redirect_uri = config('ninja.react_url').'/#/settings/online_payments';
|
||||
} else {
|
||||
@ -158,7 +154,7 @@ class StripeConnectController extends BaseController
|
||||
|
||||
//response here
|
||||
return view('auth.connect.completed', ['url' => $redirect_uri]);
|
||||
// return redirect($redirect_uri);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -129,6 +129,10 @@ class TwilioController extends BaseController
|
||||
$user->verified_phone_number = true;
|
||||
$user->save();
|
||||
|
||||
if (class_exists(\Modules\Admin\Jobs\Account\UserQualityCheck::class)) {
|
||||
\Modules\Admin\Jobs\Account\UserQualityCheck::dispatch($user, $user->company()->db);
|
||||
}
|
||||
|
||||
return response()->json(['message' => 'SMS verified'], 200);
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ class StoreBankTransactionRequest extends Request
|
||||
$rules = [];
|
||||
|
||||
$rules['bank_integration_id'] = 'bail|required|exists:bank_integrations,id,company_id,'.$user->company()->id.',is_deleted,0';
|
||||
|
||||
$rules['amount'] = ['sometimes', 'bail', 'numeric', 'nullable', 'max:99999999999999'];
|
||||
return $rules;
|
||||
}
|
||||
|
||||
@ -55,6 +55,7 @@ class StoreBankTransactionRequest extends Request
|
||||
$input['bank_integration_id'] = $this->decodePrimaryKey($input['bank_integration_id']);
|
||||
}
|
||||
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
}
|
||||
|
@ -44,9 +44,7 @@ class UpdateBankTransactionRequest extends Request
|
||||
$rules['vendor_id'] = 'bail|required|exists:vendors,id,company_id,'.auth()->user()->company()->id.',is_deleted,0';
|
||||
}
|
||||
|
||||
// if (isset($this->expense_id)) {
|
||||
// $rules['expense_id'] = 'bail|required|exists:expenses,id,company_id,'.auth()->user()->company()->id.',is_deleted,0';
|
||||
// }
|
||||
$rules['amount'] = ['sometimes', 'bail', 'nullable', 'numeric', 'max:99999999999999'];
|
||||
|
||||
$rules['bank_integration_id'] = 'bail|required|exists:bank_integrations,id,company_id,'.auth()->user()->company()->id.',is_deleted,0';
|
||||
|
||||
|
@ -67,7 +67,7 @@ class StoreCreditRequest extends Request
|
||||
|
||||
// $rules['number'] = new UniqueCreditNumberRule($this->all());
|
||||
$rules['number'] = ['nullable', Rule::unique('credits')->where('company_id', $user->company()->id)];
|
||||
$rules['discount'] = 'sometimes|numeric';
|
||||
$rules['discount'] = 'sometimes|numeric|max:99999999999999';
|
||||
$rules['is_amount_discount'] = ['boolean'];
|
||||
$rules['tax_rate1'] = 'bail|sometimes|numeric';
|
||||
$rules['tax_rate2'] = 'bail|sometimes|numeric';
|
||||
@ -76,6 +76,7 @@ class StoreCreditRequest extends Request
|
||||
$rules['tax_name2'] = 'bail|sometimes|string|nullable';
|
||||
$rules['tax_name3'] = 'bail|sometimes|string|nullable';
|
||||
$rules['exchange_rate'] = 'bail|sometimes|numeric';
|
||||
$rules['amount'] = ['sometimes', 'bail', 'numeric', 'max:99999999999999'];
|
||||
|
||||
if ($this->invoice_id) {
|
||||
$rules['invoice_id'] = new ValidInvoiceCreditRule();
|
||||
@ -101,6 +102,7 @@ class StoreCreditRequest extends Request
|
||||
$input = $this->decodePrimaryKeys($input);
|
||||
|
||||
$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;
|
||||
|
@ -67,7 +67,8 @@ class UpdateCreditRequest extends Request
|
||||
$rules['client_id'] = ['bail', 'sometimes',Rule::in([$this->credit->client_id])];
|
||||
|
||||
$rules['line_items'] = 'array';
|
||||
$rules['discount'] = 'sometimes|numeric';
|
||||
|
||||
$rules['discount'] = 'sometimes|numeric|max:99999999999999';
|
||||
$rules['is_amount_discount'] = ['boolean'];
|
||||
$rules['tax_rate1'] = 'bail|sometimes|numeric';
|
||||
$rules['tax_rate2'] = 'bail|sometimes|numeric';
|
||||
@ -76,6 +77,7 @@ class UpdateCreditRequest extends Request
|
||||
$rules['tax_name2'] = 'bail|sometimes|string|nullable';
|
||||
$rules['tax_name3'] = 'bail|sometimes|string|nullable';
|
||||
$rules['exchange_rate'] = 'bail|sometimes|numeric';
|
||||
$rules['amount'] = ['sometimes', 'bail', 'numeric', 'max:99999999999999'];
|
||||
|
||||
return $rules;
|
||||
}
|
||||
@ -92,6 +94,8 @@ class UpdateCreditRequest extends Request
|
||||
|
||||
if (isset($input['line_items'])) {
|
||||
$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'])) {
|
||||
|
@ -53,6 +53,7 @@ class StoreExpenseRequest extends Request
|
||||
$rules['payment_date'] = 'bail|nullable|sometimes|date:Y-m-d';
|
||||
$rules['date'] = 'bail|sometimes|date:Y-m-d';
|
||||
$rules['documents'] = 'bail|sometimes|array';
|
||||
$rules['amount'] = ['sometimes', 'bail', 'nullable', 'numeric', 'max:99999999999999'];
|
||||
|
||||
return $this->globalRules($rules);
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ class UpdateExpenseRequest extends Request
|
||||
$rules['transaction_id'] = 'bail|sometimes|nullable|exists:bank_transactions,id,company_id,'.$user->company()->id;
|
||||
$rules['invoice_id'] = 'bail|sometimes|nullable|exists:invoices,id,company_id,'.$user->company()->id;
|
||||
$rules['documents'] = 'bail|sometimes|array';
|
||||
|
||||
$rules['amount'] = ['sometimes', 'bail', 'nullable', 'numeric', 'max:99999999999999'];
|
||||
|
||||
return $this->globalRules($rules);
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ class StoreInvoiceRequest extends Request
|
||||
$rules['is_amount_discount'] = ['boolean'];
|
||||
|
||||
$rules['line_items'] = 'array';
|
||||
$rules['discount'] = 'sometimes|numeric';
|
||||
$rules['discount'] = 'sometimes|numeric|max:99999999999999';
|
||||
$rules['tax_rate1'] = 'bail|sometimes|numeric';
|
||||
$rules['tax_rate2'] = 'bail|sometimes|numeric';
|
||||
$rules['tax_rate3'] = 'bail|sometimes|numeric';
|
||||
@ -77,9 +77,11 @@ class StoreInvoiceRequest extends Request
|
||||
$rules['exchange_rate'] = 'bail|sometimes|numeric';
|
||||
$rules['partial'] = 'bail|sometimes|nullable|numeric|gte:0';
|
||||
$rules['partial_due_date'] = ['bail', 'sometimes', 'exclude_if:partial,0', Rule::requiredIf(fn () => $this->partial > 0), '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;
|
||||
}
|
||||
|
||||
@ -89,17 +91,18 @@ class StoreInvoiceRequest extends Request
|
||||
|
||||
$input = $this->decodePrimaryKeys($input);
|
||||
|
||||
$input['amount'] = 0;
|
||||
$input['balance'] = 0;
|
||||
|
||||
if (isset($input['line_items']) && is_array($input['line_items'])) {
|
||||
$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;
|
||||
}
|
||||
|
||||
$input['amount'] = 0;
|
||||
$input['balance'] = 0;
|
||||
|
||||
if (array_key_exists('tax_rate1', $input) && is_null($input['tax_rate1'])) {
|
||||
$input['tax_rate1'] = 0;
|
||||
}
|
||||
|
@ -66,7 +66,8 @@ class UpdateInvoiceRequest extends Request
|
||||
$rules['is_amount_discount'] = ['boolean'];
|
||||
$rules['client_id'] = ['bail', 'sometimes', Rule::in([$this->invoice->client_id])];
|
||||
$rules['line_items'] = 'array';
|
||||
$rules['discount'] = 'sometimes|numeric';
|
||||
|
||||
$rules['discount'] = 'sometimes|numeric|max:99999999999999';
|
||||
$rules['project_id'] = ['bail', 'sometimes', new ValidProjectForClient($this->all())];
|
||||
$rules['tax_rate1'] = 'bail|sometimes|numeric';
|
||||
$rules['tax_rate2'] = 'bail|sometimes|numeric';
|
||||
@ -77,6 +78,8 @@ class UpdateInvoiceRequest extends Request
|
||||
$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['amount'] = ['sometimes', 'bail', 'numeric', 'max:99999999999999'];
|
||||
|
||||
// $rules['partial_due_date'] = ['bail', 'sometimes', 'exclude_if:partial,0', Rule::requiredIf(fn () => $this->partial > 0), 'date', 'before:due_date'];
|
||||
// $rules['due_date'] = ['bail', 'sometimes', 'nullable', 'after:partial_due_date', Rule::requiredIf(fn () => strlen($this->partial_due_date) > 1), 'date'];
|
||||
|
||||
@ -97,6 +100,7 @@ class UpdateInvoiceRequest extends Request
|
||||
|
||||
if (isset($input['line_items']) && is_array($input['line_items'])) {
|
||||
$input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : [];
|
||||
$input['amount'] = $this->entityTotalAmount($input['line_items']);
|
||||
}
|
||||
|
||||
if (array_key_exists('documents', $input)) {
|
||||
|
@ -67,9 +67,8 @@ class RefundPaymentRequest extends Request
|
||||
$input = $this->all();
|
||||
|
||||
$rules = [
|
||||
'id' => 'bail|required', //@phpstan-ignore-line
|
||||
'id' => new ValidRefundableRequest($input),
|
||||
'amount' => 'numeric',
|
||||
'id' => ['bail','required', new ValidRefundableRequest($input)],
|
||||
'amount' => ['numeric', 'max:99999999999999'],
|
||||
'date' => 'required',
|
||||
'invoices.*.invoice_id' => 'required',
|
||||
'invoices.*.amount' => 'required',
|
||||
|
@ -50,7 +50,7 @@ class StorePaymentRequest extends Request
|
||||
'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)],
|
||||
'credits.*.amount' => ['bail','required', new CreditsSumRule($this->all())],
|
||||
'amount' => ['bail', 'numeric', new PaymentAmountsBalanceRule()],
|
||||
'amount' => ['bail', 'numeric', new PaymentAmountsBalanceRule(), 'max:99999999999999'],
|
||||
'number' => ['bail', 'nullable', Rule::unique('payments')->where('company_id', $user->company()->id)],
|
||||
'idempotency_key' => ['nullable', 'bail', 'string','max:64', Rule::unique('payments')->where('company_id', $user->company()->id)],
|
||||
];
|
||||
|
@ -49,7 +49,8 @@ class StorePurchaseOrderRequest extends Request
|
||||
$rules['vendor_id'] = 'bail|required|exists:vendors,id,company_id,'.$user->company()->id.',is_deleted,0';
|
||||
|
||||
$rules['number'] = ['nullable', Rule::unique('purchase_orders')->where('company_id', $user->company()->id)];
|
||||
$rules['discount'] = 'sometimes|numeric';
|
||||
|
||||
$rules['discount'] = 'sometimes|numeric|max:99999999999999';
|
||||
$rules['is_amount_discount'] = ['boolean'];
|
||||
$rules['line_items'] = 'array';
|
||||
|
||||
@ -70,6 +71,8 @@ class StorePurchaseOrderRequest extends Request
|
||||
$rules['status_id'] = 'nullable|integer|in:1,2,3,4,5';
|
||||
$rules['exchange_rate'] = 'bail|sometimes|numeric';
|
||||
|
||||
$rules['amount'] = ['sometimes', 'bail', 'numeric', 'max:99999999999999'];
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
@ -79,16 +82,18 @@ class StorePurchaseOrderRequest extends Request
|
||||
|
||||
$input = $this->decodePrimaryKeys($input);
|
||||
|
||||
$input['amount'] = 0;
|
||||
$input['balance'] = 0;
|
||||
|
||||
if(isset($input['partial']) && $input['partial'] == 0) {
|
||||
$input['partial_due_date'] = null;
|
||||
}
|
||||
|
||||
if (isset($input['line_items']) && is_array($input['line_items'])) {
|
||||
$input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : [];
|
||||
}
|
||||
$input['amount'] = $this->entityTotalAmount($input['line_items']);
|
||||
|
||||
$input['amount'] = 0;
|
||||
$input['balance'] = 0;
|
||||
}
|
||||
|
||||
if (array_key_exists('exchange_rate', $input) && is_null($input['exchange_rate'])) {
|
||||
$input['exchange_rate'] = 1;
|
||||
|
@ -52,7 +52,8 @@ class UpdatePurchaseOrderRequest extends Request
|
||||
$rules['vendor_id'] = ['bail', 'sometimes', Rule::in([$this->purchase_order->vendor_id])];
|
||||
|
||||
$rules['line_items'] = 'array';
|
||||
$rules['discount'] = 'sometimes|numeric';
|
||||
|
||||
$rules['discount'] = 'sometimes|numeric|max:99999999999999';
|
||||
$rules['is_amount_discount'] = ['boolean'];
|
||||
|
||||
if ($this->file('documents') && is_array($this->file('documents'))) {
|
||||
@ -71,6 +72,7 @@ class UpdatePurchaseOrderRequest extends Request
|
||||
|
||||
$rules['status_id'] = 'sometimes|integer|in:1,2,3,4,5';
|
||||
$rules['exchange_rate'] = 'bail|sometimes|numeric';
|
||||
$rules['amount'] = ['sometimes', 'bail', 'numeric', 'max:99999999999999'];
|
||||
|
||||
return $rules;
|
||||
}
|
||||
@ -89,6 +91,7 @@ class UpdatePurchaseOrderRequest extends Request
|
||||
|
||||
if (isset($input['line_items']) && is_array($input['line_items'])) {
|
||||
$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'])) {
|
||||
|
@ -60,12 +60,14 @@ class StoreQuoteRequest extends Request
|
||||
}
|
||||
|
||||
$rules['number'] = ['nullable', Rule::unique('quotes')->where('company_id', $user->company()->id)];
|
||||
$rules['discount'] = 'sometimes|numeric';
|
||||
|
||||
$rules['discount'] = 'sometimes|numeric|max:99999999999999';
|
||||
$rules['is_amount_discount'] = ['boolean'];
|
||||
$rules['exchange_rate'] = 'bail|sometimes|numeric';
|
||||
$rules['line_items'] = 'array';
|
||||
$rules['partial_due_date'] = ['bail', 'sometimes', 'exclude_if:partial,0', Rule::requiredIf(fn () => $this->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;
|
||||
}
|
||||
@ -79,10 +81,14 @@ class StoreQuoteRequest extends Request
|
||||
|
||||
$input = $this->decodePrimaryKeys($input);
|
||||
|
||||
$input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : [];
|
||||
$input['amount'] = 0;
|
||||
$input['balance'] = 0;
|
||||
|
||||
if (isset($input['line_items']) && is_array($input['line_items'])) {
|
||||
$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;
|
||||
}
|
||||
|
@ -59,12 +59,13 @@ class UpdateQuoteRequest extends Request
|
||||
$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';
|
||||
$rules['discount'] = 'sometimes|numeric';
|
||||
$rules['discount'] = 'sometimes|numeric|max:99999999999999';
|
||||
$rules['is_amount_discount'] = ['boolean'];
|
||||
$rules['exchange_rate'] = 'bail|sometimes|numeric';
|
||||
|
||||
$rules['partial_due_date'] = ['bail', 'sometimes', 'exclude_if:partial,0', Rule::requiredIf(fn () => $this->partial > 0), 'date', 'before:due_date'];
|
||||
$rules['due_date'] = ['bail', 'sometimes', 'nullable', 'after:partial_due_date', 'after_or_equal:date', Rule::requiredIf(fn () => strlen($this->partial_due_date) > 1), 'date'];
|
||||
$rules['amount'] = ['sometimes', 'bail', 'numeric', 'max:99999999999999'];
|
||||
|
||||
return $rules;
|
||||
}
|
||||
@ -79,6 +80,7 @@ class UpdateQuoteRequest extends Request
|
||||
|
||||
if (isset($input['line_items'])) {
|
||||
$input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : [];
|
||||
$input['amount'] = $this->entityTotalAmount($input['line_items']);
|
||||
}
|
||||
|
||||
if (array_key_exists('documents', $input)) {
|
||||
|
@ -79,6 +79,8 @@ class StoreRecurringInvoiceRequest extends Request
|
||||
$rules['exchange_rate'] = 'bail|sometimes|numeric';
|
||||
$rules['next_send_date'] = 'bail|required|date|after:yesterday';
|
||||
|
||||
$rules['amount'] = ['sometimes', 'bail', 'numeric', 'max:99999999999999'];
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
@ -145,6 +147,7 @@ class StoreRecurringInvoiceRequest extends Request
|
||||
}
|
||||
|
||||
$input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : [];
|
||||
$input['amount'] = $this->entityTotalAmount($input['line_items']);
|
||||
|
||||
if (isset($input['auto_bill'])) {
|
||||
$input['auto_bill_enabled'] = $this->setAutoBillFlag($input['auto_bill']);
|
||||
|
@ -72,6 +72,7 @@ class UpdateRecurringInvoiceRequest extends Request
|
||||
$rules['tax_name3'] = 'bail|sometimes|string|nullable';
|
||||
$rules['exchange_rate'] = 'bail|sometimes|numeric';
|
||||
$rules['next_send_date'] = 'bail|required|date|after:yesterday';
|
||||
$rules['amount'] = ['sometimes', 'bail', 'numeric', 'max:99999999999999'];
|
||||
|
||||
return $rules;
|
||||
}
|
||||
@ -126,6 +127,7 @@ class UpdateRecurringInvoiceRequest extends Request
|
||||
|
||||
if (isset($input['line_items'])) {
|
||||
$input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : [];
|
||||
$input['amount'] = $this->entityTotalAmount($input['line_items']);
|
||||
}
|
||||
|
||||
if (array_key_exists('auto_bill', $input) && isset($input['auto_bill'])) {
|
||||
|
@ -42,7 +42,7 @@ class ExpenseTransformer extends BaseTransformer
|
||||
'client_id' => isset($data['expense.client'])
|
||||
? $this->getClientId($data['expense.client'])
|
||||
: null,
|
||||
'date' => strlen($this->getString($data, 'expense.date') > 1) ? date('Y-m-d', strtotime(str_replace("/", "-", $data['expense.date']))) : now()->format('Y-m-d'),
|
||||
'date' => strlen($this->getString($data, 'expense.date') > 1) ? $this->parseDate($data['expense.date']) : now()->format('Y-m-d'),
|
||||
'public_notes' => $this->getString($data, 'expense.public_notes'),
|
||||
'private_notes' => $this->getString($data, 'expense.private_notes'),
|
||||
'category_id' => isset($data['expense.category'])
|
||||
@ -55,7 +55,7 @@ class ExpenseTransformer extends BaseTransformer
|
||||
? $this->getPaymentTypeId($data['expense.payment_type'])
|
||||
: null,
|
||||
'payment_date' => isset($data['expense.payment_date'])
|
||||
? date('Y-m-d', strtotime(str_replace("/", "-", $data['expense.payment_date'])))
|
||||
? $this->parseDate($data['expense.payment_date'])
|
||||
: null,
|
||||
'custom_value1' => $this->getString($data, 'expense.custom_value1'),
|
||||
'custom_value2' => $this->getString($data, 'expense.custom_value2'),
|
||||
|
@ -93,11 +93,8 @@ class InvoiceTransformer extends BaseTransformer
|
||||
'invoice.custom_value4'
|
||||
),
|
||||
'footer' => $this->getString($invoice_data, 'invoice.footer'),
|
||||
'partial' => $this->getFloat($invoice_data, 'invoice.partial') > 0 ?: null,
|
||||
'partial_due_date' => $this->getString(
|
||||
$invoice_data,
|
||||
'invoice.partial_due_date'
|
||||
),
|
||||
'partial' => $this->getFloat($invoice_data, 'invoice.partial') > 0 ? $this->getFloat($invoice_data, 'invoice.partial') : null,
|
||||
'partial_due_date' => isset($invoice_data['invoice.partial_due_date']) ? $this->parseDate($invoice_data['invoice.partial_due_date']) : null,
|
||||
'custom_surcharge1' => $this->getFloat(
|
||||
$invoice_data,
|
||||
'invoice.custom_surcharge1'
|
||||
|
@ -56,10 +56,10 @@ class QuoteTransformer extends BaseTransformer
|
||||
'discount' => $this->getFloat($quote_data, 'quote.discount'),
|
||||
'po_number' => $this->getString($quote_data, 'quote.po_number'),
|
||||
'date' => isset($quote_data['quote.date'])
|
||||
? date('Y-m-d', strtotime(str_replace("/", "-", $quote_data['quote.date'])))
|
||||
? $this->parseDate($quote_data['quote.date'])
|
||||
: now()->format('Y-m-d'),
|
||||
'due_date' => isset($quote_data['quote.due_date'])
|
||||
? date('Y-m-d', strtotime(str_replace("/", "-", $quote_data['quote.due_date'])))
|
||||
? $this->parseDate($quote_data['quote.due_date'])
|
||||
: null,
|
||||
'terms' => $this->getString($quote_data, 'quote.terms'),
|
||||
'public_notes' => $this->getString(
|
||||
@ -94,10 +94,7 @@ class QuoteTransformer extends BaseTransformer
|
||||
),
|
||||
'footer' => $this->getString($quote_data, 'quote.footer'),
|
||||
'partial' => $this->getFloat($quote_data, 'quote.partial'),
|
||||
'partial_due_date' => $this->getString(
|
||||
$quote_data,
|
||||
'quote.partial_due_date'
|
||||
),
|
||||
'partial_due_date' => isset($invoice_data['quote.partial_due_date']) ? $this->parseDate($quote_data['quote.partial_due_date']) : null,
|
||||
'custom_surcharge1' => $this->getString(
|
||||
$quote_data,
|
||||
'quote.custom_surcharge1'
|
||||
@ -139,10 +136,7 @@ class QuoteTransformer extends BaseTransformer
|
||||
$transformed['payments'] = [
|
||||
[
|
||||
'date' => isset($quote_data['payment.date'])
|
||||
? date(
|
||||
'Y-m-d',
|
||||
strtotime($quote_data['payment.date'])
|
||||
)
|
||||
? $this->parseDate($quote_data['payment.date'])
|
||||
: date('y-m-d'),
|
||||
'transaction_reference' => $this->getString(
|
||||
$quote_data,
|
||||
@ -158,10 +152,7 @@ class QuoteTransformer extends BaseTransformer
|
||||
$transformed['payments'] = [
|
||||
[
|
||||
'date' => isset($quote_data['payment.date'])
|
||||
? date(
|
||||
'Y-m-d',
|
||||
strtotime($quote_data['payment.date'])
|
||||
)
|
||||
? $this->parseDate($quote_data['payment.date'])
|
||||
: date('y-m-d'),
|
||||
'transaction_reference' => $this->getString(
|
||||
$quote_data,
|
||||
@ -181,10 +172,7 @@ class QuoteTransformer extends BaseTransformer
|
||||
$transformed['payments'] = [
|
||||
[
|
||||
'date' => isset($quote_data['payment.date'])
|
||||
? date(
|
||||
'Y-m-d',
|
||||
strtotime($quote_data['payment.date'])
|
||||
)
|
||||
? $this->parseDate($quote_data['payment.date'])
|
||||
: date('y-m-d'),
|
||||
'transaction_reference' => $this->getString(
|
||||
$quote_data,
|
||||
|
@ -65,9 +65,7 @@ class RecurringInvoiceTransformer extends BaseTransformer
|
||||
'next_send_date_client' => isset($invoice_data['invoice.next_send_date'])
|
||||
? $this->parseDate($invoice_data['invoice.next_send_date'])
|
||||
: now()->format('Y-m-d'),
|
||||
'due_date' => isset($invoice_data['invoice.due_date'])
|
||||
? $this->parseDate($invoice_data['invoice.due_date'])
|
||||
: null,
|
||||
'due_date' => isset($invoice_data['invoice.due_date']) ? $this->parseDate($invoice_data['invoice.due_date']) : null,
|
||||
'terms' => $this->getString($invoice_data, 'invoice.terms'),
|
||||
'due_date_days' => 'terms',
|
||||
'public_notes' => $this->getString(
|
||||
@ -101,11 +99,8 @@ class RecurringInvoiceTransformer extends BaseTransformer
|
||||
'invoice.custom_value4'
|
||||
),
|
||||
'footer' => $this->getString($invoice_data, 'invoice.footer'),
|
||||
'partial' => $this->getFloat($invoice_data, 'invoice.partial') > 0 ?: null,
|
||||
'partial_due_date' => $this->getString(
|
||||
$invoice_data,
|
||||
'invoice.partial_due_date'
|
||||
),
|
||||
'partial' => $this->getFloat($invoice_data, 'invoice.partial') > 0 ? $this->getFloat($invoice_data, 'invoice.partial') : null,
|
||||
'partial_due_date' => isset($invoice_data['invoice.partial_due_date']) ? $this->parseDate($invoice_data['invoice.partial_due_date']) : null,
|
||||
'custom_surcharge1' => $this->getString(
|
||||
$invoice_data,
|
||||
'invoice.custom_surcharge1'
|
||||
|
@ -49,7 +49,7 @@ class TaskTransformer extends BaseTransformer
|
||||
'client_id' => $clientId,
|
||||
'project_id' => $this->getProjectId($projectId, $clientId),
|
||||
'description' => $this->getString($task_data, 'task.description'),
|
||||
'status' => $this->getTaskStatusId($task_data),
|
||||
'status_id' => $this->getTaskStatusId($task_data),
|
||||
'custom_value1' => $this->getString($task_data, 'task.custom_value1'),
|
||||
'custom_value2' => $this->getString($task_data, 'task.custom_value2'),
|
||||
'custom_value3' => $this->getString($task_data, 'task.custom_value3'),
|
||||
@ -84,7 +84,7 @@ class TaskTransformer extends BaseTransformer
|
||||
} elseif(isset($item['task.billable']) && is_bool($item['task.billable'])) {
|
||||
$is_billable = $item['task.billable'];
|
||||
} else {
|
||||
$is_billable = false;
|
||||
$is_billable = true;
|
||||
}
|
||||
|
||||
if(isset($item['task.start_date']) &&
|
||||
|
@ -42,8 +42,7 @@ class InvoiceTransformer extends BaseTransformer
|
||||
'company_id' => $this->company->id,
|
||||
'client_id' => $this->getClient($this->getString($invoice_data, 'Client Name'), null),
|
||||
'number' => $this->getString($invoice_data, 'Invoice #'),
|
||||
'date' => isset($invoice_data['Date Issued']) ? date('Y-m-d', strtotime($invoice_data['Date Issued'])) : null,
|
||||
// 'currency_id' => $this->getCurrencyByCode( $invoice_data, 'Currency' ),
|
||||
'date' => isset($invoice_data['Date Issued']) ? $this->parseDate($invoice_data['Date Issued']) : null,
|
||||
'amount' => 0,
|
||||
'status_id' => $invoiceStatusMap[$status =
|
||||
strtolower($this->getString($invoice_data, 'Invoice Status'))] ?? Invoice::STATUS_SENT,
|
||||
@ -70,7 +69,7 @@ class InvoiceTransformer extends BaseTransformer
|
||||
|
||||
if (! empty($invoice_data['Date Paid'])) {
|
||||
$transformed['payments'] = [[
|
||||
'date' => date('Y-m-d', strtotime($invoice_data['Date Paid'])),
|
||||
'date' => $this->parseDate($invoice_data['Date Paid']),
|
||||
'amount' => $transformed['amount'],
|
||||
]];
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ class InvoiceTransformer extends BaseTransformer
|
||||
'company_id' => $this->company->id,
|
||||
'number' => $this->getString($invoice_data, 'DocumentNumber'),
|
||||
'notes' => $this->getString($invoice_data, 'Comment'),
|
||||
'date' => isset($invoice_data['DocumentDate']) ? date('Y-m-d', strtotime($invoice_data['DocumentDate'])) : null,
|
||||
'date' => isset($invoice_data['DocumentDate']) ? $this->parseDate($invoice_data['DocumentDate']) : null,
|
||||
// 'currency_id' => $this->getCurrencyByCode( $invoice_data, 'Currency' ),
|
||||
'amount' => $this->getFloat($invoice_data, 'TotalAmount'),
|
||||
'status_id' => $invoiceStatusMap[$status =
|
||||
@ -92,7 +92,7 @@ class InvoiceTransformer extends BaseTransformer
|
||||
if (! empty($invoice_data['Date Paid'])) {
|
||||
$transformed['payments'] = [
|
||||
[
|
||||
'date' => date('Y-m-d', strtotime($invoice_data['DatePaid'])),
|
||||
'date' => $this->parseDate($invoice_data['DatePaid']),
|
||||
'amount' => $this->getFloat($invoice_data, 'Payments'),
|
||||
],
|
||||
];
|
||||
|
@ -35,8 +35,8 @@ class InvoiceTransformer extends BaseTransformer
|
||||
'company_id' => $this->company->id,
|
||||
'client_id' => $this->getClient($this->getString($data, 'Client'), null),
|
||||
'number' => $this->getString($data, 'Details'),
|
||||
'date' => isset($data['Date']) ? date('Y-m-d', strtotime($data['Date'])) : null,
|
||||
'due_date' => isset($data['Due']) ? date('Y-m-d', strtotime($data['Due'])) : null,
|
||||
'date' => isset($data['Date']) ? $this->parseDate($data['Date']) : null,
|
||||
'due_date' => isset($data['Due']) ? $this->parseDate($data['Due']) : null,
|
||||
'status_id' => Invoice::STATUS_SENT,
|
||||
'line_items' => [
|
||||
[
|
||||
|
@ -43,7 +43,7 @@ class ExpenseTransformer extends BaseTransformer
|
||||
'vendor_id' => $this->getVendorIdOrCreate($this->getString($data, 'Vendor')),
|
||||
'number' => $this->getString($data, 'Bill Number'),
|
||||
'public_notes' => $this->getString($data, 'Notes / Memo'),
|
||||
'date' => date('Y-m-d', strtotime($data['Transaction Date Added'])) ?: now()->format('Y-m-d'), //27-01-2022
|
||||
'date' => $this->parseDate($data['Transaction Date Added']) ?: now()->format('Y-m-d'), //27-01-2022
|
||||
'currency_id' => $this->company->settings->currency_id,
|
||||
'category_id' => $this->getOrCreateExpenseCategry($data['Account Name']),
|
||||
'amount' => $amount,
|
||||
|
@ -49,10 +49,10 @@ class InvoiceTransformer extends BaseTransformer
|
||||
'company_id' => $this->company->id,
|
||||
'client_id' => $this->getClient($customer_name = $this->getString($invoice_data, $customer_key), null),
|
||||
'number' => $invoice_number = $this->getString($invoice_data, 'Invoice Number'),
|
||||
'date' => date('Y-m-d', strtotime($invoice_data[$date_key])) ?: now()->format('Y-m-d'), //27-01-2022
|
||||
'date' => $this->parseDate($invoice_data[$date_key]) ?: now()->format('Y-m-d'), //27-01-2022
|
||||
'currency_id' => $this->getCurrencyByCode($invoice_data, 'Currency'),
|
||||
'status_id' => Invoice::STATUS_SENT,
|
||||
'due_date' => array_key_exists('Due Date', $invoice_data) ? date('Y-m-d', strtotime($invoice_data['Due Date'])) : null,
|
||||
'due_date' => array_key_exists('Due Date', $invoice_data) ? $this->parseDate($invoice_data['Due Date']) : null,
|
||||
];
|
||||
|
||||
$line_items = [];
|
||||
@ -81,7 +81,7 @@ class InvoiceTransformer extends BaseTransformer
|
||||
} elseif (array_key_exists('Account Type', $record) && $record['Account Type'] === 'System Receivable Invoice') {
|
||||
// This is a payment
|
||||
$payments[] = [
|
||||
'date' => date('Y-m-d', strtotime($invoice_data[$date_key])),
|
||||
'date' => $this->parseDate($invoice_data[$date_key]),
|
||||
'amount' => $this->getFloat($record, 'Amount (One column)'),
|
||||
];
|
||||
} else {
|
||||
@ -103,7 +103,7 @@ class InvoiceTransformer extends BaseTransformer
|
||||
|
||||
if (array_key_exists('Invoice Paid', $record) && $record['Invoice Paid'] > 0) {
|
||||
$payments[] = [
|
||||
'date' => date('Y-m-d', strtotime($record['Last Payment Date'])),
|
||||
'date' => $this->parseDate($record['Last Payment Date']),
|
||||
'amount' => $this->getFloat($record, 'Invoice Paid'),
|
||||
];
|
||||
}
|
||||
|
@ -43,8 +43,8 @@ class InvoiceTransformer extends BaseTransformer
|
||||
// 'client_id' => $this->getClient($this->getString($invoice_data, 'Customer ID'), $this->getString($invoice_data, 'Primary Contact EmailID')),
|
||||
'client_id' => $this->harvestClient($invoice_data),
|
||||
'number' => $this->getString($invoice_data, 'Invoice Number'),
|
||||
'date' => isset($invoice_data['Invoice Date']) ? date('Y-m-d', strtotime($invoice_data['Invoice Date'])) : null,
|
||||
'due_date' => isset($invoice_data['Due Date']) ? date('Y-m-d', strtotime($invoice_data['Due Date'])) : null,
|
||||
'date' => isset($invoice_data['Invoice Date']) ? $this->parseDate($invoice_data['Invoice Date']) : null,
|
||||
'due_date' => isset($invoice_data['Due Date']) ? $this->parseDate($invoice_data['Due Date']) : null,
|
||||
'po_number' => $this->getString($invoice_data, 'PurchaseOrder'),
|
||||
'public_notes' => $this->getString($invoice_data, 'Notes'),
|
||||
'currency_id' => $this->getCurrencyByCode($invoice_data, 'Currency'),
|
||||
@ -74,7 +74,7 @@ class InvoiceTransformer extends BaseTransformer
|
||||
|
||||
if ($transformed['balance'] < $transformed['amount']) {
|
||||
$transformed['payments'] = [[
|
||||
'date' => isset($invoice_data['Last Payment Date']) ? date('Y-m-d', strtotime($invoice_data['Invoice Date'])) : date('Y-m-d'),
|
||||
'date' => isset($invoice_data['Last Payment Date']) ? $this->parseDate($invoice_data['Invoice Date']) : date('Y-m-d'),
|
||||
'amount' => $transformed['amount'] - $transformed['balance'],
|
||||
]];
|
||||
}
|
||||
|
@ -232,7 +232,6 @@ class SendReminders implements ShouldQueue
|
||||
}
|
||||
$invoice->service()->touchReminder($template)->save();
|
||||
|
||||
// $invoice->save();
|
||||
}
|
||||
|
||||
/**
|
||||
|
56
app/Listeners/Statement/StatementEmailedActivity.php
Normal file
56
app/Listeners/Statement/StatementEmailedActivity.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Listeners\Statement;
|
||||
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\Activity;
|
||||
use App\Repositories\ActivityRepository;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use stdClass;
|
||||
|
||||
class StatementEmailedActivity implements ShouldQueue
|
||||
{
|
||||
protected $activityRepo;
|
||||
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @param ActivityRepository $activityRepo
|
||||
*/
|
||||
public function __construct(ActivityRepository $activityRepo)
|
||||
{
|
||||
$this->activityRepo = $activityRepo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param object $event
|
||||
* @return void
|
||||
*/
|
||||
public function handle($event)
|
||||
{
|
||||
MultiDB::setDb($event->company->db);
|
||||
|
||||
$fields = new stdClass();
|
||||
|
||||
$user_id = isset($event->event_vars['user_id']) ? $event->event_vars['user_id'] : $event->client->id;
|
||||
|
||||
$fields->user_id = $user_id;
|
||||
$fields->client_id = $event->client->id;
|
||||
$fields->notes = $event->end_date;
|
||||
$fields->company_id = $event->company->id;
|
||||
$fields->activity_type_id = Activity::EMAIL_STATEMENT;
|
||||
|
||||
$this->activityRepo->save($fields, $event->client, $event->event_vars);
|
||||
}
|
||||
}
|
@ -42,18 +42,18 @@ class ClientRegisterService
|
||||
}
|
||||
|
||||
foreach ($rules as $field => $properties) {
|
||||
if ($field === 'email') {
|
||||
if ($field == 'email') {
|
||||
$rules[$field] = array_merge($rules[$field], ['email:rfc', 'max:191', Rule::unique('client_contacts')->where('company_id', $this->company->id)]);
|
||||
}
|
||||
|
||||
if ($field === 'current_password' || $field === 'password') {
|
||||
if ($field == 'current_password' || $field == 'password') {
|
||||
$rules[$field] = array_merge($rules[$field], ['string', 'min:6', 'confirmed']);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->company->settings->client_portal_terms || $this->company->settings->client_portal_privacy_policy) {
|
||||
$rules['terms'] = ['required'];
|
||||
}
|
||||
// if ($this->company->settings->client_portal_terms || $this->company->settings->client_portal_privacy_policy) {
|
||||
// $rules['terms'] = ['required'];
|
||||
// }
|
||||
|
||||
foreach ($this->additional as $field) {
|
||||
if ($field['visible'] ?? true) {
|
||||
|
@ -59,7 +59,6 @@ class Register extends Component
|
||||
|
||||
public function register(array $data)
|
||||
{
|
||||
nlog($data);
|
||||
|
||||
$service = new ClientRegisterService(
|
||||
company: $this->subscription->company,
|
||||
@ -68,13 +67,8 @@ class Register extends Component
|
||||
|
||||
$rules = $service->rules();
|
||||
|
||||
nlog($rules);
|
||||
|
||||
$data = Validator::make($data, $rules)->validate();
|
||||
|
||||
nlog("validated data");
|
||||
nlog($data);
|
||||
|
||||
$client = $service->createClient($data);
|
||||
$contact = $service->createClientContact($data, $client);
|
||||
|
||||
|
@ -202,6 +202,10 @@ class RegisterOrLogin extends Component
|
||||
|
||||
$this->register_fields = [...collect($this->subscription->company->client_registration_fields ?? [])->toArray()];
|
||||
|
||||
// if ($this->subscription->company->settings->client_portal_terms || $this->subscription->company->settings->client_portal_privacy_policy) {
|
||||
// $this->register_fields[] = ['key' => 'terms', 'required' => true, 'visible' => 'true'];
|
||||
// }
|
||||
|
||||
$first_gateway = collect($this->subscription->company->company_gateways)
|
||||
->sortBy('sort_order')
|
||||
->first();
|
||||
|
@ -258,6 +258,9 @@ class Activity extends StaticModel
|
||||
public const PAYMENT_EMAILED = 138;
|
||||
|
||||
public const VENDOR_NOTIFICATION_EMAIL = 139;
|
||||
|
||||
public const EMAIL_STATEMENT = 140;
|
||||
|
||||
|
||||
protected $casts = [
|
||||
'is_system' => 'boolean',
|
||||
@ -469,6 +472,8 @@ class Activity extends StaticModel
|
||||
':adjustment' => $translation = [substr($variable, 1) => [ 'label' => Number::formatMoney($this?->payment?->refunded, $this?->payment?->client ?? $this->company) ?? '', 'hashed_id' => '']],
|
||||
':ip' => $translation = [ 'ip' => $this->ip ?? ''],
|
||||
':contact' => $translation = $this->resolveContact(),
|
||||
':notes' => $translation = [ 'notes' => $this->notes ?? ''],
|
||||
|
||||
default => $translation = [],
|
||||
};
|
||||
|
||||
|
@ -164,6 +164,7 @@ class Quote extends BaseModel
|
||||
|
||||
protected $casts = [
|
||||
// 'date' => 'date:Y-m-d',
|
||||
'tax_data' => 'object',
|
||||
'due_date' => 'date:Y-m-d',
|
||||
'partial_due_date' => 'date:Y-m-d',
|
||||
'line_items' => 'object',
|
||||
|
@ -13,15 +13,16 @@
|
||||
namespace App\PaymentDrivers\Authorize;
|
||||
|
||||
use App\Models\Invoice;
|
||||
use App\PaymentDrivers\AuthorizePaymentDriver;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use net\authorize\api\contract\v1\CreateTransactionRequest;
|
||||
use net\authorize\api\contract\v1\ExtendedAmountType;
|
||||
use net\authorize\api\contract\v1\OpaqueDataType;
|
||||
use App\PaymentDrivers\Authorize\FDSReview;
|
||||
use net\authorize\api\contract\v1\OrderType;
|
||||
use App\PaymentDrivers\AuthorizePaymentDriver;
|
||||
use net\authorize\api\contract\v1\PaymentType;
|
||||
use net\authorize\api\contract\v1\SettingType;
|
||||
use net\authorize\api\contract\v1\OpaqueDataType;
|
||||
use net\authorize\api\contract\v1\ExtendedAmountType;
|
||||
use net\authorize\api\contract\v1\TransactionRequestType;
|
||||
use net\authorize\api\contract\v1\CreateTransactionRequest;
|
||||
use net\authorize\api\controller\CreateTransactionController;
|
||||
|
||||
/**
|
||||
@ -143,6 +144,12 @@ class AuthorizeTransaction
|
||||
nlog(' Code : '.$tresponse->getMessages()[0]->getCode());
|
||||
nlog(' Description : '.$tresponse->getMessages()[0]->getDescription());
|
||||
nlog(print_r($tresponse->getMessages()[0], 1));
|
||||
|
||||
if($tresponse->getResponseCode() == "4"){
|
||||
//notify user that this transaction is being held under FDS review:
|
||||
FDSReview::dispatch((string)$tresponse->getTransId(), $this->authorize->payment_hash, $this->authorize->company_gateway->company->db);
|
||||
}
|
||||
|
||||
} else {
|
||||
nlog('Transaction Failed ');
|
||||
if ($tresponse->getErrors() != null) {
|
||||
|
@ -13,14 +13,15 @@
|
||||
namespace App\PaymentDrivers\Authorize;
|
||||
|
||||
use App\Models\Invoice;
|
||||
use App\PaymentDrivers\AuthorizePaymentDriver;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use net\authorize\api\contract\v1\CreateTransactionRequest;
|
||||
use net\authorize\api\contract\v1\CustomerProfilePaymentType;
|
||||
use net\authorize\api\contract\v1\ExtendedAmountType;
|
||||
use App\PaymentDrivers\Authorize\FDSReview;
|
||||
use net\authorize\api\contract\v1\OrderType;
|
||||
use App\PaymentDrivers\AuthorizePaymentDriver;
|
||||
use net\authorize\api\contract\v1\ExtendedAmountType;
|
||||
use net\authorize\api\contract\v1\PaymentProfileType;
|
||||
use net\authorize\api\contract\v1\TransactionRequestType;
|
||||
use net\authorize\api\contract\v1\CreateTransactionRequest;
|
||||
use net\authorize\api\contract\v1\CustomerProfilePaymentType;
|
||||
use net\authorize\api\controller\CreateTransactionController;
|
||||
|
||||
/**
|
||||
@ -109,6 +110,12 @@ class ChargePaymentProfile
|
||||
nlog(' Code : '.$tresponse->getMessages()[0]->getCode());
|
||||
nlog(' Description : '.$tresponse->getMessages()[0]->getDescription());
|
||||
nlog(print_r($tresponse->getMessages()[0], 1));
|
||||
|
||||
if($tresponse->getResponseCode() == "4") {
|
||||
//notify user that this transaction is being held under FDS review:
|
||||
FDSReview::dispatch((string)$tresponse->getTransId(), $this->authorize?->payment_hash, $this->authorize->company_gateway->company->db);
|
||||
}
|
||||
|
||||
} else {
|
||||
nlog('Transaction Failed ');
|
||||
if ($tresponse->getErrors() != null) {
|
||||
|
67
app/PaymentDrivers/Authorize/FDSReview.php
Normal file
67
app/PaymentDrivers/Authorize/FDSReview.php
Normal file
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\PaymentDrivers\Authorize;
|
||||
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\PaymentHash;
|
||||
use App\Services\Email\Email;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use App\Services\Email\EmailObject;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Mail\Mailables\Address;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
|
||||
/*Multi Mailer implemented*/
|
||||
|
||||
class FDSReview implements ShouldQueue
|
||||
{
|
||||
use Dispatchable;
|
||||
use InteractsWithQueue;
|
||||
use Queueable;
|
||||
use SerializesModels;
|
||||
|
||||
public $tries = 1; //number of retries
|
||||
public $deleteWhenMissingModels = true;
|
||||
|
||||
public function __construct(private string $transaction_reference, private PaymentHash $payment_hash, private string $db)
|
||||
{
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
|
||||
MultiDB::setDB($this->db);
|
||||
|
||||
$company = $this->payment_hash->fee_invoice->company;
|
||||
|
||||
App::setLocale($company->getLocale());
|
||||
|
||||
$invoices_string = \implode(', ', collect($this->payment_hash->invoices())->pluck('invoice_number')->toArray()) ?: '';
|
||||
|
||||
$body = "Transaction {$this->transaction_reference} has been held for your review in Auth.net based on your Fraud Detection Settings.\n\n\nWe have marked invoices {$invoices_string} as paid in Invoice Ninja.\n\n\nPlease review this transaction in your auth.net account, and authorize if correct to ensure the transaction is finalized as expected.\n\n\nIf these charges need to be cancelled, you will need to delete the payments that have been created in Invoice Ninja.";
|
||||
|
||||
$mo = new EmailObject();
|
||||
$mo->subject = "Transaction {$this->transaction_reference} held for review by auth.net";
|
||||
$mo->body = nl2br($body);
|
||||
$mo->text_body = $body;
|
||||
$mo->company_key = $company->company_key;
|
||||
$mo->html_template = 'email.template.generic';
|
||||
$mo->to = [new Address($company->owner()->email, $company->owner()->present()->name())];
|
||||
|
||||
Email::dispatch($mo, $company);
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -52,25 +52,33 @@ class PaymentIntentFailureWebhook implements ShouldQueue
|
||||
|
||||
public function handle()
|
||||
{
|
||||
nlog("payment intent failed");
|
||||
|
||||
MultiDB::findAndSetDbByCompanyKey($this->company_key);
|
||||
nlog($this->stripe_request);
|
||||
|
||||
$company = Company::query()->where('company_key', $this->company_key)->first();
|
||||
|
||||
foreach ($this->stripe_request as $transaction) {
|
||||
if (array_key_exists('payment_intent', $transaction)) {
|
||||
$payment = Payment::query()
|
||||
->where('company_id', $company->id)
|
||||
->where(function ($query) use ($transaction) {
|
||||
$query->where('transaction_reference', $transaction['payment_intent'])
|
||||
->orWhere('transaction_reference', $transaction['id']);
|
||||
})
|
||||
->first();
|
||||
} else {
|
||||
$payment = Payment::query()
|
||||
->where('company_id', $company->id)
|
||||
->where('transaction_reference', $transaction['id'])
|
||||
->first();
|
||||
}
|
||||
|
||||
nlog($transaction);
|
||||
|
||||
$payment = Payment::query()
|
||||
->where('company_id', $company->id)
|
||||
->where(function ($query) use ($transaction) {
|
||||
|
||||
if(isset($transaction['payment_intent']))
|
||||
$query->where('transaction_reference', $transaction['payment_intent']);
|
||||
|
||||
if(isset($transaction['payment_intent']) && isset($transaction['id']))
|
||||
$query->orWhere('transaction_reference', $transaction['id']);
|
||||
|
||||
if(!isset($transaction['payment_intent']) && isset($transaction['id'])) {
|
||||
$query->where('transaction_reference', $transaction['id']);
|
||||
}
|
||||
|
||||
})
|
||||
->first();
|
||||
|
||||
if ($payment) {
|
||||
$client = $payment->client;
|
||||
|
@ -64,17 +64,28 @@ class PaymentIntentProcessingWebhook implements ShouldQueue
|
||||
$company = Company::query()->where('company_key', $this->company_key)->first();
|
||||
|
||||
foreach ($this->stripe_request as $transaction) {
|
||||
if (array_key_exists('payment_intent', $transaction)) {
|
||||
$payment = Payment::query()
|
||||
->where('company_id', $company->id)
|
||||
->where('transaction_reference', $transaction['payment_intent'])
|
||||
->first();
|
||||
} else {
|
||||
$payment = Payment::query()
|
||||
->where('company_id', $company->id)
|
||||
->where('transaction_reference', $transaction['id'])
|
||||
->first();
|
||||
}
|
||||
|
||||
|
||||
$payment = Payment::query()
|
||||
->where('company_id', $company->id)
|
||||
->where(function ($query) use ($transaction) {
|
||||
|
||||
if(isset($transaction['payment_intent'])) {
|
||||
$query->where('transaction_reference', $transaction['payment_intent']);
|
||||
}
|
||||
|
||||
if(isset($transaction['payment_intent']) && isset($transaction['id'])) {
|
||||
$query->orWhere('transaction_reference', $transaction['id']);
|
||||
}
|
||||
|
||||
if(!isset($transaction['payment_intent']) && isset($transaction['id'])) {
|
||||
$query->where('transaction_reference', $transaction['id']);
|
||||
}
|
||||
|
||||
})
|
||||
->first();
|
||||
|
||||
|
||||
|
||||
if ($payment) {
|
||||
$payment->status_id = Payment::STATUS_PENDING;
|
||||
|
@ -63,17 +63,27 @@ class PaymentIntentWebhook implements ShouldQueue
|
||||
$company = Company::query()->where('company_key', $this->company_key)->first();
|
||||
|
||||
foreach ($this->stripe_request as $transaction) {
|
||||
if (array_key_exists('payment_intent', $transaction)) {
|
||||
$payment = Payment::query()
|
||||
->where('company_id', $company->id)
|
||||
->where('transaction_reference', $transaction['payment_intent'])
|
||||
->first();
|
||||
} else {
|
||||
$payment = Payment::query()
|
||||
->where('company_id', $company->id)
|
||||
->where('transaction_reference', $transaction['id'])
|
||||
->first();
|
||||
}
|
||||
|
||||
$payment = Payment::query()
|
||||
->where('company_id', $company->id)
|
||||
->where(function ($query) use ($transaction) {
|
||||
|
||||
if(isset($transaction['payment_intent'])) {
|
||||
$query->where('transaction_reference', $transaction['payment_intent']);
|
||||
}
|
||||
|
||||
if(isset($transaction['payment_intent']) && isset($transaction['id'])) {
|
||||
$query->orWhere('transaction_reference', $transaction['id']);
|
||||
}
|
||||
|
||||
if(!isset($transaction['payment_intent']) && isset($transaction['id'])) {
|
||||
$query->where('transaction_reference', $transaction['id']);
|
||||
}
|
||||
|
||||
})
|
||||
->first();
|
||||
|
||||
|
||||
|
||||
if ($payment) {
|
||||
$payment->status_id = Payment::STATUS_COMPLETED;
|
||||
|
@ -680,7 +680,7 @@ class StripePaymentDriver extends BaseDriver
|
||||
}
|
||||
|
||||
if ($request->type === 'payment_intent.processing') {
|
||||
PaymentIntentProcessingWebhook::dispatch($request->data, $request->company_key, $this->company_gateway->id)->delay(now()->addSeconds(2));
|
||||
PaymentIntentProcessingWebhook::dispatch($request->data, $request->company_key, $this->company_gateway->id)->delay(now()->addSeconds(rand(10,12)));
|
||||
return response()->json([], 200);
|
||||
}
|
||||
|
||||
@ -692,7 +692,7 @@ class StripePaymentDriver extends BaseDriver
|
||||
}
|
||||
|
||||
if ($request->type === 'payment_intent.partially_funded') {
|
||||
PaymentIntentPartiallyFundedWebhook::dispatch($request->data, $request->company_key, $this->company_gateway->id)->delay(now()->addSeconds(rand(5, 10)));
|
||||
PaymentIntentPartiallyFundedWebhook::dispatch($request->data, $request->company_key, $this->company_gateway->id)->delay(now()->addSeconds(rand(10, 15)));
|
||||
|
||||
return response()->json([], 200);
|
||||
}
|
||||
@ -705,20 +705,27 @@ class StripePaymentDriver extends BaseDriver
|
||||
|
||||
if ($request->type === 'charge.succeeded') {
|
||||
foreach ($request->data as $transaction) {
|
||||
if (array_key_exists('payment_intent', $transaction) && $transaction['payment_intent']) {
|
||||
$payment = Payment::query()
|
||||
// ->where('company_id', $request->getCompany()->id)
|
||||
->where(function ($query) use ($transaction) {
|
||||
$query->where('transaction_reference', $transaction['payment_intent'])
|
||||
->orWhere('transaction_reference', $transaction['id']);
|
||||
})
|
||||
->first();
|
||||
} else {
|
||||
$payment = Payment::query()
|
||||
// ->where('company_id', $request->getCompany()->id)
|
||||
->where('transaction_reference', $transaction['id'])
|
||||
->first();
|
||||
}
|
||||
|
||||
|
||||
$payment = Payment::query()
|
||||
->where('company_id', $this->company_gateway->company_id)
|
||||
->where(function ($query) use ($transaction) {
|
||||
|
||||
if(isset($transaction['payment_intent'])) {
|
||||
$query->where('transaction_reference', $transaction['payment_intent']);
|
||||
}
|
||||
|
||||
if(isset($transaction['payment_intent']) && isset($transaction['id'])) {
|
||||
$query->orWhere('transaction_reference', $transaction['id']);
|
||||
}
|
||||
|
||||
if(!isset($transaction['payment_intent']) && isset($transaction['id'])) {
|
||||
$query->where('transaction_reference', $transaction['id']);
|
||||
}
|
||||
|
||||
})
|
||||
->first();
|
||||
|
||||
|
||||
if ($payment) {
|
||||
|
||||
@ -745,19 +752,28 @@ class StripePaymentDriver extends BaseDriver
|
||||
], $this->stripe_connect_auth);
|
||||
|
||||
if ($charge->captured) {
|
||||
$payment = false;
|
||||
|
||||
|
||||
$payment = Payment::query()
|
||||
->where('company_id', $this->company_gateway->company_id)
|
||||
->where(function ($query) use ($transaction) {
|
||||
|
||||
if(isset($transaction['payment_intent'])) {
|
||||
$query->where('transaction_reference', $transaction['payment_intent']);
|
||||
}
|
||||
|
||||
if(isset($transaction['payment_intent']) && isset($transaction['id'])) {
|
||||
$query->orWhere('transaction_reference', $transaction['id']);
|
||||
}
|
||||
|
||||
if(!isset($transaction['payment_intent']) && isset($transaction['id'])) {
|
||||
$query->where('transaction_reference', $transaction['id']);
|
||||
}
|
||||
|
||||
})
|
||||
->first();
|
||||
|
||||
|
||||
if (isset($transaction['payment_intent'])) {
|
||||
$payment = Payment::query()
|
||||
->where('transaction_reference', $transaction['payment_intent'])
|
||||
->where('company_id', $request->getCompany()->id)
|
||||
->first();
|
||||
} elseif (isset($transaction['id'])) {
|
||||
$payment = Payment::query()
|
||||
->where('transaction_reference', $transaction['id'])
|
||||
->where('company_id', $request->getCompany()->id)
|
||||
->first();
|
||||
}
|
||||
|
||||
if ($payment) {
|
||||
$payment->status_id = Payment::STATUS_COMPLETED;
|
||||
|
@ -97,6 +97,7 @@ use App\Events\RecurringQuote\RecurringQuoteWasCreated;
|
||||
use App\Events\RecurringQuote\RecurringQuoteWasDeleted;
|
||||
use App\Events\RecurringQuote\RecurringQuoteWasRestored;
|
||||
use App\Events\RecurringQuote\RecurringQuoteWasUpdated;
|
||||
use App\Events\Statement\StatementWasEmailed;
|
||||
use App\Events\Subscription\SubscriptionWasArchived;
|
||||
use App\Events\Subscription\SubscriptionWasCreated;
|
||||
use App\Events\Subscription\SubscriptionWasDeleted;
|
||||
@ -222,6 +223,7 @@ use App\Listeners\RecurringQuote\RecurringQuoteDeletedActivity;
|
||||
use App\Listeners\RecurringQuote\RecurringQuoteRestoredActivity;
|
||||
use App\Listeners\RecurringQuote\UpdateRecurringQuoteActivity;
|
||||
use App\Listeners\SendVerificationNotification;
|
||||
use App\Listeners\Statement\StatementEmailedActivity;
|
||||
use App\Listeners\User\ArchivedUserActivity;
|
||||
use App\Listeners\User\CreatedUserActivity;
|
||||
use App\Listeners\User\DeletedUserActivity;
|
||||
@ -577,6 +579,9 @@ class EventServiceProvider extends ServiceProvider
|
||||
RecurringInvoiceWasRestored::class => [
|
||||
RecurringInvoiceRestoredActivity::class,
|
||||
],
|
||||
StatementWasEmailed::class => [
|
||||
StatementEmailedActivity::class,
|
||||
],
|
||||
TaskWasCreated::class => [
|
||||
CreatedTaskActivity::class,
|
||||
],
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
namespace App\Services\Client;
|
||||
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\Number;
|
||||
use App\Models\Client;
|
||||
use App\Models\Credit;
|
||||
@ -23,6 +24,7 @@ use App\Services\Email\EmailObject;
|
||||
use App\Utils\Traits\GeneratesCounter;
|
||||
use Illuminate\Mail\Mailables\Address;
|
||||
use Illuminate\Database\QueryException;
|
||||
use App\Events\Statement\StatementWasEmailed;
|
||||
|
||||
class ClientService
|
||||
{
|
||||
@ -275,6 +277,9 @@ class ClientService
|
||||
|
||||
$email_object = $this->buildStatementMailableData($pdf);
|
||||
Email::dispatch($email_object, $this->client->company);
|
||||
|
||||
event(new StatementWasEmailed($this->client, $this->client->company, $this->client_end_date, Ninja::eventVars()));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -307,8 +312,8 @@ class ClientService
|
||||
$email_object->attachments = [['file' => base64_encode($pdf), 'name' => ctrans('texts.statement') . ".pdf"]];
|
||||
$email_object->client_id = $this->client->id;
|
||||
$email_object->entity_class = Invoice::class;
|
||||
$email_object->entity_id = $invoice->id ?? null;
|
||||
$email_object->invitation_id = $invoice->invitations->first()->id ?? null;
|
||||
$email_object->entity_id = $invoice?->id ?? null;
|
||||
$email_object->invitation_id = $invoice?->invitations?->first()?->id ?? null;
|
||||
$email_object->email_template_subject = 'email_subject_statement';
|
||||
$email_object->email_template_body = 'email_template_statement';
|
||||
$email_object->variables = [
|
||||
|
@ -44,6 +44,8 @@ class EmailStatementService
|
||||
|
||||
$query->cursor()
|
||||
->each(function ($_client) {
|
||||
|
||||
/**@var \App\Models\Client $_client */
|
||||
$this->client = $_client;
|
||||
|
||||
//work out the date range
|
||||
|
@ -90,4 +90,18 @@ trait CleanLineItems
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
private function entityTotalAmount($items)
|
||||
{
|
||||
$total = 0;
|
||||
|
||||
foreach($items as $item)
|
||||
{
|
||||
$total += ($item['cost'] * $item['quantity']);
|
||||
}
|
||||
|
||||
nlog($total);
|
||||
|
||||
return $total;
|
||||
}
|
||||
}
|
||||
|
@ -17,8 +17,8 @@ return [
|
||||
'require_https' => env('REQUIRE_HTTPS', true),
|
||||
'app_url' => rtrim(env('APP_URL', ''), '/'),
|
||||
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
|
||||
'app_version' => env('APP_VERSION', '5.8.53'),
|
||||
'app_tag' => env('APP_TAG', '5.8.53'),
|
||||
'app_version' => env('APP_VERSION', '5.8.54'),
|
||||
'app_tag' => env('APP_TAG', '5.8.54'),
|
||||
'minimum_client_version' => '5.0.16',
|
||||
'terms_version' => '1.0.1',
|
||||
'api_secret' => env('API_SECRET', false),
|
||||
|
@ -4010,7 +4010,7 @@ $lang = array(
|
||||
'user_detached' => 'فصل المستخدم عن الشركة',
|
||||
'create_webhook_failure' => 'فشل إنشاء Webhook',
|
||||
'payment_message_extended' => 'شكرًا لك على دفعك لـ :amount مقابل :invoice',
|
||||
'online_payments_minimum_note' => 'ملاحظة: يتم دعم المدفوعات عبر الإنترنت فقط إذا كان المبلغ أكبر من دولار واحد أو ما يعادله بالعملة.',
|
||||
'online_payments_minimum_note' => 'Note: Online payments are supported only if amount is larger than $1 or currency equivalent.',
|
||||
'payment_token_not_found' => 'لم يتم العثور على رمز الدفع ، يرجى المحاولة مرة أخرى. إذا استمرت المشكلة ، فحاول استخدام طريقة دفع أخرى',
|
||||
'vendor_address1' => 'شارع البائع',
|
||||
'vendor_address2' => 'بائع شقة / جناح',
|
||||
@ -5278,6 +5278,9 @@ $lang = array(
|
||||
'rappen_rounding_help' => 'جولة المبلغ إلى 5 سنتات',
|
||||
'assign_group' => 'تعيين المجموعة',
|
||||
'paypal_advanced_cards' => 'Advanced Card Payments',
|
||||
'local_domain_help' => 'EHLO domain (optional)',
|
||||
'port_help' => 'ie. 25,587,465',
|
||||
'host_help' => 'ie. smtp.gmail.com',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -4029,7 +4029,7 @@ $lang = array(
|
||||
'user_detached' => 'User detached from company',
|
||||
'create_webhook_failure' => 'Failed to create Webhook',
|
||||
'payment_message_extended' => 'Thank you for your payment of :amount for :invoice',
|
||||
'online_payments_minimum_note' => 'Note: Online payments are supported only if amount is bigger than $1 or currency equivalent.',
|
||||
'online_payments_minimum_note' => 'Note: Online payments are supported only if amount is larger than $1 or currency equivalent.',
|
||||
'payment_token_not_found' => 'Payment token not found, please try again. If an issue still persist, try with another payment method',
|
||||
'vendor_address1' => 'Vendor Street',
|
||||
'vendor_address2' => 'Vendor Apt/Suite',
|
||||
@ -5297,6 +5297,9 @@ $lang = array(
|
||||
'rappen_rounding_help' => 'Import rodó a 5 cèntims',
|
||||
'assign_group' => 'Assigna un grup',
|
||||
'paypal_advanced_cards' => 'Advanced Card Payments',
|
||||
'local_domain_help' => 'EHLO domain (optional)',
|
||||
'port_help' => 'ie. 25,587,465',
|
||||
'host_help' => 'ie. smtp.gmail.com',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -4028,7 +4028,7 @@ $lang = array(
|
||||
'user_detached' => 'Bruger løsrevet fra selskabet',
|
||||
'create_webhook_failure' => 'Opret Webhook mislykkedes',
|
||||
'payment_message_extended' => 'Tak for din Betaling på :amount for :invoice',
|
||||
'online_payments_minimum_note' => 'Bemærk : Online Betalinger understøttes kun, hvis Beløb er større end $1 eller tilsvarende i valuta.',
|
||||
'online_payments_minimum_note' => 'Note: Online payments are supported only if amount is larger than $1 or currency equivalent.',
|
||||
'payment_token_not_found' => 'Betaling blev ikke fundet, prøv venligst igen. Hvis et problem stadig fortsætter, kan du prøve med en anden Betaling',
|
||||
'vendor_address1' => 'Sælger Gade',
|
||||
'vendor_address2' => 'Sælger Apt/Suite',
|
||||
@ -5296,6 +5296,9 @@ $lang = array(
|
||||
'rappen_rounding_help' => 'Rund Beløb til 5 øre',
|
||||
'assign_group' => 'Tildel gruppe',
|
||||
'paypal_advanced_cards' => 'Advanced Card Payments',
|
||||
'local_domain_help' => 'EHLO domain (optional)',
|
||||
'port_help' => 'ie. 25,587,465',
|
||||
'host_help' => 'ie. smtp.gmail.com',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -4031,7 +4031,7 @@ https://invoiceninja.github.io/docs/migration/#troubleshooting',
|
||||
'user_detached' => 'Nutzer wurden vom Unternehmen entkoppelt',
|
||||
'create_webhook_failure' => 'Webhook konnte nicht erstellt werden',
|
||||
'payment_message_extended' => 'Vielen Dank für Ihre Zahlung von :amount für die Rechnung :invoice',
|
||||
'online_payments_minimum_note' => 'Hinweis: Online-Zahlungen werden nur unterstützt, wenn der Betrag größer als 1€ oder der entsprechende Währungsbetrag ist.',
|
||||
'online_payments_minimum_note' => 'Note: Online payments are supported only if amount is larger than $1 or currency equivalent.',
|
||||
'payment_token_not_found' => 'Zahlungstoken nicht gefunden, bitte versuchen Sie es erneut. Wenn das Problem weiterhin besteht, versuchen Sie es mit einer anderen Zahlungsmethode',
|
||||
'vendor_address1' => 'Straße Lieferant',
|
||||
'vendor_address2' => 'Lieferant Apt/Suite',
|
||||
@ -5301,6 +5301,9 @@ Leistungsempfängers',
|
||||
'rappen_rounding_help' => 'Betrag auf 5 Cent aufrunden',
|
||||
'assign_group' => 'Gruppe zuweisen',
|
||||
'paypal_advanced_cards' => 'Advanced Card Payments',
|
||||
'local_domain_help' => 'EHLO domain (optional)',
|
||||
'port_help' => 'ie. 25,587,465',
|
||||
'host_help' => 'ie. smtp.gmail.com',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -5300,6 +5300,10 @@ $lang = array(
|
||||
'local_domain_help' => 'EHLO domain (optional)',
|
||||
'port_help' => 'ie. 25,587,465',
|
||||
'host_help' => 'ie. smtp.gmail.com',
|
||||
'always_show_required_fields' => 'Allows show required fields form',
|
||||
'always_show_required_fields_help' => 'Displays the required fields form always at checkout',
|
||||
'advanced_cards' => 'Advanced Cards',
|
||||
'activity_140' => 'Statement sent to :client',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -4028,7 +4028,7 @@ $lang = array(
|
||||
'user_detached' => 'Usuario desvinculado de la empresa',
|
||||
'create_webhook_failure' => 'No se pudo crear el webhook',
|
||||
'payment_message_extended' => 'Gracias por su pago de :amount por :invoice',
|
||||
'online_payments_minimum_note' => 'Nota: Los pagos en línea solo se admiten si el monto es superior a $ 1 o su equivalente en moneda.',
|
||||
'online_payments_minimum_note' => 'Note: Online payments are supported only if amount is larger than $1 or currency equivalent.',
|
||||
'payment_token_not_found' => 'No se encontró el token de pago, inténtelo de nuevo. Si el problema persiste, intente con otro método de pago',
|
||||
'vendor_address1' => 'Calle del vendedor',
|
||||
'vendor_address2' => 'Proveedor Apt/Suite',
|
||||
@ -5296,6 +5296,9 @@ $lang = array(
|
||||
'rappen_rounding_help' => 'Monto redondo a 5 centavos',
|
||||
'assign_group' => 'Asignar grupo',
|
||||
'paypal_advanced_cards' => 'Advanced Card Payments',
|
||||
'local_domain_help' => 'EHLO domain (optional)',
|
||||
'port_help' => 'ie. 25,587,465',
|
||||
'host_help' => 'ie. smtp.gmail.com',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -2193,7 +2193,7 @@ Una vez que tenga los montos, vuelva a esta página de métodos de pago y haga c
|
||||
'mailgun_private_key' => 'Mailgun Private Key',
|
||||
'brevo_domain' => 'Dominio Brevo',
|
||||
'brevo_private_key' => 'Clave privada de Brevo',
|
||||
'send_test_email' => 'Send Test Email',
|
||||
'send_test_email' => 'Enviar correo electrónico de prueba',
|
||||
'select_label' => 'Seleccionar etiqueta',
|
||||
'label' => 'Etiqueta',
|
||||
'service' => 'Servicio',
|
||||
@ -4025,7 +4025,7 @@ Una vez que tenga los montos, vuelva a esta página de métodos de pago y haga c
|
||||
'user_detached' => 'Usuario desligado de la compañía',
|
||||
'create_webhook_failure' => 'Fallo al crear Webhook',
|
||||
'payment_message_extended' => 'Gracias por su pago de :amount para :invoice',
|
||||
'online_payments_minimum_note' => 'Nota: Los pagos online están soportados si la cantidad es mayor que $1 o moneda equivalente.',
|
||||
'online_payments_minimum_note' => 'Nota: Los pagos en línea solo se admiten si el importe es superior a 1 € o moneda equivalente.',
|
||||
'payment_token_not_found' => 'No se ha encontrado el token de pago, inténtelo de nuevo. Si el problema persiste, inténtelo con otro método de pago',
|
||||
'vendor_address1' => 'Calle de Proveedor',
|
||||
'vendor_address2' => 'Bloq/Pta del Proveedor',
|
||||
@ -4166,7 +4166,7 @@ Una vez que tenga los montos, vuelva a esta página de métodos de pago y haga c
|
||||
'one_time_purchases' => 'Compras únicas',
|
||||
'recurring_purchases' => 'Pagos recurrentes',
|
||||
'you_might_be_interested_in_following' => 'Puede que te interese lo siguiente',
|
||||
'quotes_with_status_sent_can_be_approved' => 'Only quotes with "Sent" status can be approved. Expired quotes cannot be approved.',
|
||||
'quotes_with_status_sent_can_be_approved' => 'Sólo se pueden aprobar presupuestos con estado "Enviado". Los presupuestos vencidos no se pueden aprobar.',
|
||||
'no_quotes_available_for_download' => 'No hay presupuestos disponibles para descargar.',
|
||||
'copyright' => 'Derechos de autor',
|
||||
'user_created_user' => ':user creó :created_user a las :time',
|
||||
@ -5292,8 +5292,11 @@ De lo contrario, este campo deberá dejarse en blanco.',
|
||||
'flutter_web_warning' => 'Recomendamos utilizar la nueva aplicación web o la aplicación de escritorio para obtener el mejor rendimiento.',
|
||||
'rappen_rounding' => 'Redondeo de rappen',
|
||||
'rappen_rounding_help' => 'Cantidad redonda a 5 centimos',
|
||||
'assign_group' => 'Assign group',
|
||||
'paypal_advanced_cards' => 'Advanced Card Payments',
|
||||
'assign_group' => 'Asignar grupo',
|
||||
'paypal_advanced_cards' => 'Pagos avanzados con tarjeta',
|
||||
'local_domain_help' => 'Dominio EHLO (opcional)',
|
||||
'port_help' => 'Ej. 25.587.465',
|
||||
'host_help' => 'Ej. smtp.gmail.com',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -4029,7 +4029,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
|
||||
'user_detached' => 'Utilisateur détaché de l\'entreprise',
|
||||
'create_webhook_failure' => 'Échec de la création du Webhook',
|
||||
'payment_message_extended' => 'Merci pour votre paiement de :amount pour :invoice',
|
||||
'online_payments_minimum_note' => 'Remarque : Les paiements en ligne ne sont pris en charge que si le montant est supérieur à 1 $ ou l\'équivalent en devise.',
|
||||
'online_payments_minimum_note' => 'Note: Online payments are supported only if amount is larger than $1 or currency equivalent.',
|
||||
'payment_token_not_found' => 'Le jeton de paiement est introuvable. Veuillez essayer de nouveau. Si le problème persiste, essayez avec un autre mode de paiement',
|
||||
'vendor_address1' => 'Rue du fournisseur',
|
||||
'vendor_address2' => 'Appt/Bâtiment du fournisseur',
|
||||
@ -5297,6 +5297,9 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
|
||||
'rappen_rounding_help' => 'Montant rond à 5 centimes',
|
||||
'assign_group' => 'Attribuer un groupe',
|
||||
'paypal_advanced_cards' => 'Advanced Card Payments',
|
||||
'local_domain_help' => 'EHLO domain (optional)',
|
||||
'port_help' => 'ie. 25,587,465',
|
||||
'host_help' => 'ie. smtp.gmail.com',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -4026,7 +4026,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
|
||||
'user_detached' => 'L\'utilisateur a été détaché de l\'entreprise',
|
||||
'create_webhook_failure' => 'Création Webhook impossible',
|
||||
'payment_message_extended' => 'Merci pour votre paiement d\'un montant de :amount',
|
||||
'online_payments_minimum_note' => 'Note: Les paiements en ligne sont acceptés seulement si le montant est plus élevé que 1$ ou en devise équivalente.',
|
||||
'online_payments_minimum_note' => 'Note: Les paiements en ligne sont possibles seulement si le montant est supérieur à 1$ ou l\'équivalent en devise.',
|
||||
'payment_token_not_found' => 'Le jeton de paiement est introuvable. Veuillez essayer de nouveau. Si le problème persiste, essayez avec un autre mode de paiement',
|
||||
'vendor_address1' => 'Rue du fournisseur',
|
||||
'vendor_address2' => 'App du fournisseur',
|
||||
@ -5294,6 +5294,9 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
|
||||
'rappen_rounding_help' => 'Arrondir au 5 cents',
|
||||
'assign_group' => 'Assigner un groupe',
|
||||
'paypal_advanced_cards' => 'Paiements avancés pour carte',
|
||||
'local_domain_help' => 'Domaine EHLO (facultatif)',
|
||||
'port_help' => 'ex. 25,587,465',
|
||||
'host_help' => 'ex. smtp.gmail.com',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -4026,7 +4026,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
|
||||
'user_detached' => 'L\'utilisateur a été détaché de l\'entreprise',
|
||||
'create_webhook_failure' => 'Création Webhook impossible',
|
||||
'payment_message_extended' => 'Merci pour votre paiement d\'un montant de :amount',
|
||||
'online_payments_minimum_note' => 'Note: Les paiements en ligne sont acceptés seulement si le montant est plus élevé que 1$ ou en devise équivalente.',
|
||||
'online_payments_minimum_note' => 'Note: Online payments are supported only if amount is larger than $1 or currency equivalent.',
|
||||
'payment_token_not_found' => 'Le jeton de paiement est introuvable. Veuillez essayer de nouveau. Si le problème persiste, essayez avec un autre mode de paiement',
|
||||
'vendor_address1' => 'Rue du fournisseur',
|
||||
'vendor_address2' => 'App du fournisseur',
|
||||
@ -5294,6 +5294,9 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
|
||||
'rappen_rounding_help' => 'Montant rond à 5 centimes',
|
||||
'assign_group' => 'Attribuer un groupe',
|
||||
'paypal_advanced_cards' => 'Advanced Card Payments',
|
||||
'local_domain_help' => 'EHLO domain (optional)',
|
||||
'port_help' => 'ie. 25,587,465',
|
||||
'host_help' => 'ie. smtp.gmail.com',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -4027,7 +4027,7 @@ $lang = array(
|
||||
'user_detached' => 'משתמש מנותק מהחברה',
|
||||
'create_webhook_failure' => 'יצירת Webhook נכשלה',
|
||||
'payment_message_extended' => 'תודה על התשלום בסך :amount עבור :invoice',
|
||||
'online_payments_minimum_note' => 'הערה: תשלומים מקוונים נתמכים רק אם הסכום גדול מ-$1 או שווה ערך במטבע.',
|
||||
'online_payments_minimum_note' => 'Note: Online payments are supported only if amount is larger than $1 or currency equivalent.',
|
||||
'payment_token_not_found' => 'אסימון תשלום לא נמצא, אנא נסה שוב. אם הבעיה עדיין נמשכת, נסה עם אמצעי תשלום אחר',
|
||||
'vendor_address1' => 'רחוב הספקים',
|
||||
'vendor_address2' => 'דירת ספק/סוויטה',
|
||||
@ -5295,6 +5295,9 @@ $lang = array(
|
||||
'rappen_rounding_help' => 'סכום עגול עד 5 סנט',
|
||||
'assign_group' => 'הקצה קבוצה',
|
||||
'paypal_advanced_cards' => 'Advanced Card Payments',
|
||||
'local_domain_help' => 'EHLO domain (optional)',
|
||||
'port_help' => 'ie. 25,587,465',
|
||||
'host_help' => 'ie. smtp.gmail.com',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -4013,7 +4013,7 @@ adva :date',
|
||||
'user_detached' => 'Felhasználó leválasztva',
|
||||
'create_webhook_failure' => 'Webhook létrehozása sikertelen',
|
||||
'payment_message_extended' => 'Fizetési üzenet kiterjesztve',
|
||||
'online_payments_minimum_note' => 'Online fizetések minimális megjegyzése',
|
||||
'online_payments_minimum_note' => 'Note: Online payments are supported only if amount is larger than $1 or currency equivalent.',
|
||||
'payment_token_not_found' => 'Fizetési token nem található',
|
||||
'vendor_address1' => 'Szállító címe 1',
|
||||
'vendor_address2' => 'Szállító címe 2',
|
||||
@ -5281,6 +5281,9 @@ adva :date',
|
||||
'rappen_rounding_help' => 'Kerek összeg 5 cent',
|
||||
'assign_group' => 'Csoport hozzárendelése',
|
||||
'paypal_advanced_cards' => 'Advanced Card Payments',
|
||||
'local_domain_help' => 'EHLO domain (optional)',
|
||||
'port_help' => 'ie. 25,587,465',
|
||||
'host_help' => 'ie. smtp.gmail.com',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -4020,7 +4020,7 @@ $lang = array(
|
||||
'user_detached' => 'Utente separato dall\'azienda',
|
||||
'create_webhook_failure' => 'Impossibile creare il webhook',
|
||||
'payment_message_extended' => 'Grazie per il pagamento di :amount per :invoice',
|
||||
'online_payments_minimum_note' => 'Nota: i pagamenti online sono supportati solo se l'importo è superiore a $ 1 o equivalente in valuta.',
|
||||
'online_payments_minimum_note' => 'Note: Online payments are supported only if amount is larger than $1 or currency equivalent.',
|
||||
'payment_token_not_found' => 'Token di pagamento non trovato, riprova. Se il problema persiste, prova con un altro metodo di pagamento',
|
||||
'vendor_address1' => 'Via Fornitore',
|
||||
'vendor_address2' => 'Scala/Appartamento Fornitore',
|
||||
@ -5288,6 +5288,9 @@ $lang = array(
|
||||
'rappen_rounding_help' => 'Ammontare tondo a 5 centesimi',
|
||||
'assign_group' => 'Assegna gruppo',
|
||||
'paypal_advanced_cards' => 'Advanced Card Payments',
|
||||
'local_domain_help' => 'EHLO domain (optional)',
|
||||
'port_help' => 'ie. 25,587,465',
|
||||
'host_help' => 'ie. smtp.gmail.com',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -2197,7 +2197,7 @@ $lang = array(
|
||||
'mailgun_private_key' => 'Mailgun Private Key',
|
||||
'brevo_domain' => 'Brevo Domain',
|
||||
'brevo_private_key' => 'Brevo Private Key',
|
||||
'send_test_email' => 'Send test email',
|
||||
'send_test_email' => 'Send Test Email',
|
||||
'select_label' => 'Select Label',
|
||||
'label' => 'Label',
|
||||
'service' => 'Service',
|
||||
@ -4029,7 +4029,7 @@ $lang = array(
|
||||
'user_detached' => 'User detached from company',
|
||||
'create_webhook_failure' => 'Failed to create Webhook',
|
||||
'payment_message_extended' => ':invoice に対して :amount をお支払いいただきありがとうございます。',
|
||||
'online_payments_minimum_note' => '注: オンラインでの支払いは、金額が 1 ドルまたは同等の通貨を超える場合にのみサポートされます。',
|
||||
'online_payments_minimum_note' => 'Note: Online payments are supported only if amount is larger than $1 or currency equivalent.',
|
||||
'payment_token_not_found' => 'Payment token not found, please try again. If an issue still persist, try with another payment method',
|
||||
'vendor_address1' => 'Vendor Street',
|
||||
'vendor_address2' => 'Vendor Apt/Suite',
|
||||
@ -4170,7 +4170,7 @@ $lang = array(
|
||||
'one_time_purchases' => 'One time purchases',
|
||||
'recurring_purchases' => 'Recurring purchases',
|
||||
'you_might_be_interested_in_following' => 'You might be interested in the following',
|
||||
'quotes_with_status_sent_can_be_approved' => 'Only quotes with "Sent" status can be approved.',
|
||||
'quotes_with_status_sent_can_be_approved' => 'Only quotes with "Sent" status can be approved. Expired quotes cannot be approved.',
|
||||
'no_quotes_available_for_download' => 'No quotes available for download.',
|
||||
'copyright' => 'Copyright',
|
||||
'user_created_user' => ':user は :created_user を :time に作成しました',
|
||||
@ -5295,6 +5295,11 @@ $lang = array(
|
||||
'flutter_web_warning' => 'We recommend using the new web app or the desktop app for the best performance',
|
||||
'rappen_rounding' => 'Rappen Rounding',
|
||||
'rappen_rounding_help' => 'Round amount to 5 cents',
|
||||
'assign_group' => 'Assign group',
|
||||
'paypal_advanced_cards' => 'Advanced Card Payments',
|
||||
'local_domain_help' => 'EHLO domain (optional)',
|
||||
'port_help' => 'ie. 25,587,465',
|
||||
'host_help' => 'ie. smtp.gmail.com',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -4009,7 +4009,7 @@ $lang = array(
|
||||
'user_detached' => 'អ្នកប្រើប្រាស់ត្រូវបានផ្តាច់ចេញពីក្រុមហ៊ុន',
|
||||
'create_webhook_failure' => 'បរាជ័យក្នុងការបង្កើត Webhook',
|
||||
'payment_message_extended' => 'សូមអរគុណចំពោះការបង់ប្រាក់របស់អ្នក :amount សម្រាប់ :invoice',
|
||||
'online_payments_minimum_note' => 'ចំណាំ៖ ការទូទាត់តាមអ៊ីនធឺណិតត្រូវបានគាំទ្រលុះត្រាតែចំនួនទឹកប្រាក់ធំជាង $1 ឬសមមូលរូបិយប័ណ្ណ។',
|
||||
'online_payments_minimum_note' => 'Note: Online payments are supported only if amount is larger than $1 or currency equivalent.',
|
||||
'payment_token_not_found' => 'រកមិនឃើញនិមិត្តសញ្ញាបង់ប្រាក់ទេ សូមព្យាយាមម្តងទៀត។ ប្រសិនបើបញ្ហានៅតែកើតមាន សូមសាកល្បងជាមួយវិធីបង់ប្រាក់ផ្សេងទៀត។',
|
||||
'vendor_address1' => 'ផ្លូវអ្នកលក់',
|
||||
'vendor_address2' => 'អ្នកលក់ Apt/Suite',
|
||||
@ -5277,6 +5277,9 @@ $lang = array(
|
||||
'rappen_rounding_help' => 'ចំនួនទឹកប្រាក់ជុំដល់ 5 សេន',
|
||||
'assign_group' => 'ចាត់តាំងក្រុម',
|
||||
'paypal_advanced_cards' => 'Advanced Card Payments',
|
||||
'local_domain_help' => 'EHLO domain (optional)',
|
||||
'port_help' => 'ie. 25,587,465',
|
||||
'host_help' => 'ie. smtp.gmail.com',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -4029,7 +4029,7 @@ $lang = array(
|
||||
'user_detached' => 'ຜູ້ໃຊ້ຖືກແຍກອອກຈາກບໍລິສັດ',
|
||||
'create_webhook_failure' => 'ລົ້ມເຫລວໃນການສ້າງ Webhook',
|
||||
'payment_message_extended' => 'ຂໍຂອບໃຈສຳລັບການຈ່າຍເງິນ:ຈຳນວນເງິນ:ໃບແຈ້ງໜີ້',
|
||||
'online_payments_minimum_note' => 'ໝາຍເຫດ: ການຈ່າຍເງິນອອນລາຍແມ່ນຮອງຮັບໄດ້ພຽງແຕ່ຖ້າຈຳນວນເງິນໃຫຍ່ກວ່າ $1 ຫຼື ທຽບເທົ່າສະກຸນເງິນເທົ່ານັ້ນ.',
|
||||
'online_payments_minimum_note' => 'Note: Online payments are supported only if amount is larger than $1 or currency equivalent.',
|
||||
'payment_token_not_found' => 'ບໍ່ພົບໂທເຄັນການຈ່າຍເງິນ, ກະລຸນາລອງໃໝ່ອີກຄັ້ງ. ຖ້າບັນຫາຍັງຄົງຢູ່, ໃຫ້ລອງໃຊ້ວິທີຈ່າຍເງິນອື່ນ',
|
||||
'vendor_address1' => 'ຖະໜົນຜູ້ຂາຍ',
|
||||
'vendor_address2' => 'ຜູ້ຂາຍ Apt/Suite',
|
||||
@ -5297,6 +5297,9 @@ $lang = array(
|
||||
'rappen_rounding_help' => 'ຈໍານວນຮອບເປັນ 5 ເຊັນ',
|
||||
'assign_group' => 'ກຳນົດກຸ່ມ',
|
||||
'paypal_advanced_cards' => 'Advanced Card Payments',
|
||||
'local_domain_help' => 'EHLO domain (optional)',
|
||||
'port_help' => 'ie. 25,587,465',
|
||||
'host_help' => 'ie. smtp.gmail.com',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -4026,7 +4026,7 @@ Kom terug naar deze betalingsmethode pagina zodra u de bedragen heeft ontvangen
|
||||
'user_detached' => 'Gebruiker losgekoppeld van bedrijf',
|
||||
'create_webhook_failure' => 'Maken van webhook is mislukt',
|
||||
'payment_message_extended' => 'Bedankt voor uw betaling van :amount voor :invoice',
|
||||
'online_payments_minimum_note' => 'Opmerking: Online betalingen worden alleen ondersteund als het bedrag groter is dan € 1 of het equivalent in een andere valuta.',
|
||||
'online_payments_minimum_note' => 'Note: Online payments are supported only if amount is larger than $1 or currency equivalent.',
|
||||
'payment_token_not_found' => 'Betalingstoken niet gevonden. Probeer het opnieuw. Als het probleem zich blijft voordoen, probeer het dan met een andere betaalmethode',
|
||||
'vendor_address1' => 'Leverancier straatnaam',
|
||||
'vendor_address2' => 'Leverancier Apt / Suite',
|
||||
@ -5297,6 +5297,9 @@ Email: :email<b><br><b>',
|
||||
'rappen_rounding_help' => 'Rond het bedrag af op 5 cent',
|
||||
'assign_group' => 'Groep toewijzen',
|
||||
'paypal_advanced_cards' => 'Advanced Card Payments',
|
||||
'local_domain_help' => 'EHLO domain (optional)',
|
||||
'port_help' => 'ie. 25,587,465',
|
||||
'host_help' => 'ie. smtp.gmail.com',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -4026,7 +4026,7 @@ Quando tiver as quantias, volte a esta página de formas de pagamento e clique "
|
||||
'user_detached' => 'Usuário desconectado da empresa',
|
||||
'create_webhook_failure' => 'Falha ao criar Webhook',
|
||||
'payment_message_extended' => 'Obrigado pelo seu pagamento de :amount por :invoice',
|
||||
'online_payments_minimum_note' => 'Nota: Os pagamentos on-line são suportados apenas se o valor for superior a US$ 1 ou o equivalente em moeda.',
|
||||
'online_payments_minimum_note' => 'Note: Online payments are supported only if amount is larger than $1 or currency equivalent.',
|
||||
'payment_token_not_found' => 'Token de pagamento não encontrado. Tente novamente. Se o problema persistir, tente outra forma de pagamento',
|
||||
'vendor_address1' => 'Rua do Vendedor',
|
||||
'vendor_address2' => 'Apartamento/Suíte do Vendedor',
|
||||
@ -5294,6 +5294,9 @@ Quando tiver as quantias, volte a esta página de formas de pagamento e clique "
|
||||
'rappen_rounding_help' => 'Montante redondo para 5 centavos',
|
||||
'assign_group' => 'Atribuir grupo',
|
||||
'paypal_advanced_cards' => 'Advanced Card Payments',
|
||||
'local_domain_help' => 'EHLO domain (optional)',
|
||||
'port_help' => 'ie. 25,587,465',
|
||||
'host_help' => 'ie. smtp.gmail.com',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -4028,7 +4028,7 @@ debitar da sua conta de acordo com essas instruções. Está elegível a um reem
|
||||
'user_detached' => 'Utilizador não vinculado à empresa',
|
||||
'create_webhook_failure' => 'Falha ao criar Webhook',
|
||||
'payment_message_extended' => 'Obrigado pelo pagamento de :amount para :invoice',
|
||||
'online_payments_minimum_note' => 'Nota: Pagamentos online estão disponíveis se a quantia for superior a 1$ ou ao equivalente na moeda utilizada.',
|
||||
'online_payments_minimum_note' => 'Note: Online payments are supported only if amount is larger than $1 or currency equivalent.',
|
||||
'payment_token_not_found' => 'Token de pagamento não encontrada, por favor tente novamente. Se este erro persistir, tente outro método de pagamento',
|
||||
'vendor_address1' => 'Morada Fornecedor',
|
||||
'vendor_address2' => 'Andar / Fração Fornecedor',
|
||||
@ -5297,6 +5297,9 @@ O envio de E-mails foi suspenso. Será retomado às 23:00 UTC.',
|
||||
'rappen_rounding_help' => 'Montante redondo para 5 centavos',
|
||||
'assign_group' => 'Atribuir grupo',
|
||||
'paypal_advanced_cards' => 'Advanced Card Payments',
|
||||
'local_domain_help' => 'EHLO domain (optional)',
|
||||
'port_help' => 'ie. 25,587,465',
|
||||
'host_help' => 'ie. smtp.gmail.com',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -4030,7 +4030,7 @@ Odată ce sumele au ajuns la dumneavoastră, reveniți la pagina cu metode de pl
|
||||
'user_detached' => 'Utilizatorul s-a detașat de companie',
|
||||
'create_webhook_failure' => 'Webhook nu a putut fi creat',
|
||||
'payment_message_extended' => 'Mulțumim că ați efectuat plata în valoare de :amount pentru :invoice',
|
||||
'online_payments_minimum_note' => 'Notă: Plățile online pot fi efectuate doar dacă suma depășește $1 sau echivalentul în valută.',
|
||||
'online_payments_minimum_note' => 'Note: Online payments are supported only if amount is larger than $1 or currency equivalent.',
|
||||
'payment_token_not_found' => 'Token-ul de plată nu a putut fi găsit. Încercați din nou. Dacă nu funcționează, încercați o altă metodă de plată',
|
||||
'vendor_address1' => 'Stradă furnizor',
|
||||
'vendor_address2' => 'Apartament furnizor',
|
||||
@ -5298,6 +5298,9 @@ Odată ce sumele au ajuns la dumneavoastră, reveniți la pagina cu metode de pl
|
||||
'rappen_rounding_help' => 'Suma rotundă la 5 cenți',
|
||||
'assign_group' => 'Atribuiți grup',
|
||||
'paypal_advanced_cards' => 'Advanced Card Payments',
|
||||
'local_domain_help' => 'EHLO domain (optional)',
|
||||
'port_help' => 'ie. 25,587,465',
|
||||
'host_help' => 'ie. smtp.gmail.com',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -2847,7 +2847,7 @@ $lang = array(
|
||||
'reminder1' => 'Prvá Upomienka',
|
||||
'reminder2' => 'Druhá Upomienka',
|
||||
'reminder3' => 'Tretia Upomienka',
|
||||
'send' => 'Odoslané',
|
||||
'send' => 'Odoslať',
|
||||
'auto_billing' => 'Automatické účtovanie',
|
||||
'button' => 'Tlačidlo',
|
||||
'more' => 'VIac',
|
||||
@ -4016,7 +4016,7 @@ $lang = array(
|
||||
'user_detached' => 'Používateľ je oddelený od spoločnosti',
|
||||
'create_webhook_failure' => 'Nepodarilo sa vytvoriť webhook',
|
||||
'payment_message_extended' => 'Ďakujeme za platbu vo výške :amount za :invoice',
|
||||
'online_payments_minimum_note' => 'Poznámka: Online platby sú podporované iba vtedy, ak je suma vyššia ako 1 $ alebo ekvivalent v inej mene.',
|
||||
'online_payments_minimum_note' => 'Note: Online payments are supported only if amount is larger than $1 or currency equivalent.',
|
||||
'payment_token_not_found' => 'Platobný token sa nenašiel, skúste to znova. Ak problém stále pretrváva, skúste použiť iný spôsob platby ',
|
||||
'vendor_address1' => 'Ulica predajcu',
|
||||
'vendor_address2' => 'Apartmán/byt dodávateľa',
|
||||
@ -4223,7 +4223,7 @@ $lang = array(
|
||||
'payment_type_Bancontact' => 'Zákaz kontaktu',
|
||||
'payment_type_BECS' => 'BECS',
|
||||
'payment_type_ACSS' => 'ACSS',
|
||||
'gross_line_total' => 'Hrubý riadok celkom',
|
||||
'gross_line_total' => 'Celková suma brutto',
|
||||
'lang_Slovak' => 'Slovensky',
|
||||
'normal' => 'Normálne',
|
||||
'large' => 'Veľké',
|
||||
@ -5284,6 +5284,9 @@ $lang = array(
|
||||
'rappen_rounding_help' => 'Okrúhla suma do 5 centov',
|
||||
'assign_group' => 'Priradiť skupinu',
|
||||
'paypal_advanced_cards' => 'Advanced Card Payments',
|
||||
'local_domain_help' => 'EHLO domain (optional)',
|
||||
'port_help' => 'ie. 25,587,465',
|
||||
'host_help' => 'ie. smtp.gmail.com',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -4029,7 +4029,7 @@ Kada budete imali iznose, vratite se na ovu stranicu sa načinima plaćanja i k
|
||||
'user_detached' => 'Korisnik je odvojen od kompanije',
|
||||
'create_webhook_failure' => 'Neuspešno kreiranje Webhook-a',
|
||||
'payment_message_extended' => 'Hvala vam na vašoj uplati od :amount za :invoice',
|
||||
'online_payments_minimum_note' => 'Napomena: onlajn plaćanja su podržana samo ako je iznos veći od 1 USD ili ekvivalentne valute.',
|
||||
'online_payments_minimum_note' => 'Note: Online payments are supported only if amount is larger than $1 or currency equivalent.',
|
||||
'payment_token_not_found' => 'Token za plaćanje nije pronađen, pokušajte ponovo. Ako problem i dalje postoji, pokušajte sa drugim načinom plaćanja ',
|
||||
'vendor_address1' => 'Ulica dobavljača',
|
||||
'vendor_address2' => 'Stan/apartman dobavljača',
|
||||
@ -5297,6 +5297,9 @@ Kada budete imali iznose, vratite se na ovu stranicu sa načinima plaćanja i k
|
||||
'rappen_rounding_help' => 'Round amount to 5 cents',
|
||||
'assign_group' => 'Assign group',
|
||||
'paypal_advanced_cards' => 'Advanced Card Payments',
|
||||
'local_domain_help' => 'EHLO domain (optional)',
|
||||
'port_help' => 'ie. 25,587,465',
|
||||
'host_help' => 'ie. smtp.gmail.com',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -4037,7 +4037,7 @@ Den här funktionen kräver att en produkt skapas och en betalningsgateway är k
|
||||
'user_detached' => 'Användaren har kopplats bort från företaget',
|
||||
'create_webhook_failure' => 'Det gick inte att skapa Webhook',
|
||||
'payment_message_extended' => 'Tack för din betalning på :amount för :invoice',
|
||||
'online_payments_minimum_note' => 'Notera: Online betalningar stöds endast om beloppet är större än 10:- eller motsvarande valuta.',
|
||||
'online_payments_minimum_note' => 'Note: Online payments are supported only if amount is larger than $1 or currency equivalent.',
|
||||
'payment_token_not_found' => 'Betalningstoken hittades inte. Försök igen. Om problemet fortfarande kvarstår kan du prova med en annan betalningsmetod',
|
||||
'vendor_address1' => 'Leverantörsadress',
|
||||
'vendor_address2' => 'Leverantörsadress 2',
|
||||
@ -5305,6 +5305,9 @@ Den här funktionen kräver att en produkt skapas och en betalningsgateway är k
|
||||
'rappen_rounding_help' => 'Round amount to 5 cents',
|
||||
'assign_group' => 'Assign group',
|
||||
'paypal_advanced_cards' => 'Advanced Card Payments',
|
||||
'local_domain_help' => 'EHLO domain (optional)',
|
||||
'port_help' => 'ie. 25,587,465',
|
||||
'host_help' => 'ie. smtp.gmail.com',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
@ -4029,7 +4029,7 @@ $lang = array(
|
||||
'user_detached' => '用戶脫離公司',
|
||||
'create_webhook_failure' => '建立 Webhook 失敗',
|
||||
'payment_message_extended' => '感謝您為:amount支付:invoice',
|
||||
'online_payments_minimum_note' => '注意:僅當金額大於 1 美元或等值貨幣時才支援線上付款。',
|
||||
'online_payments_minimum_note' => 'Note: Online payments are supported only if amount is larger than $1 or currency equivalent.',
|
||||
'payment_token_not_found' => '未找到支付令牌,請重試。如果問題仍然存在,請嘗試使用其他付款方式',
|
||||
'vendor_address1' => '供應商街',
|
||||
'vendor_address2' => '供應商 公寓/套房',
|
||||
@ -5297,6 +5297,9 @@ $lang = array(
|
||||
'rappen_rounding_help' => '金額為 5 美分',
|
||||
'assign_group' => '分配群組',
|
||||
'paypal_advanced_cards' => 'Advanced Card Payments',
|
||||
'local_domain_help' => 'EHLO domain (optional)',
|
||||
'port_help' => 'ie. 25,587,465',
|
||||
'host_help' => 'ie. smtp.gmail.com',
|
||||
);
|
||||
|
||||
return $lang;
|
||||
|
109
public/build/assets/app-042e859e.js
vendored
109
public/build/assets/app-042e859e.js
vendored
File diff suppressed because one or more lines are too long
109
public/build/assets/app-bfac6a32.js
vendored
Normal file
109
public/build/assets/app-bfac6a32.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -9,7 +9,7 @@
|
||||
]
|
||||
},
|
||||
"resources/js/app.js": {
|
||||
"file": "assets/app-042e859e.js",
|
||||
"file": "assets/app-bfac6a32.js",
|
||||
"imports": [
|
||||
"_index-08e160a7.js",
|
||||
"__commonjsHelpers-725317a4.js"
|
||||
|
@ -96,7 +96,7 @@ class TaskImportTest extends TestCase
|
||||
$time_log = json_decode($task->time_log);
|
||||
|
||||
foreach($time_log as $log) {
|
||||
$this->assertFalse($log[3]);
|
||||
$this->assertTrue($log[3]);
|
||||
}
|
||||
|
||||
$task = Task::where('company_id', $this->company->id)->where('number', 'x1233')->first();
|
||||
@ -106,7 +106,7 @@ class TaskImportTest extends TestCase
|
||||
$time_log = json_decode($task->time_log);
|
||||
|
||||
foreach($time_log as $log) {
|
||||
$this->assertFalse($log[3]);
|
||||
$this->assertTrue($log[3]);
|
||||
}
|
||||
|
||||
|
||||
|
199
tests/Feature/MaxAmountTest.php
Normal file
199
tests/Feature/MaxAmountTest.php
Normal file
@ -0,0 +1,199 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use Tests\TestCase;
|
||||
use App\Models\Quote;
|
||||
use App\Models\Credit;
|
||||
use App\Models\Invoice;
|
||||
use Tests\MockAccountData;
|
||||
use App\Models\PurchaseOrder;
|
||||
use App\DataMapper\InvoiceItem;
|
||||
use App\Models\RecurringInvoice;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Illuminate\Routing\Middleware\ThrottleRequests;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @covers App\Http\Controllers\ActivityController
|
||||
*/
|
||||
class MaxAmountTest extends TestCase
|
||||
{
|
||||
use DatabaseTransactions;
|
||||
use MockAccountData;
|
||||
|
||||
protected function setUp() :void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->makeTestData();
|
||||
|
||||
$this->withoutMiddleware(
|
||||
ThrottleRequests::class
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
public function testInvoiceMaxAmount()
|
||||
{
|
||||
$item = new InvoiceItem();
|
||||
$item->cost = 10000000000000000;
|
||||
$item->quantity = 100;
|
||||
|
||||
$data = [
|
||||
'user_id' => $this->user->id,
|
||||
'client_id' => $this->client->id,
|
||||
'company_id' => $this->company->id,
|
||||
'line_items' => [$item]
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->postJson('/api/v1/invoices', $data);
|
||||
|
||||
$response->assertStatus(422);
|
||||
|
||||
$i = Invoice::factory()->create($data);
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->putJson("/api/v1/invoices/{$i->hashed_id}", $data);
|
||||
|
||||
$response->assertStatus(422);
|
||||
}
|
||||
|
||||
|
||||
public function testCreditMaxAmount()
|
||||
{
|
||||
$item = new InvoiceItem();
|
||||
$item->cost = 10000000000000000;
|
||||
$item->quantity = 100;
|
||||
|
||||
$data = [
|
||||
'user_id' => $this->user->id,
|
||||
'client_id' => $this->client->id,
|
||||
'company_id' => $this->company->id,
|
||||
'line_items' => [$item]
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->postJson('/api/v1/credits', $data);
|
||||
|
||||
$response->assertStatus(422);
|
||||
|
||||
$i = Credit::factory()->create($data);
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->putJson("/api/v1/credits/{$i->hashed_id}", $data);
|
||||
|
||||
$response->assertStatus(422);
|
||||
}
|
||||
|
||||
|
||||
public function testQuoteMaxAmount()
|
||||
{
|
||||
$item = new InvoiceItem();
|
||||
$item->cost = 10000000000000000;
|
||||
$item->quantity = 100;
|
||||
|
||||
$data = [
|
||||
'user_id' => $this->user->id,
|
||||
'client_id' => $this->client->id,
|
||||
'company_id' => $this->company->id,
|
||||
'line_items' => [$item]
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->postJson('/api/v1/quotes', $data);
|
||||
|
||||
$response->assertStatus(422);
|
||||
|
||||
$i = Quote::factory()->create($data);
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->putJson("/api/v1/quotes/{$i->hashed_id}", $data);
|
||||
|
||||
$response->assertStatus(422);
|
||||
}
|
||||
|
||||
public function testPurchaseOrderMaxAmount()
|
||||
{
|
||||
$item = new InvoiceItem();
|
||||
$item->cost = 10000000000000000;
|
||||
$item->quantity = 100;
|
||||
|
||||
$data = [
|
||||
'user_id' => $this->user->id,
|
||||
'vendor_id' => $this->vendor->id,
|
||||
'company_id' => $this->company->id,
|
||||
'line_items' => [$item]
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->postJson('/api/v1/purchase_orders', $data);
|
||||
|
||||
$response->assertStatus(422);
|
||||
|
||||
$i = PurchaseOrder::factory()->create($data);
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->putJson("/api/v1/purchase_orders/{$i->hashed_id}", $data);
|
||||
|
||||
$response->assertStatus(422);
|
||||
}
|
||||
|
||||
public function testRecurringInvoiceMaxAmount()
|
||||
{
|
||||
$item = new InvoiceItem();
|
||||
$item->cost = 10000000000000000;
|
||||
$item->quantity = 100;
|
||||
|
||||
$data = [
|
||||
'user_id' => $this->user->id,
|
||||
'client_id' => $this->client->id,
|
||||
'company_id' => $this->company->id,
|
||||
'line_items' => [$item],
|
||||
'frequency_id' => 5
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->postJson('/api/v1/recurring_invoices', $data);
|
||||
|
||||
$response->assertStatus(422);
|
||||
|
||||
$i = RecurringInvoice::factory()->create($data);
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->putJson("/api/v1/recurring_invoices/{$i->hashed_id}", $data);
|
||||
|
||||
$response->assertStatus(422);
|
||||
}
|
||||
}
|
@ -104,6 +104,33 @@ class TaskApiTest extends TestCase
|
||||
}
|
||||
}
|
||||
|
||||
public function testTimeLogWithSameStartAndStopTimes()
|
||||
{
|
||||
$settings = ClientSettings::defaults();
|
||||
$settings->default_task_rate = 41;
|
||||
|
||||
$c = Client::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
'company_id' => $this->company->id,
|
||||
'settings' => $settings,
|
||||
]);
|
||||
|
||||
$data = [
|
||||
'client_id' => $c->hashed_id,
|
||||
'description' => 'Test Task',
|
||||
'time_log' => '[[1681165417,1681165432,"sumtin",true],[1681165446,1681165446]]',
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->postJson("/api/v1/tasks", $data);
|
||||
|
||||
$response->assertStatus(200);
|
||||
$arr = $response->json();
|
||||
|
||||
}
|
||||
|
||||
public function testRoundingViaApi()
|
||||
{
|
||||
|
||||
|
73
tests/Unit/TaskRoundingTest.php
Normal file
73
tests/Unit/TaskRoundingTest.php
Normal file
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace Tests\Unit;
|
||||
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
class TaskRoundingTest extends TestCase
|
||||
{
|
||||
|
||||
public int $task_round_to_nearest = 1;
|
||||
|
||||
public bool $task_round_up = true;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
}
|
||||
|
||||
public function testRoundUp()
|
||||
{
|
||||
$start_time = 1714942800;
|
||||
$end_time = 1714943220; //7:07am
|
||||
$this->task_round_to_nearest = 600;
|
||||
|
||||
//calculated time = 7:10am
|
||||
$rounded = 1714943400;
|
||||
|
||||
$this->assertEquals($rounded, $this->roundTimeLog($start_time, $end_time));
|
||||
|
||||
}
|
||||
|
||||
public function testRoundDown()
|
||||
{
|
||||
$start_time = 1714942800;
|
||||
$end_time = 1714943220; //7:07am
|
||||
$this->task_round_to_nearest = 600;
|
||||
$this->task_round_up = false;
|
||||
|
||||
//calculated time = 7:10am
|
||||
$rounded = $start_time;
|
||||
|
||||
$this->assertEquals($rounded, $this->roundTimeLog($start_time, $end_time));
|
||||
|
||||
}
|
||||
|
||||
public function roundTimeLog(int $start_time, int $end_time): int
|
||||
{
|
||||
if($this->task_round_to_nearest == 1)
|
||||
return $end_time;
|
||||
|
||||
$interval = $end_time - $start_time;
|
||||
|
||||
if($this->task_round_up)
|
||||
return $start_time + (int)ceil($interval/$this->task_round_to_nearest)*$this->task_round_to_nearest;
|
||||
|
||||
return $start_time - (int)floor($interval/$this->task_round_to_nearest) * $this->task_round_to_nearest;
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user