1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-09-21 08:51:34 +02:00

Merge remote-tracking branch 'upstream/v2' into v2-1809-remove-omnipay-from-stripe

This commit is contained in:
Benjamin Beganović 2020-09-24 11:36:41 +02:00
commit 9b4d166e10
111 changed files with 118687 additions and 114036 deletions

View File

@ -1 +1 @@
5.0.13 5.0.17

View File

@ -12,7 +12,6 @@
namespace App\Console\Commands; namespace App\Console\Commands;
use App\Console\Commands\TestData\CreateTestCreditJob; use App\Console\Commands\TestData\CreateTestCreditJob;
use App\Console\Commands\TestData\CreateTestInvoiceJob;
use App\Console\Commands\TestData\CreateTestQuoteJob; use App\Console\Commands\TestData\CreateTestQuoteJob;
use App\DataMapper\CompanySettings; use App\DataMapper\CompanySettings;
use App\DataMapper\DefaultSettings; use App\DataMapper\DefaultSettings;
@ -463,9 +462,6 @@ class CreateTestData extends Command
private function createInvoice($client) private function createInvoice($client)
{ {
// for($x=0; $x<$this->count; $x++){
// dispatch(new CreateTestInvoiceJob($client));
// }
$faker = \Faker\Factory::create(); $faker = \Faker\Factory::create();

View File

@ -358,9 +358,6 @@ class DemoMode extends Command
private function createInvoice($client, $assigned_user_id = null) private function createInvoice($client, $assigned_user_id = null)
{ {
// for($x=0; $x<$this->count; $x++){
// dispatch(new CreateTestInvoiceJob($client));
// }
$faker = \Faker\Factory::create(); $faker = \Faker\Factory::create();

View File

@ -1,160 +0,0 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Console\Commands\TestData;
use App\Events\Invoice\InvoiceWasCreated;
use App\Events\Payment\PaymentWasCreated;
use App\Factory\InvoiceFactory;
use App\Factory\InvoiceItemFactory;
use App\Factory\PaymentFactory;
use App\Helpers\Invoice\InvoiceSum;
use App\Models\Client;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\Product;
use App\Utils\Ninja;
use App\Utils\Traits\MakesHash;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Carbon;
class CreateTestInvoiceJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, MakesHash;
protected $client;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct(Client $client)
{
$this->client = $client;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
$faker = \Faker\Factory::create();
$invoice = InvoiceFactory::create($this->client->company->id, $this->client->user->id); //stub the company and user_id
$invoice->client_id = $this->client->id;
// $invoice->date = $faker->date();
$dateable = Carbon::now()->subDays(rand(0, 90));
$invoice->date = $dateable;
$invoice->line_items = $this->buildLineItems(rand(1, 10));
$invoice->uses_inclusive_taxes = false;
if (rand(0, 1)) {
$invoice->tax_name1 = 'GST';
$invoice->tax_rate1 = 10.00;
}
if (rand(0, 1)) {
$invoice->tax_name2 = 'VAT';
$invoice->tax_rate2 = 17.50;
}
if (rand(0, 1)) {
$invoice->tax_name3 = 'CA Sales Tax';
$invoice->tax_rate3 = 5;
}
$invoice->save();
$invoice_calc = new InvoiceSum($invoice);
$invoice_calc->build();
$invoice = $invoice_calc->getInvoice();
$invoice->save();
$invoice->service()->createInvitations()->markSent()->save();
$invoice->ledger()->updateInvoiceBalance($invoice->balance);
//UpdateCompanyLedgerWithInvoice::dispatchNow($invoice, $invoice->balance, $invoice->company);
//$this->invoice_repo->markSent($invoice);
if (rand(0, 1)) {
$payment = PaymentFactory::create($this->client->company->id, $this->client->user->id);
$payment->date = $dateable;
$payment->client_id = $this->client->id;
$payment->amount = $invoice->balance;
$payment->transaction_reference = rand(0, 500);
$payment->type_id = PaymentType::CREDIT_CARD_OTHER;
$payment->status_id = Payment::STATUS_COMPLETED;
$payment->number = $this->client->getNextPaymentNumber($this->client);
$payment->currency_id = 1;
$payment->save();
$payment->invoices()->save($invoice);
event(new PaymentWasCreated($payment, $payment->company, Ninja::eventVars()));
$payment->service()->updateInvoicePayment();
//UpdateInvoicePayment::dispatchNow($payment, $payment->company);
}
//@todo this slow things down, but gives us PDFs of the invoices for inspection whilst debugging.
event(new InvoiceWasCreated($invoice, $invoice->company, Ninja::eventVars()));
}
private function buildLineItems($count = 1)
{
$line_items = [];
for ($x = 0; $x < $count; $x++) {
$item = InvoiceItemFactory::create();
$item->quantity = 1;
//$item->cost = 10;
if (rand(0, 1)) {
$item->tax_name1 = 'GST';
$item->tax_rate1 = 10.00;
}
if (rand(0, 1)) {
$item->tax_name1 = 'VAT';
$item->tax_rate1 = 17.50;
}
if (rand(0, 1)) {
$item->tax_name1 = 'Sales Tax';
$item->tax_rate1 = 5;
}
$product = Product::all()->random();
$item->cost = (float) $product->cost;
$item->product_key = $product->product_key;
$item->notes = $product->notes;
$item->custom_value1 = $product->custom_value1;
$item->custom_value2 = $product->custom_value2;
$item->custom_value3 = $product->custom_value3;
$item->custom_value4 = $product->custom_value4;
$line_items[] = $item;
}
return $line_items;
}
}

View File

@ -613,7 +613,6 @@ class CompanySettings extends BaseSettings
'$total_taxes', '$total_taxes',
'$line_taxes', '$line_taxes',
'$subtotal', '$subtotal',
'$total',
'$discount', '$discount',
'$custom_surcharge1', '$custom_surcharge1',
'$custom_surcharge2', '$custom_surcharge2',
@ -621,6 +620,7 @@ class CompanySettings extends BaseSettings
'$custom_surcharge4', '$custom_surcharge4',
'$paid_to_date', '$paid_to_date',
'$client.balance', '$client.balance',
'$total',
], ],
]; ];

View File

@ -24,13 +24,10 @@ class VendorFactory
$vendor->name = ''; $vendor->name = '';
$vendor->website = ''; $vendor->website = '';
$vendor->private_notes = ''; $vendor->private_notes = '';
$vendor->balance = 0; $vendor->public_notes = '';
$vendor->paid_to_date = 0;
$vendor->country_id = 4; $vendor->country_id = 4;
$vendor->is_deleted = 0; $vendor->is_deleted = 0;
$vendor->vendor_hash = Str::random(40);
$vendor_contact = VendorContactFactory::create($company_id, $user_id);
$vendor->contacts->add($vendor_contact);
return $vendor; return $vendor;
} }

View File

@ -69,11 +69,17 @@ class BaseController extends Controller
'company.company_gateways.gateway', 'company.company_gateways.gateway',
'company.clients.contacts', 'company.clients.contacts',
'company.clients.gateway_tokens', 'company.clients.gateway_tokens',
'company.clients.documents',
'company.products', 'company.products',
'company.products.documents',
'company.recurring_invoices', 'company.recurring_invoices',
'company.invoices.invitations.contact', 'company.invoices.invitations.contact',
'company.invoices.invitations.company', 'company.invoices.invitations.company',
'company.invoices.documents', 'company.invoices.documents',
'company.recurring_invoices',
'company.recurring_invoices.invitations.contact',
'company.recurring_invoices.invitations.company',
'company.recurring_invoices.documents',
'company.payments.paymentables', 'company.payments.paymentables',
'company.quotes.invitations.contact', 'company.quotes.invitations.contact',
'company.quotes.invitations.company', 'company.quotes.invitations.company',
@ -87,6 +93,7 @@ class BaseController extends Controller
'company.tasks', 'company.tasks',
'company.projects', 'company.projects',
'company.designs', 'company.designs',
'company.documents',
'company.webhooks', 'company.webhooks',
'company.tokens_hashed', 'company.tokens_hashed',
]; ];
@ -197,10 +204,10 @@ class BaseController extends Controller
$query->with( $query->with(
[ [
'company' => function ($query) use ($updated_at) { 'company' => function ($query) use ($updated_at) {
$query->whereNotNull('updated_at'); $query->whereNotNull('updated_at')->with('documents');
}, },
'company.clients' => function ($query) use ($updated_at) { 'company.clients' => function ($query) use ($updated_at) {
$query->where('clients.updated_at', '>=', $updated_at)->with('contacts'); $query->where('clients.updated_at', '>=', $updated_at)->with('contacts', 'gateway_tokens','documents');
}, },
'company.tax_rates' => function ($query) use ($updated_at) { 'company.tax_rates' => function ($query) use ($updated_at) {
$query->where('updated_at', '>=', $updated_at); $query->where('updated_at', '>=', $updated_at);
@ -212,7 +219,7 @@ class BaseController extends Controller
$query->whereNotNull('updated_at'); $query->whereNotNull('updated_at');
}, },
'company.products' => function ($query) use ($updated_at) { 'company.products' => function ($query) use ($updated_at) {
$query->where('updated_at', '>=', $updated_at); $query->where('updated_at', '>=', $updated_at)->with('documents');
}, },
'company.recurring_invoices'=> function ($query) use ($updated_at) { 'company.recurring_invoices'=> function ($query) use ($updated_at) {
$query->where('updated_at', '>=', $updated_at)->with('company'); $query->where('updated_at', '>=', $updated_at)->with('company');
@ -220,8 +227,11 @@ class BaseController extends Controller
'company.invoices'=> function ($query) use ($updated_at) { 'company.invoices'=> function ($query) use ($updated_at) {
$query->where('updated_at', '>=', $updated_at)->with('invitations', 'company', 'documents'); $query->where('updated_at', '>=', $updated_at)->with('invitations', 'company', 'documents');
}, },
'company.recurring_invoices'=> function ($query) use ($updated_at) {
$query->where('updated_at', '>=', $updated_at)->with('invitations', 'company', 'documents');
},
'company.payments'=> function ($query) use ($updated_at) { 'company.payments'=> function ($query) use ($updated_at) {
$query->where('updated_at', '>=', $updated_at)->with('paymentables'); $query->where('updated_at', '>=', $updated_at)->with('paymentables','documents');
}, },
'company.quotes'=> function ($query) use ($updated_at) { 'company.quotes'=> function ($query) use ($updated_at) {
$query->where('updated_at', '>=', $updated_at)->with('invitations', 'documents'); $query->where('updated_at', '>=', $updated_at)->with('invitations', 'documents');

View File

@ -87,7 +87,7 @@ class InvoiceController extends Controller
$total = $invoices->sum('balance'); $total = $invoices->sum('balance');
$invoices = $invoices->filter(function ($invoice) { $invoices = $invoices->filter(function ($invoice) {
return $invoice->isPayable(); return $invoice->isPayable() && $invoice->balance > 0;
}); });
if ($invoices->count() == 0) { if ($invoices->count() == 0) {

View File

@ -73,12 +73,6 @@ class PaymentController extends Controller
*/ */
public function process() public function process()
{ {
//REFACTOR - Here the request will contain an array of invoices and the amount to be charged for the invoice
//REFACTOR - At this point, we will also need to modify the invoice to include a line item for a gateway fee if applicable
// This is tagged with a type_id of 3 which is for a pending gateway fee.
//REFACTOR - In order to preserve state we should save the array of invoices and amounts and store it in db/cache and use a HASH
// to rehydrate these values in the payment response.
// dd(request()->all());
$gateway = CompanyGateway::find(request()->input('company_gateway_id')); $gateway = CompanyGateway::find(request()->input('company_gateway_id'));
/*find invoices*/ /*find invoices*/

View File

@ -135,6 +135,13 @@ class PaymentMethodController extends Controller
*/ */
public function destroy(ClientGatewayToken $payment_method) public function destroy(ClientGatewayToken $payment_method)
{ {
$gateway = $this->getClientGateway();
$gateway
->driver(auth()->user()->client)
->setPaymentMethod(request()->query('method'))
->detach($payment_method);
try { try {
event(new MethodDeleted($payment_method, auth('contact')->user()->company, Ninja::eventVars())); event(new MethodDeleted($payment_method, auth('contact')->user()->company, Ninja::eventVars()));
$payment_method->delete(); $payment_method->delete();

View File

@ -11,7 +11,14 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Factory\ExpenseFactory;
use App\Filters\ExpenseFilters; use App\Filters\ExpenseFilters;
use App\Http\Requests\Expense\CreateExpenseRequest;
use App\Http\Requests\Expense\DestroyExpenseRequest;
use App\Http\Requests\Expense\EditExpenseRequest;
use App\Http\Requests\Expense\ShowExpenseRequest;
use App\Http\Requests\Expense\StoreExpenseRequest;
use App\Http\Requests\Expense\UpdateExpenseRequest;
use App\Jobs\Entity\ActionEntity; use App\Jobs\Entity\ActionEntity;
use App\Jobs\Util\ProcessBulk; use App\Jobs\Util\ProcessBulk;
use App\Jobs\Util\UploadAvatar; use App\Jobs\Util\UploadAvatar;
@ -266,7 +273,7 @@ class ExpenseController extends BaseController
return $request->disallowUpdate(); return $request->disallowUpdate();
} }
$expense = $this->client_repo->save($request->all(), $expense); $expense = $this->expense_repo->save($request->all(), $expense);
$this->uploadLogo($request->file('company_logo'), $expense->company, $expense); $this->uploadLogo($request->file('company_logo'), $expense->company, $expense);
@ -359,11 +366,7 @@ class ExpenseController extends BaseController
*/ */
public function store(StoreExpenseRequest $request) public function store(StoreExpenseRequest $request)
{ {
$expense = $this->client_repo->save($request->all(), ExpenseFactory::create(auth()->user()->company()->id, auth()->user()->id)); $expense = $this->expense_repo->save($request->all(), ExpenseFactory::create(auth()->user()->company()->id, auth()->user()->id));
$expense->load('contacts', 'primary_contact');
$this->uploadLogo($request->file('company_logo'), $expense->company, $expense);
return $this->itemResponse($expense); return $this->itemResponse($expense);
} }
@ -485,7 +488,7 @@ class ExpenseController extends BaseController
$expenses->each(function ($expense, $key) use ($action) { $expenses->each(function ($expense, $key) use ($action) {
if (auth()->user()->can('edit', $expense)) { if (auth()->user()->can('edit', $expense)) {
$this->client_repo->{$action}($expense); $this->expense_repo->{$action}($expense);
} }
}); });

View File

@ -700,7 +700,7 @@ class InvoiceController extends BaseController
} }
break; break;
case 'email': case 'email':
//check query paramater for email_type and set the template else use calculateTemplate //check query parameter for email_type and set the template else use calculateTemplate
if (request()->has('email_type') && property_exists($invoice->company->settings, request()->input('email_type'))) { if (request()->has('email_type') && property_exists($invoice->company->settings, request()->input('email_type'))) {
$this->reminder_template = $invoice->client->getSetting(request()->input('email_type')); $this->reminder_template = $invoice->client->getSetting(request()->input('email_type'));
} else { } else {

View File

@ -11,7 +11,14 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Factory\VendorFactory;
use App\Filters\VendorFilters; use App\Filters\VendorFilters;
use App\Http\Requests\Vendor\CreateVendorRequest;
use App\Http\Requests\Vendor\DestroyVendorRequest;
use App\Http\Requests\Vendor\EditVendorRequest;
use App\Http\Requests\Vendor\ShowVendorRequest;
use App\Http\Requests\Vendor\StoreVendorRequest;
use App\Http\Requests\Vendor\UpdateVendorRequest;
use App\Jobs\Entity\ActionEntity; use App\Jobs\Entity\ActionEntity;
use App\Jobs\Util\ProcessBulk; use App\Jobs\Util\ProcessBulk;
use App\Jobs\Util\UploadAvatar; use App\Jobs\Util\UploadAvatar;
@ -31,7 +38,6 @@ use Illuminate\Support\Facades\Log;
/** /**
* Class VendorController. * Class VendorController.
* @covers App\Http\Controllers\VendorController
*/ */
class VendorController extends BaseController class VendorController extends BaseController
{ {
@ -266,7 +272,7 @@ class VendorController extends BaseController
return $request->disallowUpdate(); return $request->disallowUpdate();
} }
$vendor = $this->client_repo->save($request->all(), $vendor); $vendor = $this->vendor_repo->save($request->all(), $vendor);
$this->uploadLogo($request->file('company_logo'), $vendor->company, $vendor); $this->uploadLogo($request->file('company_logo'), $vendor->company, $vendor);
@ -359,7 +365,7 @@ class VendorController extends BaseController
*/ */
public function store(StoreVendorRequest $request) public function store(StoreVendorRequest $request)
{ {
$vendor = $this->client_repo->save($request->all(), VendorFactory::create(auth()->user()->company()->id, auth()->user()->id)); $vendor = $this->vendor_repo->save($request->all(), VendorFactory::create(auth()->user()->company()->id, auth()->user()->id));
$vendor->load('contacts', 'primary_contact'); $vendor->load('contacts', 'primary_contact');
@ -485,7 +491,7 @@ class VendorController extends BaseController
$vendors->each(function ($vendor, $key) use ($action) { $vendors->each(function ($vendor, $key) use ($action) {
if (auth()->user()->can('edit', $vendor)) { if (auth()->user()->can('edit', $vendor)) {
$this->client_repo->{$action}($vendor); $this->vendor_repo->{$action}($vendor);
} }
}); });

View File

@ -56,7 +56,7 @@ class Kernel extends HttpKernel
'bindings', 'bindings',
'query_logging', 'query_logging',
\App\Http\Middleware\StartupCheck::class, \App\Http\Middleware\StartupCheck::class,
// \App\Http\Middleware\Cors::class, \App\Http\Middleware\Cors::class,
], ],
'contact' => [ 'contact' => [
'throttle:60,1', 'throttle:60,1',

View File

@ -19,7 +19,7 @@ class RecurringInvoicesTable extends Component
$query = $query $query = $query
->where('client_id', auth('contact')->user()->client->id) ->where('client_id', auth('contact')->user()->client->id)
->whereIn('status_id', [RecurringInvoice::STATUS_PENDING, RecurringInvoice::STATUS_ACTIVE, RecurringInvoice::STATUS_COMPLETED]) ->whereIn('status_id', [RecurringInvoice::STATUS_PENDING, RecurringInvoice::STATUS_ACTIVE, RecurringInvoice::STATUS_PAUSED,RecurringInvoice::STATUS_COMPLETED])
->orderBy('status_id', 'asc') ->orderBy('status_id', 'asc')
->with('client') ->with('client')
->orderBy($this->sort_field, $this->sort_asc ? 'asc' : 'desc') ->orderBy($this->sort_field, $this->sort_asc ? 'asc' : 'desc')

View File

@ -16,7 +16,7 @@ class Cors
// ALLOW OPTIONS METHOD // ALLOW OPTIONS METHOD
$headers = [ $headers = [
'Access-Control-Allow-Methods'=> 'POST, GET, OPTIONS, PUT, DELETE', 'Access-Control-Allow-Methods'=> 'POST, GET, OPTIONS, PUT, DELETE',
'Access-Control-Allow-Headers'=> 'X-API-COMPANY-KEY,X-API-SECRET,X-API-TOKEN,X-API-PASSWORD,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range', 'Access-Control-Allow-Headers'=> 'X-API-COMPANY-KEY,X-CLIENT-VERSION,X-API-SECRET,X-API-TOKEN,X-API-PASSWORD,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range',
]; ];
return Response::make('OK', 200, $headers); return Response::make('OK', 200, $headers);

View File

@ -52,8 +52,8 @@ class QueryLogging
Log::info($request->method().' - '.$request->url().": $count queries - ".$time); Log::info($request->method().' - '.$request->url().": $count queries - ".$time);
// if($count > 100) // if($count > 50)
// Log::info($queries); // Log::info($queries);
} }
} }

View File

@ -0,0 +1,47 @@
<?php
namespace App\Http\Requests\Expense;
use App\Models\Expense;
use App\Utils\Traits\BulkOptions;
use Illuminate\Foundation\Http\FormRequest;
class BulkExpenseRequest extends FormRequest
{
use BulkOptions;
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
if (! $this->has('action')) {
return false;
}
if (! in_array($this->action, $this->getBulkOptions(), true)) {
return false;
}
return auth()->user()->can(auth()->user()->isAdmin(), Expense::class);
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
$rules = $this->getGlobalRules();
/* We don't require IDs on bulk storing. */
if ($this->action !== self::$STORE_METHOD) {
$rules['ids'] = ['required'];
}
return $rules;
}
}

View File

@ -0,0 +1,28 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Http\Requests\Expense;
use App\Http\Requests\Request;
use App\Models\Expense;
class CreateExpenseRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize() : bool
{
return auth()->user()->can('create', Expense::class);
}
}

View File

@ -0,0 +1,28 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Http\Requests\Expense;
use App\Http\Requests\Request;
use App\Models\Expense;
class DestroyExpenseRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize() : bool
{
return auth()->user()->can('edit', $this->expense);
}
}

View File

@ -0,0 +1,38 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Http\Requests\Expense;
use App\Http\Requests\Request;
use App\Models\Expense;
class EditExpenseRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize() : bool
{
return auth()->user()->can('edit', $this->expense);
}
// public function prepareForValidation()
// {
// $input = $this->all();
// //$input['id'] = $this->encodePrimaryKey($input['id']);
// $this->replace($input);
// }
}

View File

@ -0,0 +1,28 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Http\Requests\Expense;
use App\Http\Requests\Request;
use App\Models\Expense;
class ShowExpenseRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize() : bool
{
return auth()->user()->can('view', $this->expense);
}
}

View File

@ -0,0 +1,76 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Http\Requests\Expense;
use App\DataMapper\ExpenseSettings;
use App\Http\Requests\Request;
use App\Http\ValidationRules\Expense\UniqueExpenseNumberRule;
use App\Http\ValidationRules\ValidExpenseGroupSettingsRule;
use App\Models\Expense;
use App\Utils\Traits\MakesHash;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\Rule;
class StoreExpenseRequest extends Request
{
use MakesHash;
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize() : bool
{
return auth()->user()->can('create', Expense::class);
}
public function rules()
{
/* Ensure we have a client name, and that all emails are unique*/
//$rules['name'] = 'required|min:1';
$rules['id_number'] = 'unique:expenses,id_number,'.$this->id.',id,company_id,'.$this->company_id;
//$rules['settings'] = new ValidExpenseGroupSettingsRule();
$rules['contacts.*.email'] = 'nullable|distinct';
$rules['number'] = new UniqueExpenseNumberRule($this->all());
// $contacts = request('contacts');
// if (is_array($contacts)) {
// for ($i = 0; $i < count($contacts); $i++) {
// //$rules['contacts.' . $i . '.email'] = 'nullable|email|distinct';
// }
// }
return $rules;
}
protected function prepareForValidation()
{
// $input = $this->all();
// $this->replace($input);
}
public function messages()
{
return [
'unique' => ctrans('validation.unique', ['attribute' => 'email']),
//'required' => trans('validation.required', ['attribute' => 'email']),
'contacts.*.email.required' => ctrans('validation.email', ['attribute' => 'email']),
];
}
}

View File

@ -0,0 +1,77 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Http\Requests\Expense;
use App\Http\Requests\Request;
use App\Http\ValidationRules\IsDeletedRule;
use App\Http\ValidationRules\ValidExpenseGroupSettingsRule;
use App\Utils\Traits\ChecksEntityStatus;
use App\Utils\Traits\MakesHash;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\Rule;
class UpdateExpenseRequest extends Request
{
use MakesHash;
use ChecksEntityStatus;
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize() : bool
{
return auth()->user()->can('edit', $this->expense);
}
public function rules()
{
/* Ensure we have a client name, and that all emails are unique*/
$rules['country_id'] = 'integer|nullable';
//$rules['id_number'] = 'unique:clients,id_number,,id,company_id,' . auth()->user()->company()->id;
$rules['contacts.*.email'] = 'nullable|distinct';
if ($this->input('number')) {
$rules['number'] = 'unique:expenses,number,'.$this->id.',id,company_id,'.$this->expense->company_id;
}
$contacts = request('contacts');
if (is_array($contacts)) {
// for ($i = 0; $i < count($contacts); $i++) {
// // $rules['contacts.' . $i . '.email'] = 'nullable|email|unique:client_contacts,email,' . isset($contacts[$i]['id'].',company_id,'.$this->company_id);
// //$rules['contacts.' . $i . '.email'] = 'nullable|email';
// }
}
return $rules;
}
public function messages()
{
return [
'unique' => ctrans('validation.unique', ['attribute' => 'email']),
'email' => ctrans('validation.email', ['attribute' => 'email']),
'name.required' => ctrans('validation.required', ['attribute' => 'name']),
'required' => ctrans('validation.required', ['attribute' => 'email']),
];
}
protected function prepareForValidation()
{
$input = $this->all();
$this->replace($input);
}
}

View File

@ -42,27 +42,24 @@ class StoreVendorRequest extends Request
//$rules['settings'] = new ValidVendorGroupSettingsRule(); //$rules['settings'] = new ValidVendorGroupSettingsRule();
$rules['contacts.*.email'] = 'nullable|distinct'; $rules['contacts.*.email'] = 'nullable|distinct';
$contacts = request('contacts'); // $contacts = request('contacts');
if (is_array($contacts)) { // if (is_array($contacts)) {
for ($i = 0; $i < count($contacts); $i++) { // for ($i = 0; $i < count($contacts); $i++) {
//$rules['contacts.' . $i . '.email'] = 'nullable|email|distinct'; // //$rules['contacts.' . $i . '.email'] = 'nullable|email|distinct';
} // }
} // }
return $rules; return $rules;
} }
protected function prepareForValidation() protected function prepareForValidation()
{ {
$input = $this->all(); // $input = $this->all();
if (! isset($input['settings'])) {
$input['settings'] = VendorSettings::defaults();
}
$this->replace($input); // $this->replace($input);
} }
public function messages() public function messages()

View File

@ -0,0 +1,69 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Http\ValidationRules\Expense;
use App\Libraries\MultiDB;
use App\Models\Expense;
use App\Models\User;
use Illuminate\Contracts\Validation\Rule;
/**
* Class UniqueExpenseNumberRule.
*/
class UniqueExpenseNumberRule implements Rule
{
public $input;
public function __construct($input)
{
$this->input = $input;
}
/**
* @param string $attribute
* @param mixed $value
* @return bool
*/
public function passes($attribute, $value)
{
return $this->checkIfExpenseNumberUnique(); //if it exists, return false!
}
/**
* @return string
*/
public function message()
{
return 'Expense number already taken';
}
/**
* @param $email
*
* //off,when_sent,when_paid
*
* @return bool
*/
private function checkIfExpenseNumberUnique() : bool
{
$expense = Expense::where('client_id', $this->input['client_id'])
->where('number', $this->input['number'])
->withTrashed()
->exists();
if ($expense) {
return false;
}
return true;
}
}

View File

@ -54,7 +54,8 @@ class ValidInvoicesRules implements Rule
} }
$unique_array = []; $unique_array = [];
//todo optimize this into a single query
foreach ($this->input['invoices'] as $invoice) { foreach ($this->input['invoices'] as $invoice) {
$unique_array[] = $invoice['invoice_id']; $unique_array[] = $invoice['invoice_id'];

View File

@ -19,6 +19,7 @@ use App\Models\ClientContact;
use App\Models\Company; use App\Models\Company;
use App\Models\Design; use App\Models\Design;
use App\Models\Invoice; use App\Models\Invoice;
use App\Services\PdfMaker\Design as PdfMakerDesign;
use App\Services\PdfMaker\PdfMaker as PdfMakerService; use App\Services\PdfMaker\PdfMaker as PdfMakerService;
use App\Utils\HtmlEngine; use App\Utils\HtmlEngine;
use App\Utils\PhantomJS\Phantom; use App\Utils\PhantomJS\Phantom;
@ -82,17 +83,12 @@ class CreateQuotePdf implements ShouldQueue
$quote_design_id = $this->quote->design_id ? $this->quote->design_id : $this->decodePrimaryKey($this->quote->client->getSetting('quote_design_id')); $quote_design_id = $this->quote->design_id ? $this->quote->design_id : $this->decodePrimaryKey($this->quote->client->getSetting('quote_design_id'));
$design = Design::find($quote_design_id); $design = Design::find($quote_design_id);
$html = new HtmlEngine(null, $this->invitation, 'quote'); $html = new HtmlEngine(null, $this->invitation, 'quote');
$design_namespace = 'App\Services\PdfMaker\Designs\\'.$design->name; $template = new PdfMakerDesign(strtolower($design->name));
$design_class = new $design_namespace();
$pdf_variables = json_decode(json_encode($this->quote->company->settings->pdf_variables), 1);
$state = [ $state = [
'template' => $design_class->elements([ 'template' => $template->elements([
'client' => $this->quote->client, 'client' => $this->quote->client,
'entity' => $this->quote, 'entity' => $this->quote,
'pdf_variables' => (array) $this->quote->company->settings->pdf_variables, 'pdf_variables' => (array) $this->quote->company->settings->pdf_variables,
@ -107,7 +103,7 @@ class CreateQuotePdf implements ShouldQueue
$maker = new PdfMakerService($state); $maker = new PdfMakerService($state);
$maker $maker
->design($design_namespace) ->design($template)
->build(); ->build();
//todo - move this to the client creation stage so we don't keep hitting this unnecessarily //todo - move this to the client creation stage so we don't keep hitting this unnecessarily

View File

@ -92,6 +92,7 @@ class UserEmailChanged extends BaseMailerJob implements ShouldQueue
'button' => ctrans('texts.account_login'), 'button' => ctrans('texts.account_login'),
'signature' => $this->company->owner()->signature, 'signature' => $this->company->owner()->signature,
'logo' => $this->company->present()->logo(), 'logo' => $this->company->present()->logo(),
'settings' => $this->settings,
]; ];
} }
} }

View File

@ -56,7 +56,7 @@ class SendFailedEmails implements ShouldQueue
private function processEmails() private function processEmails()
{ {
\Log::error('processing emails'); //\Log::error('processing emails');
//info("process emails"); //info("process emails");
//@todo check that the quota is available for the job //@todo check that the quota is available for the job

View File

@ -89,6 +89,7 @@ class EntityPaidObject
'button' => ctrans('texts.view_payment'), 'button' => ctrans('texts.view_payment'),
'signature' => $settings->email_signature, 'signature' => $settings->email_signature,
'logo' => $this->company->present()->logo(), 'logo' => $this->company->present()->logo(),
'settings' => $settings,
]; ];
return $data; return $data;

View File

@ -84,6 +84,8 @@ class EntitySentObject
'button' => ctrans("texts.view_{$this->entity_type}"), 'button' => ctrans("texts.view_{$this->entity_type}"),
'signature' => $settings->email_signature, 'signature' => $settings->email_signature,
'logo' => $this->company->present()->logo(), 'logo' => $this->company->present()->logo(),
'settings' => $settings,
]; ];
} }
} }

View File

@ -84,6 +84,8 @@ class EntityViewedObject
'button' => ctrans("texts.view_{$this->entity_type}"), 'button' => ctrans("texts.view_{$this->entity_type}"),
'signature' => $settings->email_signature, 'signature' => $settings->email_signature,
'logo' => $this->company->present()->logo(), 'logo' => $this->company->present()->logo(),
'settings' => $settings,
]; ];
return $data; return $data;

View File

@ -76,6 +76,8 @@ class PaymentFailureObject
), ),
'signature' => $signature, 'signature' => $signature,
'logo' => $this->company->present()->logo(), 'logo' => $this->company->present()->logo(),
'settings' => $this->client->getMergedSettings(),
]; ];
return $data; return $data;

View File

@ -36,11 +36,11 @@ class RecurringInvoice extends BaseModel
/** /**
* Invoice Statuses. * Invoice Statuses.
*/ */
const STATUS_DRAFT = 2; const STATUS_DRAFT = 1;
const STATUS_ACTIVE = 3; const STATUS_ACTIVE = 2;
const STATUS_CANCELLED = 4; const STATUS_PAUSED = 3;
const STATUS_COMPLETED = 4;
const STATUS_PENDING = -1; const STATUS_PENDING = -1;
const STATUS_COMPLETED = -2;
/** /**
* Recurring intervals //todo MAP WHEN WE MIGRATE. * Recurring intervals //todo MAP WHEN WE MIGRATE.
@ -102,6 +102,7 @@ class RecurringInvoice extends BaseModel
'frequency_id', 'frequency_id',
'next_send_date', 'next_send_date',
'remaining_cycles', 'remaining_cycles',
'auto_bill',
]; ];
protected $casts = [ protected $casts = [
@ -189,13 +190,10 @@ class RecurringInvoice extends BaseModel
public function getStatusAttribute() public function getStatusAttribute()
{ {
if ($this->status_id == self::STATUS_ACTIVE && $this->next_send_date > Carbon::now()) { //marked as active, but yet to fire first cycle if ($this->status_id == self::STATUS_ACTIVE && $this->next_send_date > Carbon::now())
return self::STATUS_PENDING; return self::STATUS_PENDING;
} elseif ($this->status_id == self::STATUS_ACTIVE && $this->next_send_date > Carbon::now()) { else
return self::STATUS_COMPLETED;
} else {
return $this->status_id; return $this->status_id;
}
} }
public function nextSendDate() :?Carbon public function nextSendDate() :?Carbon
@ -288,16 +286,16 @@ class RecurringInvoice extends BaseModel
return '<h4><span class="badge badge-light">'.ctrans('texts.draft').'</span></h4>'; return '<h4><span class="badge badge-light">'.ctrans('texts.draft').'</span></h4>';
break; break;
case self::STATUS_PENDING: case self::STATUS_PENDING:
return '<h4><span class="badge badge-primary">'.ctrans('texts.sent').'</span></h4>'; return '<h4><span class="badge badge-primary">'.ctrans('texts.pending').'</span></h4>';
break; break;
case self::STATUS_ACTIVE: case self::STATUS_ACTIVE:
return '<h4><span class="badge badge-primary">'.ctrans('texts.partial').'</span></h4>'; return '<h4><span class="badge badge-primary">'.ctrans('texts.active').'</span></h4>';
break; break;
case self::STATUS_COMPLETED: case self::STATUS_COMPLETED:
return '<h4><span class="badge badge-success">'.ctrans('texts.status_completed').'</span></h4>'; return '<h4><span class="badge badge-success">'.ctrans('texts.status_completed').'</span></h4>';
break; break;
case self::STATUS_CANCELLED: case self::STATUS_PAUSED:
return '<h4><span class="badge badge-danger">'.ctrans('texts.overdue').'</span></h4>'; return '<h4><span class="badge badge-danger">'.ctrans('texts.paused').'</span></h4>';
break; break;
default: default:
// code... // code...
@ -368,7 +366,7 @@ class RecurringInvoice extends BaseModel
/* Return early if nothing to send back! */ /* Return early if nothing to send back! */
if( $this->status_id == self::STATUS_COMPLETED || if( $this->status_id == self::STATUS_COMPLETED ||
$this->status_id == self::STATUS_DRAFT || $this->status_id == self::STATUS_DRAFT ||
$this->status_id == self::STATUS_CANCELLED || $this->status_id == self::STATUS_PAUSED ||
$this->remaining_cycles == 0 || $this->remaining_cycles == 0 ||
!$this->next_send_date) { !$this->next_send_date) {

View File

@ -13,6 +13,7 @@ namespace App\Models;
use App\Models\Filterable; use App\Models\Filterable;
use App\Models\VendorContact; use App\Models\VendorContact;
use App\Utils\Traits\GeneratesCounter;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
@ -21,7 +22,8 @@ class Vendor extends BaseModel
{ {
use SoftDeletes; use SoftDeletes;
use Filterable; use Filterable;
use GeneratesCounter;
protected $fillable = [ protected $fillable = [
'name', 'name',
'id_number', 'id_number',
@ -34,6 +36,7 @@ class Vendor extends BaseModel
'postal_code', 'postal_code',
'country_id', 'country_id',
'private_notes', 'private_notes',
'public_notes',
'currency_id', 'currency_id',
'website', 'website',
'transaction_name', 'transaction_name',
@ -63,6 +66,12 @@ class Vendor extends BaseModel
return self::class; return self::class;
} }
public function primary_contact()
{
return $this->hasMany(VendorContact::class)->where('is_primary', true);
}
public function documents() public function documents()
{ {
return $this->morphMany(Document::class, 'documentable'); return $this->morphMany(Document::class, 'documentable');

View File

@ -1,4 +1,13 @@
<?php <?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Notifications\Admin; namespace App\Notifications\Admin;

View File

@ -1,4 +1,13 @@
<?php <?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Notifications\Admin; namespace App\Notifications\Admin;

View File

@ -1,4 +1,13 @@
<?php <?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Notifications\Admin; namespace App\Notifications\Admin;

View File

@ -1,4 +1,13 @@
<?php <?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Notifications\Admin; namespace App\Notifications\Admin;

View File

@ -1,4 +1,13 @@
<?php <?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Notifications\Admin; namespace App\Notifications\Admin;

View File

@ -1,4 +1,13 @@
<?php <?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Notifications\Admin; namespace App\Notifications\Admin;

View File

@ -1,4 +1,13 @@
<?php <?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Notifications; namespace App\Notifications;
@ -114,6 +123,7 @@ class BaseNotification extends Notification implements ShouldQueue
'view_text' => ctrans('texts.view_'.$this->entity_string), 'view_text' => ctrans('texts.view_'.$this->entity_string),
'logo' => $this->entity->company->present()->logo(), 'logo' => $this->entity->company->present()->logo(),
'signature' => $this->settings->email_signature, 'signature' => $this->settings->email_signature,
'settings' => $this->settings,
]; ];

View File

@ -1,4 +1,13 @@
<?php <?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Notifications; namespace App\Notifications;

View File

@ -1,4 +1,13 @@
<?php <?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Notifications; namespace App\Notifications;

View File

@ -1,4 +1,13 @@
<?php <?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Notifications; namespace App\Notifications;

View File

@ -1,4 +1,13 @@
<?php <?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Notifications; namespace App\Notifications;

View File

@ -1,4 +1,13 @@
<?php <?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Notifications\Ninja; namespace App\Notifications\Ninja;

View File

@ -1,4 +1,13 @@
<?php <?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Notifications\Ninja; namespace App\Notifications\Ninja;

View File

@ -1,4 +1,13 @@
<?php <?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Notifications; namespace App\Notifications;

View File

@ -134,8 +134,8 @@ class AuthorizePaymentMethod
$payment_meta = new \stdClass; $payment_meta = new \stdClass;
$payment_meta->exp_month = 'xx'; $payment_meta->exp_month = 'xx';
$payment_meta->exp_year = 'xx'; $payment_meta->exp_year = 'xx';
$payment_meta->brand = $payment_profile->getPaymentProfile()->getPayment()->getCreditCard()->getCardType(); $payment_meta->brand = (string)$payment_profile->getPaymentProfile()->getPayment()->getCreditCard()->getCardType();
$payment_meta->last4 = $payment_profile->getPaymentProfile()->getPayment()->getCreditCard()->getCardNumber(); $payment_meta->last4 = (string)$payment_profile->getPaymentProfile()->getPayment()->getCreditCard()->getCardNumber();
$payment_meta->type = $this->payment_method; $payment_meta->type = $this->payment_method;
return $payment_meta; return $payment_meta;

View File

@ -143,4 +143,15 @@ class AuthorizePaymentDriver extends BaseDriver
return $this->payment_method->tokenBilling($cgt, $payment_hash); return $this->payment_method->tokenBilling($cgt, $payment_hash);
} }
/**
* Detach payment method from Authorize.net.
*
* @param \App\Models\ClientGatewayToken $token
* @return void
*/
public function detach(ClientGatewayToken $token)
{
// Authorize.net doesn't support this feature.
}
} }

View File

@ -268,7 +268,7 @@ class CheckoutComPaymentDriver extends BaseDriver
$this->attachInvoices($payment, $state['payment_hash']); $this->attachInvoices($payment, $state['payment_hash']);
$payment->service()->updateInvoicePayment(); $payment->service()->updateInvoicePayment($state['payment_hash']);
event(new PaymentWasCreated($payment, $payment->company, Ninja::eventVars())); event(new PaymentWasCreated($payment, $payment->company, Ninja::eventVars()));

View File

@ -75,4 +75,15 @@ class CustomPaymentDriver extends BaseDriver
public function processPaymentResponse($request) public function processPaymentResponse($request)
{ {
} }
/**
* Detach payment method from custom payment driver.
*
* @param \App\Models\ClientGatewayToken $token
* @return void
*/
public function detach(ClientGatewayToken $token)
{
// Driver doesn't support this feature.
}
} }

View File

@ -322,4 +322,15 @@ class PayPalExpressPaymentDriver extends BasePaymentDriver
'code' => $response->getData()['L_ERRORCODE0'], 'code' => $response->getData()['L_ERRORCODE0'],
]; ];
} }
/**
* Detach payment method from PayPal.
*
* @param \App\Models\ClientGatewayToken $token
* @return void
*/
public function detach(ClientGatewayToken $token)
{
// PayPal doesn't support this feature.
}
} }

View File

@ -191,9 +191,9 @@ class ACH
$payment = $this->stripe->createPayment($data, Payment::STATUS_PENDING); $payment = $this->stripe->createPayment($data, Payment::STATUS_PENDING);
$this->stripe->attachInvoices($payment, $state['hashed_ids']); $this->stripe->attachInvoices($payment, $state['hashed_ids']); //todo remove hashed_ids
$payment->service()->updateInvoicePayment(); $payment->service()->updateInvoicePayment();//inject payment_hash
event(new PaymentWasCreated($payment, $payment->company, Ninja::eventVars())); event(new PaymentWasCreated($payment, $payment->company, Ninja::eventVars()));

View File

@ -61,10 +61,10 @@ class CreditCard
$stripe_payment_method->attach(['customer' => $customer->id]); $stripe_payment_method->attach(['customer' => $customer->id]);
$payment_meta = new \stdClass; $payment_meta = new \stdClass;
$payment_meta->exp_month = $stripe_payment_method_obj['card']['exp_month']; $payment_meta->exp_month = (string)$stripe_payment_method_obj['card']['exp_month'];
$payment_meta->exp_year = $stripe_payment_method_obj['card']['exp_year']; $payment_meta->exp_year = (string)$stripe_payment_method_obj['card']['exp_year'];
$payment_meta->brand = $stripe_payment_method_obj['card']['brand']; $payment_meta->brand = (string)$stripe_payment_method_obj['card']['brand'];
$payment_meta->last4 = $stripe_payment_method_obj['card']['last4']; $payment_meta->last4 = (string)$stripe_payment_method_obj['card']['last4'];
$payment_meta->type = GatewayType::CREDIT_CARD; $payment_meta->type = GatewayType::CREDIT_CARD;
$client_gateway_token = new ClientGatewayToken(); $client_gateway_token = new ClientGatewayToken();
@ -163,23 +163,23 @@ class CreditCard
$payment_method_object = $state['payment_method']->jsonSerialize(); $payment_method_object = $state['payment_method']->jsonSerialize();
$state['payment_meta'] = [ $state['payment_meta'] = [
'exp_month' => $payment_method_object['card']['exp_month'], 'exp_month' => (string)$payment_method_object['card']['exp_month'],
'exp_year' => $payment_method_object['card']['exp_year'], 'exp_year' => (string)$payment_method_object['card']['exp_year'],
'brand' => $payment_method_object['card']['brand'], 'brand' => (string)$payment_method_object['card']['brand'],
'last4' => $payment_method_object['card']['last4'], 'last4' => (string)$payment_method_object['card']['last4'],
'type' => $payment_method_object['type'], 'type' => GatewayType::CREDIT_CARD,
]; ];
$payment_meta = new \stdClass; $payment_meta = new \stdClass;
$payment_meta->exp_month = $payment_method_object['card']['exp_month']; $payment_meta->exp_month = (string)$payment_method_object['card']['exp_month'];
$payment_meta->exp_year = $payment_method_object['card']['exp_year']; $payment_meta->exp_year = (string)$payment_method_object['card']['exp_year'];
$payment_meta->brand = $payment_method_object['card']['brand']; $payment_meta->brand = (string)$payment_method_object['card']['brand'];
$payment_meta->last4 = $payment_method_object['card']['last4']; $payment_meta->last4 = (string)$payment_method_object['card']['last4'];
$payment_meta->type = $payment_method_object['type']; $payment_meta->type = GatewayType::CREDIT_CARD;
$payment_type = PaymentType::parseCardType($payment_method_object['card']['brand']); $payment_type = PaymentType::parseCardType($payment_method_object['card']['brand']);
if ($state['save_card'] == true) { if ($state['save_card'] == true || $state['save_card'] == 'true') {
$this->saveCard($state); $this->saveCard($state);
} }

View File

@ -312,7 +312,7 @@ class StripePaymentDriver extends BasePaymentDriver
$customer = \Stripe\Customer::create($data); $customer = \Stripe\Customer::create($data);
} }
if (! $customer) { if (!$customer) {
throw new \Exception('Unable to create gateway customer'); throw new \Exception('Unable to create gateway customer');
} }
@ -391,7 +391,7 @@ class StripePaymentDriver extends BasePaymentDriver
* @param float $amount The amount of the payment * @param float $amount The amount of the payment
* @return Payment The payment object * @return Payment The payment object
*/ */
public function createPaymentRecord($data, $amount) :?Payment public function createPaymentRecord($data, $amount): ?Payment
{ {
$payment = PaymentFactory::create($this->client->company_id, $this->client->user_id); $payment = PaymentFactory::create($this->client->company_id, $this->client->user_id);
$payment->client_id = $this->client->id; $payment->client_id = $this->client->id;
@ -407,4 +407,26 @@ class StripePaymentDriver extends BasePaymentDriver
return $payment->service()->applyNumber()->save(); return $payment->service()->applyNumber()->save();
} }
/**
* Detach payment method from the Stripe.
* https://stripe.com/docs/api/payment_methods/detach
*
* @param \App\Models\ClientGatewayToken $token
* @return bool
*/
public function detach(ClientGatewayToken $token)
{
$stripe = new \Stripe\StripeClient(
$this->company_gateway->getConfigField('apiKey')
);
try {
$response = $stripe->paymentMethods->detach($token->token);
} catch (\Exception $e) {
SystemLogger::dispatch([
'server_response' => $response, 'data' => request()->all(),
], SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_STRIPE, $this->client);
}
}
} }

View File

@ -56,7 +56,8 @@ class AppServiceProvider extends ServiceProvider
public function boot() public function boot()
{ {
Relation::morphMap([ Relation::morphMap([
'invoices' => \App\Models\Invoice::class, 'invoices' => \App\Models\Invoice::class,
// 'credits' => \App\Models\Credit::class,
'proposals' => \App\Models\Proposal::class, 'proposals' => \App\Models\Proposal::class,
]); ]);

View File

@ -225,6 +225,7 @@ class EventServiceProvider extends ServiceProvider
], ],
InvoiceWasPaid::class => [ InvoiceWasPaid::class => [
InvoicePaidActivity::class, InvoicePaidActivity::class,
CreateInvoicePdf::class,
], ],
InvoiceWasViewed::class => [ InvoiceWasViewed::class => [
InvoiceViewedActivity::class, InvoiceViewedActivity::class,
@ -238,6 +239,7 @@ class EventServiceProvider extends ServiceProvider
], ],
InvoiceWasDeleted::class => [ InvoiceWasDeleted::class => [
InvoiceDeletedActivity::class, InvoiceDeletedActivity::class,
CreateInvoicePdf::class,
], ],
InvoiceWasArchived::class => [ InvoiceWasArchived::class => [
InvoiceArchivedActivity::class, InvoiceArchivedActivity::class,
@ -247,6 +249,7 @@ class EventServiceProvider extends ServiceProvider
], ],
InvoiceWasReversed::class => [ InvoiceWasReversed::class => [
InvoiceReversedActivity::class, InvoiceReversedActivity::class,
CreateInvoicePdf::class,
], ],
InvoiceWasCancelled::class => [ InvoiceWasCancelled::class => [
InvoiceCancelledActivity::class, InvoiceCancelledActivity::class,

View File

@ -114,6 +114,7 @@ class PaymentRepository extends BaseRepository
$payment->invoices()->saveMany($invoices); $payment->invoices()->saveMany($invoices);
//todo optimize this into a single query
foreach ($data['invoices'] as $paid_invoice) { foreach ($data['invoices'] as $paid_invoice) {
$invoice = Invoice::whereId($paid_invoice['invoice_id'])->first(); $invoice = Invoice::whereId($paid_invoice['invoice_id'])->first();
@ -133,6 +134,7 @@ class PaymentRepository extends BaseRepository
$credits = Credit::whereIn('id', $this->transformKeys(array_column($data['credits'], 'credit_id')))->get(); $credits = Credit::whereIn('id', $this->transformKeys(array_column($data['credits'], 'credit_id')))->get();
$payment->credits()->saveMany($credits); $payment->credits()->saveMany($credits);
//todo optimize into a single query
foreach ($data['credits'] as $paid_credit) { foreach ($data['credits'] as $paid_credit) {
$credit = Credit::find($this->decodePrimaryKey($paid_credit['credit_id'])); $credit = Credit::find($this->decodePrimaryKey($paid_credit['credit_id']));

View File

@ -13,6 +13,7 @@ namespace App\Repositories;
use App\Models\Vendor; use App\Models\Vendor;
use App\Models\VendorContact; use App\Models\VendorContact;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str; use Illuminate\Support\Str;
/** /**
@ -58,9 +59,17 @@ class VendorContactRepository extends BaseRepository
$update_contact->fill($contact); $update_contact->fill($contact);
if (array_key_exists('password', $contact) && strlen($contact['password']) > 1) {
$update_contact->password = Hash::make($contact['password']);
}
$update_contact->save(); $update_contact->save();
}); });
$vendor->load('contacts');
//always made sure we have one blank contact to maintain state //always made sure we have one blank contact to maintain state
if ($contacts->count() == 0) { if ($contacts->count() == 0) {
$new_contact = new VendorContact; $new_contact = new VendorContact;

View File

@ -18,6 +18,7 @@ use App\Factory\InvoiceItemFactory;
use App\Factory\PaymentFactory; use App\Factory\PaymentFactory;
use App\Helpers\Invoice\InvoiceSum; use App\Helpers\Invoice\InvoiceSum;
use App\Models\Client; use App\Models\Client;
use App\Models\Credit;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\Payment; use App\Models\Payment;
use App\Models\Paymentable; use App\Models\Paymentable;
@ -55,7 +56,7 @@ class HandleReversal extends AbstractService
$total_paid = $this->invoice->amount - $this->invoice->balance; $total_paid = $this->invoice->amount - $this->invoice->balance;
/*Adjust payment applied and the paymentables to the correct amount */ /*Adjust payment applied and the paymentables to the correct amount */
$paymentables = Paymentable::wherePaymentableType(Invoice::class) $paymentables = Paymentable::wherePaymentableType('invoices')
->wherePaymentableId($this->invoice->id) ->wherePaymentableId($this->invoice->id)
->get(); ->get();
@ -95,6 +96,23 @@ class HandleReversal extends AbstractService
$credit->service()->markSent()->save(); $credit->service()->markSent()->save();
} }
/*If there is a payment linked, then the credit needs to be linked back to that payment in case of refund*/
if($paymentables->count() > 0){
$payment = $paymentables->first()->payment;
$payment->credits()->save($credit);
$paymentable_credit = $payment->credits()
->wherePaymentableType(Credit::class)
->wherePaymentableId($credit->id)
->first();
//harvest the credit record and add in the amount for the credit.
$paymentable_credit->pivot->amount = $total_paid;
$paymentable_credit->pivot->save();
}
/* Set invoice balance to 0 */ /* Set invoice balance to 0 */
if ($this->invoice->balance != 0) { if ($this->invoice->balance != 0) {
$this->invoice->ledger()->updateInvoiceBalance($balance_remaining * -1, $notes)->save(); $this->invoice->ledger()->updateInvoiceBalance($balance_remaining * -1, $notes)->save();
@ -119,37 +137,4 @@ class HandleReversal extends AbstractService
//create a ledger row for this with the resulting Credit ( also include an explanation in the notes section ) //create a ledger row for this with the resulting Credit ( also include an explanation in the notes section )
} }
// public function run2()
// {
// /* Check again!! */
// if (!$this->invoice->invoiceReversable($this->invoice)) {
// return $this->invoice;
// }
// if($this->invoice->status_id == Invoice::STATUS_CANCELLED)
// $this->invoice = $this->invoice->service()->reverseCancellation()->save();
// //$balance_remaining = $this->invoice->balance;
// //$total_paid = $this->invoice->amount - $this->invoice->balance;
// /*Adjust payment applied and the paymentables to the correct amount */
// $paymentables = Paymentable::wherePaymentableType(Invoice::class)
// ->wherePaymentableId($this->invoice->id)
// ->get();
// $total_paid = 0;
// $paymentables->each(function ($paymentable) use ($total_paid) {
// $reversable_amount = $paymentable->amount - $paymentable->refunded;
// $total_paid -= $reversable_amount;
// $paymentable->amount = $paymentable->refunded;
// $paymentable->save();
// });
// //Unwinding any payments made to this invoice
// }
} }

View File

@ -206,6 +206,9 @@ class InvoiceService
if($this->invoice->balance == 0) if($this->invoice->balance == 0)
$this->setStatus(Invoice::STATUS_PAID); $this->setStatus(Invoice::STATUS_PAID);
if($this->invoice->balance > 0 && $this->invoice->balance < $this->invoice->amount)
$this->setStatus(Invoice::STATUS_PARTIAL);
return $this; return $this;
} }

View File

@ -14,6 +14,7 @@ namespace App\Services\Payment;
use App\Factory\PaymentFactory; use App\Factory\PaymentFactory;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\Payment; use App\Models\Payment;
use App\Models\PaymentHash;
use App\Services\Payment\ApplyNumber; use App\Services\Payment\ApplyNumber;
use App\Services\Payment\DeletePayment; use App\Services\Payment\DeletePayment;
use App\Services\Payment\RefundPayment; use App\Services\Payment\RefundPayment;
@ -84,7 +85,7 @@ class PaymentService
return (new DeletePayment($this->payment))->run(); return (new DeletePayment($this->payment))->run();
} }
public function updateInvoicePayment($payment_hash = null) :?Payment public function updateInvoicePayment(PaymentHash $payment_hash) :?Payment
{ {
return ((new UpdateInvoicePayment($this->payment, $payment_hash)))->run(); return ((new UpdateInvoicePayment($this->payment, $payment_hash)))->run();
} }

View File

@ -16,6 +16,8 @@ use App\Helpers\Email\PaymentEmail;
use App\Jobs\Payment\EmailPayment; use App\Jobs\Payment\EmailPayment;
use App\Jobs\Util\SystemLogger; use App\Jobs\Util\SystemLogger;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\Payment;
use App\Models\PaymentHash;
use App\Models\SystemLog; use App\Models\SystemLog;
use App\Utils\Ninja; use App\Utils\Ninja;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
@ -28,7 +30,7 @@ class UpdateInvoicePayment
public $payment_hash; public $payment_hash;
public function __construct($payment, $payment_hash) public function __construct(Payment $payment, PaymentHash $payment_hash)
{ {
$this->payment = $payment; $this->payment = $payment;
$this->payment_hash = $payment_hash; $this->payment_hash = $payment_hash;
@ -41,6 +43,7 @@ class UpdateInvoicePayment
$invoices = Invoice::whereIn('id', $this->transformKeys(array_column($paid_invoices, 'invoice_id')))->get(); $invoices = Invoice::whereIn('id', $this->transformKeys(array_column($paid_invoices, 'invoice_id')))->get();
collect($paid_invoices)->each(function ($paid_invoice) use ($invoices) { collect($paid_invoices)->each(function ($paid_invoice) use ($invoices) {
$invoice = $invoices->first(function ($inv) use ($paid_invoice) { $invoice = $invoices->first(function ($inv) use ($paid_invoice) {
return $paid_invoice->invoice_id == $inv->hashed_id; return $paid_invoice->invoice_id == $inv->hashed_id;
}); });
@ -68,7 +71,9 @@ class UpdateInvoicePayment
/*update paymentable record*/ /*update paymentable record*/
$pivot_invoice->pivot->amount = $paid_amount; $pivot_invoice->pivot->amount = $paid_amount;
$pivot_invoice->save(); $pivot_invoice->pivot->save();
$this->payment->applied += $paid_amount;
$invoice->service() //caution what if we amount paid was less than partial - we wipe it! $invoice->service() //caution what if we amount paid was less than partial - we wipe it!
->clearPartial() ->clearPartial()
@ -79,6 +84,8 @@ class UpdateInvoicePayment
event(new InvoiceWasUpdated($invoice, $invoice->company, Ninja::eventVars())); event(new InvoiceWasUpdated($invoice, $invoice->company, Ninja::eventVars()));
}); });
$this->payment->save();
return $this->payment; return $this->payment;
} }

View File

@ -76,6 +76,7 @@ class VendorTransformer extends EntityTransformer
'name' => $vendor->name ?: '', 'name' => $vendor->name ?: '',
'website' => $vendor->website ?: '', 'website' => $vendor->website ?: '',
'private_notes' => $vendor->private_notes ?: '', 'private_notes' => $vendor->private_notes ?: '',
'public_notes' => $vendor->public_notes ?: '',
'last_login' => (int) $vendor->last_login, 'last_login' => (int) $vendor->last_login,
'address1' => $vendor->address1 ?: '', 'address1' => $vendor->address1 ?: '',
'address2' => $vendor->address2 ?: '', 'address2' => $vendor->address2 ?: '',

View File

@ -1,4 +1,13 @@
<?php <?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Utils\ClientPortal\CustomMessage; namespace App\Utils\ClientPortal\CustomMessage;

View File

@ -1,4 +1,13 @@
<?php <?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Utils\ClientPortal\CustomMessage; namespace App\Utils\ClientPortal\CustomMessage;

View File

@ -37,6 +37,8 @@ class TemplateEngine
private $settings_entity; private $settings_entity;
private $settings;
public function __construct($body, $subject, $entity, $entity_id, $template) public function __construct($body, $subject, $entity, $entity_id, $template)
{ {
$this->body = $body; $this->body = $body;
@ -77,8 +79,10 @@ class TemplateEngine
{ {
if ($this->entity_obj) { if ($this->entity_obj) {
$this->settings_entity = $this->entity_obj->client; $this->settings_entity = $this->entity_obj->client;
$this->settings = $this->settings_entity->getMergedSettings();
} else { } else {
$this->settings_entity = auth()->user()->company(); $this->settings_entity = auth()->user()->company();
$this->settings = $this->settings_entity->settings;
} }
return $this; return $this;
@ -168,6 +172,7 @@ class TemplateEngine
$data['body'] = '$body'; $data['body'] = '$body';
$data['footer'] = ''; $data['footer'] = '';
$data['signature'] = $this->settings_entity->getSetting('email_signature'); $data['signature'] = $this->settings_entity->getSetting('email_signature');
$data['settings'] = $this->settings;
if ($email_style == 'custom') { if ($email_style == 'custom') {
$wrapper = $this->settings_entity->getSetting('email_style_custom'); $wrapper = $this->settings_entity->getSetting('email_style_custom');

View File

@ -13,11 +13,13 @@ namespace App\Utils\Traits;
use App\Models\Client; use App\Models\Client;
use App\Models\Credit; use App\Models\Credit;
use App\Models\Expense;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\Payment; use App\Models\Payment;
use App\Models\Quote; use App\Models\Quote;
use App\Models\RecurringInvoice; use App\Models\RecurringInvoice;
use App\Models\Timezone; use App\Models\Timezone;
use App\Models\Vendor;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
/** /**
@ -238,6 +240,28 @@ trait GeneratesCounter
return $client_number; return $client_number;
} }
/**
* Gets the next client number.
*
* @param \App\Models\Vendor $vendor The vendor
* @return string The next vendor number.
*/
public function getNextVendorNumber(Vendor $vendor) :string
{
$this->resetCompanyCounters($vendor->company);
$counter = $vendor->company->settings->vendor_number_counter;
$setting_entity = $vendor->company->settings->vendor_number_counter;
$vendor_number = $this->checkEntityNumber(Vendor::class, $vendor, $counter, $vendor->company->settings->counter_padding, $vendor->company->settings->vendor_number_pattern);
$this->incrementCounter($vendor->company, 'vendor_number_counter');
return $vendor_number;
}
/** /**
* Determines if it has shared counter. * Determines if it has shared counter.
* *
@ -254,33 +278,29 @@ trait GeneratesCounter
* Checks that the number has not already been used. * Checks that the number has not already been used.
* *
* @param Collection $entity The entity ie App\Models\Client, Invoice, Quote etc * @param Collection $entity The entity ie App\Models\Client, Invoice, Quote etc
* @param int $counter The counter * @param int $counter The counter
* @param int $padding The padding * @param int $padding The padding
* *
* @return string The padded and prefixed invoice number * @return string The padded and prefixed entity number
*/ */
private function checkEntityNumber($class, $client, $counter, $padding, $pattern) private function checkEntityNumber($class, $entity, $counter, $padding, $pattern)
{ {
$check = false; $check = false;
do { do {
$number = $this->padCounter($counter, $padding); $number = $this->padCounter($counter, $padding);
$number = $this->applyNumberPattern($client, $number, $pattern); $number = $this->applyNumberPattern($entity, $number, $pattern);
if ($class == Invoice::class || $class == RecurringInvoice::class) {
$check = $class::whereCompanyId($client->company_id)->whereNumber($number)->withTrashed()->first();
} elseif ($class == Client::class) {
$check = $class::whereCompanyId($client->company_id)->whereIdNumber($number)->withTrashed()->first();
} elseif ($class == Credit::class) {
$check = $class::whereCompanyId($client->company_id)->whereNumber($number)->withTrashed()->first();
} elseif ($class == Quote::class) {
$check = $class::whereCompanyId($client->company_id)->whereNumber($number)->withTrashed()->first();
} elseif ($class == Payment::class) {
$check = $class::whereCompanyId($client->company_id)->whereNumber($number)->withTrashed()->first();
}
if ($class == Invoice::class || $class == RecurringInvoice::class)
$check = $class::whereCompanyId($entity->company_id)->whereNumber($number)->withTrashed()->first();
elseif ($class == Client::class || $class == Vendor::class)
$check = $class::whereCompanyId($entity->company_id)->whereIdNumber($number)->withTrashed()->first();
else
$check = $class::whereCompanyId($entity->company_id)->whereNumber($number)->withTrashed()->first();
$counter++; $counter++;
} while ($check); } while ($check);
return $number; return $number;
@ -389,16 +409,74 @@ trait GeneratesCounter
$client->company->save(); $client->company->save();
} }
private function resetCompanyCounters($company)
{
$timezone = Timezone::find($company->settings->timezone_id);
$reset_date = Carbon::parse($company->settings->reset_counter_date, $timezone->name);
if (! $reset_date->isToday() || ! $company->settings->reset_counter_date) {
return false;
}
switch ($company->reset_counter_frequency_id) {
case RecurringInvoice::FREQUENCY_WEEKLY:
$reset_date->addWeek();
break;
case RecurringInvoice::FREQUENCY_TWO_WEEKS:
$reset_date->addWeeks(2);
break;
case RecurringInvoice::FREQUENCY_FOUR_WEEKS:
$reset_date->addWeeks(4);
break;
case RecurringInvoice::FREQUENCY_MONTHLY:
$reset_date->addMonth();
break;
case RecurringInvoice::FREQUENCY_TWO_MONTHS:
$reset_date->addMonths(2);
break;
case RecurringInvoice::FREQUENCY_THREE_MONTHS:
$reset_date->addMonths(3);
break;
case RecurringInvoice::FREQUENCY_FOUR_MONTHS:
$reset_date->addMonths(4);
break;
case RecurringInvoice::FREQUENCY_SIX_MONTHS:
$reset_date->addMonths(6);
break;
case RecurringInvoice::FREQUENCY_ANNUALLY:
$reset_date->addYear();
break;
case RecurringInvoice::FREQUENCY_TWO_YEARS:
$reset_date->addYears(2);
break;
}
$settings = $company->settings;
$settings->reset_counter_date = $reset_date->format('Y-m-d');
$settings->invoice_number_counter = 1;
$settings->quote_number_counter = 1;
$settings->credit_number_counter = 1;
$settings->vendor_number_counter = 1;
$settings->ticket_number_counter = 1;
$settings->payment_number_counter = 1;
$settings->task_number_counter = 1;
$settings->expense_number_counter = 1;
$company->settings = $settings;
$company->save();
}
/** /**
* { function_description }. * Formats a entity number by pattern
* *
* @param \App\Models\Client $client The client * @param \App\Models\BaseModel $entity The entity object
* @param string $counter The counter * @param string $counter The counter
* @param null|string $pattern The pattern * @param null|string $pattern The pattern
* *
* @return string ( description_of_the_return_value ) * @return string The formatted number pattern
*/ */
private function applyNumberPattern(Client $client, string $counter, $pattern) :string private function applyNumberPattern($entity, string $counter, $pattern) :string
{ {
if (! $pattern) { if (! $pattern) {
return $counter; return $counter;
@ -417,7 +495,7 @@ trait GeneratesCounter
$replace[] = $counter; $replace[] = $counter;
if (strstr($pattern, '{$user_id}')) { if (strstr($pattern, '{$user_id}')) {
$user_id = $client->user_id ? $client->user_id : 0; $user_id = $entity->user_id ? $entity->user_id : 0;
$search[] = '{$user_id}'; $search[] = '{$user_id}';
$replace[] = str_pad(($user_id), 2, '0', STR_PAD_LEFT); $replace[] = str_pad(($user_id), 2, '0', STR_PAD_LEFT);
} }
@ -429,24 +507,24 @@ trait GeneratesCounter
$search[] = $matches[0]; $search[] = $matches[0];
/* The following adjusts for the company timezone - may bork tests depending on the time of day the tests are run!!!!!!*/ /* The following adjusts for the company timezone - may bork tests depending on the time of day the tests are run!!!!!!*/
$date = Carbon::now($client->company->timezone()->name)->format($format); $date = Carbon::now($entity->company->timezone()->name)->format($format);
$replace[] = str_replace($format, $date, $matches[1]); $replace[] = str_replace($format, $date, $matches[1]);
} }
$search[] = '{$custom1}'; $search[] = '{$custom1}';
$replace[] = $client->custom_value1; $replace[] = $entity->custom_value1;
$search[] = '{$custom2}'; $search[] = '{$custom2}';
$replace[] = $client->custom_value2; $replace[] = $entity->custom_value2;
$search[] = '{$custom3}'; $search[] = '{$custom3}';
$replace[] = $client->custom_value3; $replace[] = $entity->custom_value3;
$search[] = '{$custom4}'; $search[] = '{$custom4}';
$replace[] = $client->custom_value4; $replace[] = $entity->custom_value4;
$search[] = '{$id_number}'; $search[] = '{$id_number}';
$replace[] = $client->id_number; $replace[] = $entity->id_number;
return str_replace($search, $replace, $pattern); return str_replace($search, $replace, $pattern);
} }

381
composer.lock generated
View File

@ -108,16 +108,16 @@
}, },
{ {
"name": "aws/aws-sdk-php", "name": "aws/aws-sdk-php",
"version": "3.154.1", "version": "3.154.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/aws/aws-sdk-php.git", "url": "https://github.com/aws/aws-sdk-php.git",
"reference": "5651d8a92164d98869b70a15e4c06ce4c14c7c28" "reference": "83a1382930359e4d4f4c9187239f059d5b282520"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/5651d8a92164d98869b70a15e4c06ce4c14c7c28", "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/83a1382930359e4d4f4c9187239f059d5b282520",
"reference": "5651d8a92164d98869b70a15e4c06ce4c14c7c28", "reference": "83a1382930359e4d4f4c9187239f059d5b282520",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -189,7 +189,7 @@
"s3", "s3",
"sdk" "sdk"
], ],
"time": "2020-09-11T18:12:41+00:00" "time": "2020-09-18T18:16:42+00:00"
}, },
{ {
"name": "brick/math", "name": "brick/math",
@ -245,16 +245,16 @@
}, },
{ {
"name": "checkout/checkout-sdk-php", "name": "checkout/checkout-sdk-php",
"version": "1.0.8", "version": "1.0.10",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/checkout/checkout-sdk-php.git", "url": "https://github.com/checkout/checkout-sdk-php.git",
"reference": "c83ecc54e549efde8ac53cf1bc9701e800d98b0b" "reference": "837f9622165f3ae4f9fdf8d0eca5da2ec46984fa"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/checkout/checkout-sdk-php/zipball/c83ecc54e549efde8ac53cf1bc9701e800d98b0b", "url": "https://api.github.com/repos/checkout/checkout-sdk-php/zipball/837f9622165f3ae4f9fdf8d0eca5da2ec46984fa",
"reference": "c83ecc54e549efde8ac53cf1bc9701e800d98b0b", "reference": "837f9622165f3ae4f9fdf8d0eca5da2ec46984fa",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -296,7 +296,7 @@
"php", "php",
"sdk" "sdk"
], ],
"time": "2019-07-05T16:22:08+00:00" "time": "2020-09-17T15:39:25+00:00"
}, },
{ {
"name": "cleverit/ubl_invoice", "name": "cleverit/ubl_invoice",
@ -1084,16 +1084,16 @@
}, },
{ {
"name": "doctrine/dbal", "name": "doctrine/dbal",
"version": "2.10.3", "version": "2.10.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/doctrine/dbal.git", "url": "https://github.com/doctrine/dbal.git",
"reference": "03ca23afc2ee062f5d3e32426ad37c34a4770dcf" "reference": "47433196b6390d14409a33885ee42b6208160643"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/doctrine/dbal/zipball/03ca23afc2ee062f5d3e32426ad37c34a4770dcf", "url": "https://api.github.com/repos/doctrine/dbal/zipball/47433196b6390d14409a33885ee42b6208160643",
"reference": "03ca23afc2ee062f5d3e32426ad37c34a4770dcf", "reference": "47433196b6390d14409a33885ee42b6208160643",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1189,7 +1189,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2020-09-02T01:35:42+00:00" "time": "2020-09-12T21:20:41+00:00"
}, },
{ {
"name": "doctrine/event-manager", "name": "doctrine/event-manager",
@ -1562,21 +1562,22 @@
}, },
{ {
"name": "fedeisas/laravel-mail-css-inliner", "name": "fedeisas/laravel-mail-css-inliner",
"version": "3.0.1", "version": "3.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/fedeisas/laravel-mail-css-inliner.git", "url": "https://github.com/fedeisas/laravel-mail-css-inliner.git",
"reference": "f414cb31536dcb132338042c8b7fd43e73fbb1b9" "reference": "263f395b46ef9666151ac78daf429632b0b2e2c3"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/fedeisas/laravel-mail-css-inliner/zipball/f414cb31536dcb132338042c8b7fd43e73fbb1b9", "url": "https://api.github.com/repos/fedeisas/laravel-mail-css-inliner/zipball/263f395b46ef9666151ac78daf429632b0b2e2c3",
"reference": "f414cb31536dcb132338042c8b7fd43e73fbb1b9", "reference": "263f395b46ef9666151ac78daf429632b0b2e2c3",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-dom": "*", "ext-dom": "*",
"illuminate/support": "^7.4", "illuminate/mail": "^7.4 || ^8.0",
"illuminate/support": "^7.4 || ^8.0",
"php": "^7.2.5", "php": "^7.2.5",
"tijsverkoyen/css-to-inline-styles": "~2.0" "tijsverkoyen/css-to-inline-styles": "~2.0"
}, },
@ -1613,7 +1614,7 @@
"laravel", "laravel",
"mailer" "mailer"
], ],
"time": "2020-04-08T17:22:14+00:00" "time": "2020-09-12T05:00:14+00:00"
}, },
{ {
"name": "fideloper/proxy", "name": "fideloper/proxy",
@ -1771,16 +1772,16 @@
}, },
{ {
"name": "google/apiclient", "name": "google/apiclient",
"version": "v2.7.1", "version": "v2.7.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/googleapis/google-api-php-client.git", "url": "https://github.com/googleapis/google-api-php-client.git",
"reference": "e748d1d5a51166754f13809d35f1fa162cbec530" "reference": "9df720d72c59456b5466e3f66e1e78cfe422a5ba"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/googleapis/google-api-php-client/zipball/e748d1d5a51166754f13809d35f1fa162cbec530", "url": "https://api.github.com/repos/googleapis/google-api-php-client/zipball/9df720d72c59456b5466e3f66e1e78cfe422a5ba",
"reference": "e748d1d5a51166754f13809d35f1fa162cbec530", "reference": "9df720d72c59456b5466e3f66e1e78cfe422a5ba",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1829,20 +1830,20 @@
"keywords": [ "keywords": [
"google" "google"
], ],
"time": "2020-09-08T16:38:08+00:00" "time": "2020-09-18T20:02:04+00:00"
}, },
{ {
"name": "google/apiclient-services", "name": "google/apiclient-services",
"version": "v0.145", "version": "v0.146",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/googleapis/google-api-php-client-services.git", "url": "https://github.com/googleapis/google-api-php-client-services.git",
"reference": "96de5dabadb693f161a31a1a1e018882fa05816e" "reference": "029e20e81508cee6dc652529514eeeb1cf56ce54"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/96de5dabadb693f161a31a1a1e018882fa05816e", "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/029e20e81508cee6dc652529514eeeb1cf56ce54",
"reference": "96de5dabadb693f161a31a1a1e018882fa05816e", "reference": "029e20e81508cee6dc652529514eeeb1cf56ce54",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1866,20 +1867,20 @@
"keywords": [ "keywords": [
"google" "google"
], ],
"time": "2020-09-05T00:24:41+00:00" "time": "2020-09-12T00:24:59+00:00"
}, },
{ {
"name": "google/auth", "name": "google/auth",
"version": "v1.12.0", "version": "v1.13.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/googleapis/google-auth-library-php.git", "url": "https://github.com/googleapis/google-auth-library-php.git",
"reference": "74cad289014f7ef747618480f6b59f6303357f34" "reference": "173191f5defd1d9ae8bdfc28da31b63eb73dd34e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/googleapis/google-auth-library-php/zipball/74cad289014f7ef747618480f6b59f6303357f34", "url": "https://api.github.com/repos/googleapis/google-auth-library-php/zipball/173191f5defd1d9ae8bdfc28da31b63eb73dd34e",
"reference": "74cad289014f7ef747618480f6b59f6303357f34", "reference": "173191f5defd1d9ae8bdfc28da31b63eb73dd34e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1918,7 +1919,7 @@
"google", "google",
"oauth2" "oauth2"
], ],
"time": "2020-09-08T16:33:56+00:00" "time": "2020-09-18T20:03:05+00:00"
}, },
{ {
"name": "guzzlehttp/guzzle", "name": "guzzlehttp/guzzle",
@ -2297,24 +2298,24 @@
}, },
{ {
"name": "jean85/pretty-package-versions", "name": "jean85/pretty-package-versions",
"version": "1.5.0", "version": "1.5.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/Jean85/pretty-package-versions.git", "url": "https://github.com/Jean85/pretty-package-versions.git",
"reference": "e9f4324e88b8664be386d90cf60fbc202e1f7fc9" "reference": "a917488320c20057da87f67d0d40543dd9427f7a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/e9f4324e88b8664be386d90cf60fbc202e1f7fc9", "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/a917488320c20057da87f67d0d40543dd9427f7a",
"reference": "e9f4324e88b8664be386d90cf60fbc202e1f7fc9", "reference": "a917488320c20057da87f67d0d40543dd9427f7a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"composer/package-versions-deprecated": "^1.8.0", "composer/package-versions-deprecated": "^1.8.0",
"php": "^7.0" "php": "^7.0|^8.0"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^6.0" "phpunit/phpunit": "^6.0|^8.5|^9.2"
}, },
"type": "library", "type": "library",
"extra": { "extra": {
@ -2344,7 +2345,7 @@
"release", "release",
"versions" "versions"
], ],
"time": "2020-06-23T06:23:06+00:00" "time": "2020-09-14T08:43:34+00:00"
}, },
{ {
"name": "justinrainbow/json-schema", "name": "justinrainbow/json-schema",
@ -2460,16 +2461,16 @@
}, },
{ {
"name": "laravel/framework", "name": "laravel/framework",
"version": "v7.28.1", "version": "v7.28.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/laravel/framework.git", "url": "https://github.com/laravel/framework.git",
"reference": "f7493ab717ca2a9598b1db2d6a3bae8ac8c755e8" "reference": "b0942c391975972b1a54b2dc983e33a239f169a9"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/f7493ab717ca2a9598b1db2d6a3bae8ac8c755e8", "url": "https://api.github.com/repos/laravel/framework/zipball/b0942c391975972b1a54b2dc983e33a239f169a9",
"reference": "f7493ab717ca2a9598b1db2d6a3bae8ac8c755e8", "reference": "b0942c391975972b1a54b2dc983e33a239f169a9",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2614,7 +2615,7 @@
"framework", "framework",
"laravel" "laravel"
], ],
"time": "2020-09-09T15:02:46+00:00" "time": "2020-09-17T14:23:26+00:00"
}, },
{ {
"name": "laravel/slack-notification-channel", "name": "laravel/slack-notification-channel",
@ -2859,16 +2860,16 @@
}, },
{ {
"name": "league/commonmark", "name": "league/commonmark",
"version": "1.5.4", "version": "1.5.5",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/thephpleague/commonmark.git", "url": "https://github.com/thephpleague/commonmark.git",
"reference": "21819c989e69bab07e933866ad30c7e3f32984ba" "reference": "45832dfed6007b984c0d40addfac48d403dc6432"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/21819c989e69bab07e933866ad30c7e3f32984ba", "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/45832dfed6007b984c0d40addfac48d403dc6432",
"reference": "21819c989e69bab07e933866ad30c7e3f32984ba", "reference": "45832dfed6007b984c0d40addfac48d403dc6432",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2880,7 +2881,7 @@
}, },
"require-dev": { "require-dev": {
"cebe/markdown": "~1.0", "cebe/markdown": "~1.0",
"commonmark/commonmark.js": "0.29.1", "commonmark/commonmark.js": "0.29.2",
"erusev/parsedown": "~1.0", "erusev/parsedown": "~1.0",
"ext-json": "*", "ext-json": "*",
"github/gfm": "0.29.0", "github/gfm": "0.29.0",
@ -2950,7 +2951,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2020-08-18T01:19:12+00:00" "time": "2020-09-13T14:44:46+00:00"
}, },
{ {
"name": "league/flysystem", "name": "league/flysystem",
@ -3438,16 +3439,16 @@
}, },
{ {
"name": "livewire/livewire", "name": "livewire/livewire",
"version": "v1.3.3", "version": "v1.3.5",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/livewire/livewire.git", "url": "https://github.com/livewire/livewire.git",
"reference": "d3df4ec046d2886bbf43d4cd8d8d9858e422e2ce" "reference": "b1673ff9fc78a3296ca4a3b0d1ca26da0a5cdf82"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/livewire/livewire/zipball/d3df4ec046d2886bbf43d4cd8d8d9858e422e2ce", "url": "https://api.github.com/repos/livewire/livewire/zipball/b1673ff9fc78a3296ca4a3b0d1ca26da0a5cdf82",
"reference": "d3df4ec046d2886bbf43d4cd8d8d9858e422e2ce", "reference": "b1673ff9fc78a3296ca4a3b0d1ca26da0a5cdf82",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3497,7 +3498,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2020-08-21T15:57:49+00:00" "time": "2020-09-17T04:38:16+00:00"
}, },
{ {
"name": "maennchen/zipstream-php", "name": "maennchen/zipstream-php",
@ -3838,16 +3839,16 @@
}, },
{ {
"name": "nesbot/carbon", "name": "nesbot/carbon",
"version": "2.39.2", "version": "2.40.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/briannesbitt/Carbon.git", "url": "https://github.com/briannesbitt/Carbon.git",
"reference": "326efde1bc09077a26cb77f6e2e32e13f06c27f2" "reference": "6c7646154181013ecd55e80c201b9fd873c6ee5d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/326efde1bc09077a26cb77f6e2e32e13f06c27f2", "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/6c7646154181013ecd55e80c201b9fd873c6ee5d",
"reference": "326efde1bc09077a26cb77f6e2e32e13f06c27f2", "reference": "6c7646154181013ecd55e80c201b9fd873c6ee5d",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3923,7 +3924,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2020-09-10T12:16:42+00:00" "time": "2020-09-11T19:00:58+00:00"
}, },
{ {
"name": "nikic/php-parser", "name": "nikic/php-parser",
@ -5907,22 +5908,22 @@
}, },
{ {
"name": "sentry/sdk", "name": "sentry/sdk",
"version": "2.1.0", "version": "2.2.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/getsentry/sentry-php-sdk.git", "url": "https://github.com/getsentry/sentry-php-sdk.git",
"reference": "18921af9c2777517ef9fb480845c22a98554d6af" "reference": "089858b1b27d3705a5fd1c32d8d10beb55980190"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/getsentry/sentry-php-sdk/zipball/18921af9c2777517ef9fb480845c22a98554d6af", "url": "https://api.github.com/repos/getsentry/sentry-php-sdk/zipball/089858b1b27d3705a5fd1c32d8d10beb55980190",
"reference": "18921af9c2777517ef9fb480845c22a98554d6af", "reference": "089858b1b27d3705a5fd1c32d8d10beb55980190",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"http-interop/http-factory-guzzle": "^1.0", "http-interop/http-factory-guzzle": "^1.0",
"php-http/guzzle6-adapter": "^1.1|^2.0", "sentry/sentry": "^2.5",
"sentry/sentry": "^2.3" "symfony/http-client": "^4.3|^5.0"
}, },
"type": "metapackage", "type": "metapackage",
"notification-url": "https://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
@ -5935,21 +5936,41 @@
"email": "accounts@sentry.io" "email": "accounts@sentry.io"
} }
], ],
"description": "This is a metapackage shipping sentry/sentry with a recommended http client.", "description": "This is a metapackage shipping sentry/sentry with a recommended HTTP client.",
"time": "2020-01-08T19:16:29+00:00" "homepage": "http://sentry.io",
"keywords": [
"crash-reporting",
"crash-reports",
"error-handler",
"error-monitoring",
"log",
"logging",
"sentry"
],
"funding": [
{
"url": "https://sentry.io/",
"type": "custom"
},
{
"url": "https://sentry.io/pricing/",
"type": "custom"
}
],
"time": "2020-09-14T09:30:55+00:00"
}, },
{ {
"name": "sentry/sentry", "name": "sentry/sentry",
"version": "2.4.3", "version": "2.5.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/getsentry/sentry-php.git", "url": "https://github.com/getsentry/sentry-php.git",
"reference": "89fd1f91657b33ec9139f33f8a201eb086276103" "reference": "bab5b73dbaf5f0ff62317e1611d952764d5514a9"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/getsentry/sentry-php/zipball/89fd1f91657b33ec9139f33f8a201eb086276103", "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/bab5b73dbaf5f0ff62317e1611d952764d5514a9",
"reference": "89fd1f91657b33ec9139f33f8a201eb086276103", "reference": "bab5b73dbaf5f0ff62317e1611d952764d5514a9",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -5991,7 +6012,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "2.4-dev" "dev-master": "2.5.x-dev"
} }
}, },
"autoload": { "autoload": {
@ -6033,7 +6054,7 @@
"type": "custom" "type": "custom"
} }
], ],
"time": "2020-08-13T10:54:32+00:00" "time": "2020-09-14T07:02:40+00:00"
}, },
{ {
"name": "sentry/sentry-laravel", "name": "sentry/sentry-laravel",
@ -7072,6 +7093,167 @@
], ],
"time": "2020-08-17T10:01:29+00:00" "time": "2020-08-17T10:01:29+00:00"
}, },
{
"name": "symfony/http-client",
"version": "v5.1.5",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-client.git",
"reference": "21c4372e9cd2305313f4d4792d7b9fa7c25ade53"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-client/zipball/21c4372e9cd2305313f4d4792d7b9fa7c25ade53",
"reference": "21c4372e9cd2305313f4d4792d7b9fa7c25ade53",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"psr/log": "^1.0",
"symfony/http-client-contracts": "^2.1.1",
"symfony/polyfill-php73": "^1.11",
"symfony/polyfill-php80": "^1.15",
"symfony/service-contracts": "^1.0|^2"
},
"provide": {
"php-http/async-client-implementation": "*",
"php-http/client-implementation": "*",
"psr/http-client-implementation": "1.0",
"symfony/http-client-implementation": "1.1"
},
"require-dev": {
"amphp/http-client": "^4.2.1",
"amphp/http-tunnel": "^1.0",
"amphp/socket": "^1.1",
"guzzlehttp/promises": "^1.3.1",
"nyholm/psr7": "^1.0",
"php-http/httplug": "^1.0|^2.0",
"psr/http-client": "^1.0",
"symfony/dependency-injection": "^4.4|^5.0",
"symfony/http-kernel": "^4.4.13|^5.1.5",
"symfony/process": "^4.4|^5.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.1-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\HttpClient\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony HttpClient component",
"homepage": "https://symfony.com",
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-09-02T08:02:12+00:00"
},
{
"name": "symfony/http-client-contracts",
"version": "v2.2.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-client-contracts.git",
"reference": "3a5d0fe7908daaa23e3dbf4cee3ba4bfbb19fdd3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/3a5d0fe7908daaa23e3dbf4cee3ba4bfbb19fdd3",
"reference": "3a5d0fe7908daaa23e3dbf4cee3ba4bfbb19fdd3",
"shasum": ""
},
"require": {
"php": ">=7.2.5"
},
"suggest": {
"symfony/http-client-implementation": ""
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.2-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
"psr-4": {
"Symfony\\Contracts\\HttpClient\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Generic abstractions related to HTTP clients",
"homepage": "https://symfony.com",
"keywords": [
"abstractions",
"contracts",
"decoupling",
"interfaces",
"interoperability",
"standards"
],
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-09-07T11:33:47+00:00"
},
{ {
"name": "symfony/http-foundation", "name": "symfony/http-foundation",
"version": "v5.1.5", "version": "v5.1.5",
@ -9561,16 +9743,16 @@
}, },
{ {
"name": "facade/flare-client-php", "name": "facade/flare-client-php",
"version": "1.3.5", "version": "1.3.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/facade/flare-client-php.git", "url": "https://github.com/facade/flare-client-php.git",
"reference": "25907a113bfc212a38d458ae365bfb902b4e7fb8" "reference": "451fadf38e9f635e7f8e1f5b3cf5c9eb82f11799"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/facade/flare-client-php/zipball/25907a113bfc212a38d458ae365bfb902b4e7fb8", "url": "https://api.github.com/repos/facade/flare-client-php/zipball/451fadf38e9f635e7f8e1f5b3cf5c9eb82f11799",
"reference": "25907a113bfc212a38d458ae365bfb902b4e7fb8", "reference": "451fadf38e9f635e7f8e1f5b3cf5c9eb82f11799",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -9583,7 +9765,6 @@
}, },
"require-dev": { "require-dev": {
"friendsofphp/php-cs-fixer": "^2.14", "friendsofphp/php-cs-fixer": "^2.14",
"larapack/dd": "^1.1",
"phpunit/phpunit": "^7.5.16", "phpunit/phpunit": "^7.5.16",
"spatie/phpunit-snapshot-assertions": "^2.0" "spatie/phpunit-snapshot-assertions": "^2.0"
}, },
@ -9619,7 +9800,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2020-08-26T18:06:23+00:00" "time": "2020-09-18T06:35:11+00:00"
}, },
{ {
"name": "facade/ignition", "name": "facade/ignition",
@ -10270,16 +10451,16 @@
}, },
{ {
"name": "phpdocumentor/reflection-docblock", "name": "phpdocumentor/reflection-docblock",
"version": "5.2.1", "version": "5.2.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "d870572532cd70bc3fab58f2e23ad423c8404c44" "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d870572532cd70bc3fab58f2e23ad423c8404c44", "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/069a785b2141f5bcf49f3e353548dc1cce6df556",
"reference": "d870572532cd70bc3fab58f2e23ad423c8404c44", "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -10318,20 +10499,20 @@
} }
], ],
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
"time": "2020-08-15T11:14:08+00:00" "time": "2020-09-03T19:13:55+00:00"
}, },
{ {
"name": "phpdocumentor/type-resolver", "name": "phpdocumentor/type-resolver",
"version": "1.3.0", "version": "1.4.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpDocumentor/TypeResolver.git", "url": "https://github.com/phpDocumentor/TypeResolver.git",
"reference": "e878a14a65245fbe78f8080eba03b47c3b705651" "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/e878a14a65245fbe78f8080eba03b47c3b705651", "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0",
"reference": "e878a14a65245fbe78f8080eba03b47c3b705651", "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -10363,7 +10544,7 @@
} }
], ],
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
"time": "2020-06-27T10:12:23+00:00" "time": "2020-09-17T18:55:26+00:00"
}, },
{ {
"name": "phpspec/prophecy", "name": "phpspec/prophecy",
@ -11466,16 +11647,16 @@
}, },
{ {
"name": "swagger-api/swagger-ui", "name": "swagger-api/swagger-ui",
"version": "v3.33.0", "version": "v3.34.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/swagger-api/swagger-ui.git", "url": "git@github.com:swagger-api/swagger-ui.git",
"reference": "829d87530030bb5bfa24a5093d098c672adfbb9b" "reference": "c20a8c479eaa7897a2ddabcaf5f75e6d41f4525c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/swagger-api/swagger-ui/zipball/829d87530030bb5bfa24a5093d098c672adfbb9b", "url": "https://api.github.com/repos/swagger-api/swagger-ui/zipball/c20a8c479eaa7897a2ddabcaf5f75e6d41f4525c",
"reference": "829d87530030bb5bfa24a5093d098c672adfbb9b", "reference": "c20a8c479eaa7897a2ddabcaf5f75e6d41f4525c",
"shasum": "" "shasum": ""
}, },
"type": "library", "type": "library",
@ -11519,7 +11700,7 @@
"swagger", "swagger",
"ui" "ui"
], ],
"time": "2020-09-10T23:20:14+00:00" "time": "2020-09-18T18:46:18+00:00"
}, },
{ {
"name": "symfony/debug", "name": "symfony/debug",

View File

@ -12,8 +12,8 @@ return [
'require_https' => env('REQUIRE_HTTPS', true), 'require_https' => env('REQUIRE_HTTPS', true),
'app_url' => rtrim(env('APP_URL', ''), '/').'/', 'app_url' => rtrim(env('APP_URL', ''), '/').'/',
'app_domain' => env('APP_DOMAIN', ''), 'app_domain' => env('APP_DOMAIN', ''),
'app_version' => '5.0.13', 'app_version' => '5.0.17',
'minimum_client_version' => '5.0.13', 'minimum_client_version' => '5.0.16',
'terms_version' => '1.0.1', 'terms_version' => '1.0.1',
'api_secret' => env('API_SECRET', ''), 'api_secret' => env('API_SECRET', ''),
'google_maps_api_key' => env('GOOGLE_MAPS_API_KEY'), 'google_maps_api_key' => env('GOOGLE_MAPS_API_KEY'),

View File

@ -84,9 +84,9 @@ class AddIsPublicToDocumentsTable extends Migration
$t->unsignedInteger('recurring_invoice_id')->index(); $t->unsignedInteger('recurring_invoice_id')->index();
$t->string('key')->index(); $t->string('key')->index();
$t->foreign('recurring_invoice_id')->references('id')->on('recurring_invoices')->onDelete('cascade')->onUpdate('cascade');
$t->foreign('user_id')->references('id')->on('users')->onDelete('cascade')->onUpdate('cascade'); $t->foreign('user_id')->references('id')->on('users')->onDelete('cascade')->onUpdate('cascade');
$t->foreign('client_contact_id')->references('id')->on('client_contacts')->onDelete('cascade')->onUpdate('cascade'); $t->foreign('client_contact_id')->references('id')->on('client_contacts')->onDelete('cascade')->onUpdate('cascade');
$t->foreign('recurring_invoice_id')->references('id')->on('recurring_invoices')->onDelete('cascade')->onUpdate('cascade');
$t->foreign('company_id')->references('id')->on('companies')->onDelete('cascade')->onUpdate('cascade'); $t->foreign('company_id')->references('id')->on('companies')->onDelete('cascade')->onUpdate('cascade');
$t->timestamps(6); $t->timestamps(6);
@ -104,5 +104,7 @@ class AddIsPublicToDocumentsTable extends Migration
*/ */
public function down() public function down()
{ {
} }
} }

View File

@ -0,0 +1,45 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class IdNumberFieldsForMissingEntities extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('expenses', function (Blueprint $table) {
$table->string('number')->nullable();
});
Schema::table('tasks', function (Blueprint $table) {
$table->string('number')->nullable();
});
Schema::table('vendors', function (Blueprint $table) {
$table->text('vendor_hash')->nullable();
$table->text('public_notes')->nullable();
});
Schema::table('vendor_contacts', function (Blueprint $table) {
$table->boolean('send_email')->default(0);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}

View File

@ -4611,6 +4611,32 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
cached_network_image
The MIT License (MIT)
Copyright (c) 2018 Rene Floor
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
charcode charcode
dart_style dart_style
@ -5582,7 +5608,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
device_info device_info
device_info_platform_interface
google_sign_in_platform_interface google_sign_in_platform_interface
image_picker_platform_interface image_picker_platform_interface
local_auth local_auth
@ -5617,6 +5642,36 @@ url_launcher_platform_interface
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
device_info_platform_interface
url_launcher
Copyright 2017 The Chromium Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
double-conversion double-conversion
icu icu
@ -5967,7 +6022,6 @@ firebase_core
firebase_core_platform_interface firebase_core_platform_interface
shared_preferences shared_preferences
shared_preferences_platform_interface shared_preferences_platform_interface
url_launcher
// Copyright 2017 The Chromium Authors. All rights reserved. // Copyright 2017 The Chromium Authors. All rights reserved.
// //
@ -5998,10 +6052,8 @@ url_launcher
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
firebase_core_web firebase_core_web
flutter_plugin_android_lifecycle
shared_preferences_web shared_preferences_web
url_launcher_macos url_launcher_macos
url_launcher_web
// Copyright 2019 The Chromium Authors. All rights reserved. // Copyright 2019 The Chromium Authors. All rights reserved.
// //
@ -6060,6 +6112,56 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
flutter_blurhash
MIT License
Copyright (c) 2019 Robert Felker
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--------------------------------------------------------------------------------
flutter_cache_manager
The MIT License (MIT)
Copyright (c) 2017 Rene Floor
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
flutter_colorpicker flutter_colorpicker
@ -6302,6 +6404,37 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
--------------------------------------------------------------------------------
flutter_plugin_android_lifecycle
url_launcher_web
url_launcher_windows
Copyright 2019 The Chromium Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
flutter_redux flutter_redux
@ -7784,7 +7917,6 @@ freely, subject to the following restrictions:
distribution. distribution.
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
google_sign_in google_sign_in
google_sign_in_web
Copyright 2016, the Flutter project authors. All rights reserved. Copyright 2016, the Flutter project authors. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@ -7813,6 +7945,35 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
google_sign_in_web
Copyright 2016, the Flutter project authors. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
harfbuzz harfbuzz
@ -10960,35 +11121,32 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
in_app_purchase in_app_purchase
webview_flutter
// Copyright 2018 The Chromium Authors. All rights reserved. Copyright 2018 The Chromium Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without modification,
// modification, are permitted provided that the following conditions are are permitted provided that the following conditions are met:
// met:
// * Redistributions of source code must retain the above copyright
// * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
// notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above
// * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
// copyright notice, this list of conditions and the following disclaimer disclaimer in the documentation and/or other materials provided
// in the documentation and/or other materials provided with the with the distribution.
// distribution. * Neither the name of Google Inc. nor the names of its
// * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived
// contributors may be used to endorse or promote products derived from from this software without specific prior written permission.
// this software without specific prior written permission.
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
js js
@ -12792,6 +12950,31 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
octo_image
MIT License
Copyright (c) 2020 Baseflow
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
path_provider_linux path_provider_linux
@ -15974,6 +16157,37 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
webview_flutter
// Copyright 2018 The Chromium Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
wuffs wuffs

BIN
public/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 917 B

View File

@ -3,32 +3,35 @@ const MANIFEST = 'flutter-app-manifest';
const TEMP = 'flutter-temp-cache'; const TEMP = 'flutter-temp-cache';
const CACHE_NAME = 'flutter-app-cache'; const CACHE_NAME = 'flutter-app-cache';
const RESOURCES = { const RESOURCES = {
"assets/assets/images/logo.png": "090f69e23311a4b6d851b3880ae52541", "main.dart.js": "e887dbd02dff5dde4421ce0395612e94",
"assets/assets/images/payment_types/mastercard.png": "6f6cdc29ee2e22e06b1ac029cb52ef71", "assets/NOTICES": "cc579c7545b2b2a03247838dd1d601d7",
"assets/assets/images/payment_types/laser.png": "b4e6e93dd35517ac429301119ff05868",
"assets/assets/images/payment_types/jcb.png": "07e0942d16c5592118b72e74f2f7198c",
"assets/assets/images/payment_types/amex.png": "c49a4247984b3732a4af50a3390aa978",
"assets/assets/images/payment_types/paypal.png": "8e06c094c1871376dfea1da8088c29d1",
"assets/assets/images/payment_types/dinerscard.png": "06d85186ba858c18ab7c9caa42c92024",
"assets/assets/images/payment_types/ach.png": "7433f0aff779dc98a649b7a2daf777cf",
"assets/assets/images/payment_types/switch.png": "4fa11c45327f5fdc20205821b2cfd9cc",
"assets/assets/images/payment_types/discover.png": "6c0a386a00307f87db7bea366cca35f5",
"assets/assets/images/payment_types/maestro.png": "e533b92bfb50339fdbfa79e3dfe81f08",
"assets/assets/images/payment_types/carteblanche.png": "d936e11fa3884b8c9f1bd5c914be8629",
"assets/assets/images/payment_types/solo.png": "2030c3ccaccf5d5e87916a62f5b084d6",
"assets/assets/images/payment_types/unionpay.png": "7002f52004e0ab8cc0b7450b0208ccb2",
"assets/assets/images/payment_types/other.png": "d936e11fa3884b8c9f1bd5c914be8629",
"assets/assets/images/payment_types/visa.png": "3ddc4a4d25c946e8ad7e6998f30fd4e3",
"assets/assets/images/google-icon.png": "0f118259ce403274f407f5e982e681c3",
"assets/NOTICES": "9eef57a7772ab70663faf36b6e8eafce",
"assets/AssetManifest.json": "ea09ed4b9b8b6c83d6896248aac7c527",
"assets/packages/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf": "b0fd91bb29dcb296a9a37f8bda0a2d85",
"assets/FontManifest.json": "cf3c681641169319e61b61bd0277378f", "assets/FontManifest.json": "cf3c681641169319e61b61bd0277378f",
"assets/packages/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf": "b0fd91bb29dcb296a9a37f8bda0a2d85",
"assets/fonts/MaterialIcons-Regular.otf": "a68d2a28c526b3b070aefca4bac93d25", "assets/fonts/MaterialIcons-Regular.otf": "a68d2a28c526b3b070aefca4bac93d25",
"favicon.ico": "51636d3a390451561744c42188ccd628", "assets/assets/images/google-icon.png": "0f118259ce403274f407f5e982e681c3",
"main.dart.js": "152fc42b888e5c0cbd1fbcf6db4c6542", "assets/assets/images/payment_types/other.png": "d936e11fa3884b8c9f1bd5c914be8629",
"assets/assets/images/payment_types/laser.png": "b4e6e93dd35517ac429301119ff05868",
"assets/assets/images/payment_types/ach.png": "7433f0aff779dc98a649b7a2daf777cf",
"assets/assets/images/payment_types/paypal.png": "8e06c094c1871376dfea1da8088c29d1",
"assets/assets/images/payment_types/visa.png": "3ddc4a4d25c946e8ad7e6998f30fd4e3",
"assets/assets/images/payment_types/switch.png": "4fa11c45327f5fdc20205821b2cfd9cc",
"assets/assets/images/payment_types/unionpay.png": "7002f52004e0ab8cc0b7450b0208ccb2",
"assets/assets/images/payment_types/discover.png": "6c0a386a00307f87db7bea366cca35f5",
"assets/assets/images/payment_types/jcb.png": "07e0942d16c5592118b72e74f2f7198c",
"assets/assets/images/payment_types/solo.png": "2030c3ccaccf5d5e87916a62f5b084d6",
"assets/assets/images/payment_types/carteblanche.png": "d936e11fa3884b8c9f1bd5c914be8629",
"assets/assets/images/payment_types/mastercard.png": "6f6cdc29ee2e22e06b1ac029cb52ef71",
"assets/assets/images/payment_types/amex.png": "c49a4247984b3732a4af50a3390aa978",
"assets/assets/images/payment_types/maestro.png": "e533b92bfb50339fdbfa79e3dfe81f08",
"assets/assets/images/payment_types/dinerscard.png": "06d85186ba858c18ab7c9caa42c92024",
"assets/assets/images/logo.png": "090f69e23311a4b6d851b3880ae52541",
"assets/AssetManifest.json": "ea09ed4b9b8b6c83d6896248aac7c527",
"favicon.png": "5dcef449791fa27946b3d35ad8803796",
"/": "e65799be52f7bbcaf39d78046726b95a", "/": "e65799be52f7bbcaf39d78046726b95a",
"manifest.json": "77215c1737c7639764e64a192be2f7b8" "favicon.ico": "51636d3a390451561744c42188ccd628",
"manifest.json": "77215c1737c7639764e64a192be2f7b8",
"icons/Icon-512.png": "96e752610906ba2a93c65f8abe1645f1",
"icons/Icon-192.png": "ac9a721a12bbc803b44f645561ecb1e1"
}; };
// The application shell files that are downloaded before a service worker can // The application shell files that are downloaded before a service worker can
@ -39,7 +42,6 @@ const CORE = [
"assets/NOTICES", "assets/NOTICES",
"assets/AssetManifest.json", "assets/AssetManifest.json",
"assets/FontManifest.json"]; "assets/FontManifest.json"];
// During install, the TEMP cache is populated with the application shell files. // During install, the TEMP cache is populated with the application shell files.
self.addEventListener("install", (event) => { self.addEventListener("install", (event) => {
return event.waitUntil( return event.waitUntil(
@ -60,7 +62,6 @@ self.addEventListener("activate", function(event) {
var tempCache = await caches.open(TEMP); var tempCache = await caches.open(TEMP);
var manifestCache = await caches.open(MANIFEST); var manifestCache = await caches.open(MANIFEST);
var manifest = await manifestCache.match('manifest'); var manifest = await manifestCache.match('manifest');
// When there is no prior manifest, clear the entire cache. // When there is no prior manifest, clear the entire cache.
if (!manifest) { if (!manifest) {
await caches.delete(CACHE_NAME); await caches.delete(CACHE_NAME);
@ -74,7 +75,6 @@ self.addEventListener("activate", function(event) {
await manifestCache.put('manifest', new Response(JSON.stringify(RESOURCES))); await manifestCache.put('manifest', new Response(JSON.stringify(RESOURCES)));
return; return;
} }
var oldManifest = await manifest.json(); var oldManifest = await manifest.json();
var origin = self.location.origin; var origin = self.location.origin;
for (var request of await contentCache.keys()) { for (var request of await contentCache.keys()) {
@ -114,21 +114,25 @@ self.addEventListener("activate", function(event) {
self.addEventListener("fetch", (event) => { self.addEventListener("fetch", (event) => {
var origin = self.location.origin; var origin = self.location.origin;
var key = event.request.url.substring(origin.length + 1); var key = event.request.url.substring(origin.length + 1);
if (event.request.url == origin || event.request.url.startsWith(origin + '/#')) { if (key.indexOf('?v=') != -1) {
key = key.split('?v=')[0];
}
if (event.request.url == origin || event.request.url.startsWith(origin + '/#') || key == '') {
key = '/'; key = '/';
} }
// If the URL is not the RESOURCE list, skip the cache. // If the URL is not the RESOURCE list, skip the cache.
if (!RESOURCES[key]) { if (!RESOURCES[key]) {
return event.respondWith(fetch(event.request)); return event.respondWith(fetch(event.request));
} }
if (key == '/') {
return onlineFirst(event);
}
event.respondWith(caches.open(CACHE_NAME) event.respondWith(caches.open(CACHE_NAME)
.then((cache) => { .then((cache) => {
return cache.match(event.request).then((response) => { return cache.match(event.request).then((response) => {
// Either respond with the cached resource, or perform a fetch and // Either respond with the cached resource, or perform a fetch and
// lazily populate the cache. Ensure the resources are not cached // lazily populate the cache.
// by the browser for longer than the service worker expects. return response || fetch(event.request).then((response) => {
var modifiedRequest = new Request(event.request, {'cache': 'reload'});
return response || fetch(modifiedRequest).then((response) => {
cache.put(event.request, response.clone()); cache.put(event.request, response.clone());
return response; return response;
}); });
@ -143,7 +147,6 @@ self.addEventListener('message', (event) => {
if (event.data === 'skipWaiting') { if (event.data === 'skipWaiting') {
return self.skipWaiting(); return self.skipWaiting();
} }
if (event.message === 'downloadOffline') { if (event.message === 'downloadOffline') {
downloadOffline(); downloadOffline();
} }
@ -169,3 +172,25 @@ async function downloadOffline() {
} }
return contentCache.addAll(resources); return contentCache.addAll(resources);
} }
// Attempt to download the resource online before falling back to
// the offline cache.
function onlineFirst(event) {
return event.respondWith(
fetch(event.request).then((response) => {
return caches.open(CACHE_NAME).then((cache) => {
cache.put(event.request, response.clone());
return response;
});
}).catch((error) => {
return caches.open(CACHE_NAME).then((cache) => {
return cache.match(event.request).then((response) => {
if (response != null) {
return response;
}
throw error;
});
});
})
);
}

BIN
public/icons/Icon-192.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

BIN
public/icons/Icon-512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

@ -1,2 +1,2 @@
/*! For license information please see checkout.com.js.LICENSE.txt */ /*! For license information please see checkout.com.js.LICENSE.txt */
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=9)}({9:function(e,t,n){e.exports=n("XYrq")},XYrq:function(e,t){window.CKOConfig={publicKey:document.querySelector('meta[name="public-key"]').content,customerEmail:document.querySelector('meta[name="customer-email"]').content,value:document.querySelector('meta[name="value"]').content,currency:document.querySelector('meta[name="currency"]').content,paymentMode:"cards",cardFormMode:"cardTokenisation",cardTokenised:function(e){document.querySelector('input[name="gateway_response"]').value=JSON.stringify(e.data),document.querySelector('input[name="store_card"]').value=document.getElementById("store-card-checkbox").checked?1:0,document.getElementById("server-response").submit()}}}}); !function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/",n(n.s=9)}({9:function(e,t,n){e.exports=n("XYrq")},XYrq:function(e,t){window.CKOConfig={publicKey:document.querySelector('meta[name="public-key"]').content,customerEmail:document.querySelector('meta[name="customer-email"]').content,value:document.querySelector('meta[name="value"]').content,currency:document.querySelector('meta[name="currency"]').content,paymentMode:"cards",cardFormMode:"cardTokenisation",cardTokenised:function(e){document.querySelector('input[name="gateway_response"]').value=JSON.stringify(e.data),document.querySelector('input[name="store_card"]').value=document.querySelector("input[name=token-billing-checkbox]:checked").value,document.getElementById("server-response").submit()}}}});

229694
public/main.dart.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -9,7 +9,7 @@
"/js/clients/payments/alipay.js": "/js/clients/payments/alipay.js?id=766690d4207c0d8e75d1", "/js/clients/payments/alipay.js": "/js/clients/payments/alipay.js?id=766690d4207c0d8e75d1",
"/js/clients/payments/authorize-credit-card-payment.js": "/js/clients/payments/authorize-credit-card-payment.js?id=914bbac0c52e458a55ea", "/js/clients/payments/authorize-credit-card-payment.js": "/js/clients/payments/authorize-credit-card-payment.js?id=914bbac0c52e458a55ea",
"/js/clients/payments/card-js.min.js": "/js/clients/payments/card-js.min.js?id=7200ac43b87bddf1bedc", "/js/clients/payments/card-js.min.js": "/js/clients/payments/card-js.min.js?id=7200ac43b87bddf1bedc",
"/js/clients/payments/checkout.com.js": "/js/clients/payments/checkout.com.js?id=42d239882b80af83ad22", "/js/clients/payments/checkout.com.js": "/js/clients/payments/checkout.com.js?id=bee8407bd5dfae80dc6a",
"/js/clients/payments/process.js": "/js/clients/payments/process.js?id=8f0a87e44b6e6824c010", "/js/clients/payments/process.js": "/js/clients/payments/process.js?id=8f0a87e44b6e6824c010",
"/js/clients/payments/sofort.js": "/js/clients/payments/sofort.js?id=ca99b358b094202d1e3a", "/js/clients/payments/sofort.js": "/js/clients/payments/sofort.js?id=ca99b358b094202d1e3a",
"/js/clients/quotes/action-selectors.js": "/js/clients/quotes/action-selectors.js?id=1702ddb9f59521c7758f", "/js/clients/quotes/action-selectors.js": "/js/clients/quotes/action-selectors.js?id=1702ddb9f59521c7758f",

View File

@ -66,11 +66,6 @@ class AuthorizeAuthorizeCard {
} }
handle() { handle() {
//this.handleFormValidation();
// At this point as an small API you can request this.form.valid to check if input elements are valid.
// Note: this.form.valid will not handle empty fields.
this.cardButton.addEventListener("click", () => { this.cardButton.addEventListener("click", () => {
this.cardButton.disabled = !this.cardButton.disabled; this.cardButton.disabled = !this.cardButton.disabled;
this.handleAuthorization(); this.handleAuthorization();

View File

@ -23,7 +23,7 @@ window.CKOConfig = {
document.querySelector( document.querySelector(
'input[name="store_card"]' 'input[name="store_card"]'
).value = document.getElementById('store-card-checkbox').checked ? 1 : 0; ).value = document.querySelector('input[name=token-billing-checkbox]:checked').value;
document.getElementById('server-response').submit(); document.getElementById('server-response').submit();
}, },

View File

@ -3272,4 +3272,5 @@ return [
'password_strength' => 'Password strength too weak', 'password_strength' => 'Password strength too weak',
'thanks' => 'Thanks', 'thanks' => 'Thanks',
'paused' => 'Paused',
]; ];

View File

@ -1,4 +1,4 @@
@component('email.template.master', ['design' => 'light']) @component('email.template.master', ['design' => 'light', 'settings' =>$settings])
@slot('header') @slot('header')
@component('email.components.header', ['p' => '', 'logo' => $url]) @component('email.components.header', ['p' => '', 'logo' => $url])

View File

@ -1,4 +1,4 @@
@component('email.template.master', ['design' => 'light']) @component('email.template.master', ['design' => 'light', 'settings' =>$settings])
@slot('header') @slot('header')
@component('email.components.header', ['p' => $title, 'logo' => $logo]) @component('email.components.header', ['p' => $title, 'logo' => $logo])

View File

@ -1,4 +1,4 @@
@component('email.template.master', ['design' => 'light']) @component('email.template.master', ['design' => 'light', 'settings' =>$settings])
@slot('header') @slot('header')
@component('email.components.header', ['p' => $title, 'logo' => $logo]) @component('email.components.header', ['p' => $title, 'logo' => $logo])

View File

@ -1,4 +1,4 @@
@component('email.template.master', ['design' => 'light']) @component('email.template.master', ['design' => 'light', 'settings' =>$settings])
@slot('header') @slot('header')
@component('email.components.header', ['p' => 'Payment for your invoice has been completed!', 'logo' => 'https://www.invoiceninja.com/wp-content/uploads/2019/01/InvoiceNinja-Logo-Round-300x300.png']) @component('email.components.header', ['p' => 'Payment for your invoice has been completed!', 'logo' => 'https://www.invoiceninja.com/wp-content/uploads/2019/01/InvoiceNinja-Logo-Round-300x300.png'])

View File

@ -1,4 +1,4 @@
@component('email.template.master', ['design' => 'light']) @component('email.template.master', ['design' => 'light', 'settings' =>$settings])
@slot('header') @slot('header')
@component('email.components.header') @component('email.components.header')

View File

@ -1,4 +1,4 @@
@component('email.template.master', ['design' => 'light']) @component('email.template.master', ['design' => 'light', 'settings' =>$settings])
@slot('header') @slot('header')
@component('email.components.header') @component('email.components.header')

View File

@ -1,4 +1,4 @@
@component('email.template.master', ['design' => 'light']) @component('email.template.master', ['design' => 'light', 'settings' =>$settings])
@slot('header') @slot('header')
@component('email.components.header', ['p' => 'Your quote was approved!', 'logo' => 'https://www.invoiceninja.com/wp-content/uploads/2019/01/InvoiceNinja-Logo-Round-300x300.png']) @component('email.components.header', ['p' => 'Your quote was approved!', 'logo' => 'https://www.invoiceninja.com/wp-content/uploads/2019/01/InvoiceNinja-Logo-Round-300x300.png'])

View File

@ -1,4 +1,4 @@
@component('email.template.master', ['design' => 'dark']) @component('email.template.master', ['design' => 'dark', 'settings' => $settings])
@slot('header') @slot('header')
@component('email.components.header', ['p' => $body, 'logo' => 'https://www.invoiceninja.com/wp-content/uploads/2019/01/InvoiceNinja-Logo-Round-300x300.png']) @component('email.components.header', ['p' => $body, 'logo' => 'https://www.invoiceninja.com/wp-content/uploads/2019/01/InvoiceNinja-Logo-Round-300x300.png'])

View File

@ -1,10 +1,10 @@
@component('email.template.master', ['design' => 'light']) @component('email.template.master', ['design' => 'light', 'settings' => $settings])
@slot('header') @slot('header')
@component('email.components.header', ['p' => $body, 'logo' => 'https://www.invoiceninja.com/wp-content/uploads/2019/01/InvoiceNinja-Logo-Round-300x300.png']) @component('email.components.header', ['p' => $body, 'logo' => 'https://www.invoiceninja.com/wp-content/uploads/2019/01/InvoiceNinja-Logo-Round-300x300.png'])
@if(isset($title)) @if(isset($title))
{{$title}} {{$title}}
@endif @endif
@endcomponent @endcomponent

View File

@ -1,5 +1,5 @@
@php @php
if(!isset($design)) $design = 'light'; if(!isset($design)) $design = 'light';
@endphp @endphp
<!DOCTYPE html> <!DOCTYPE html>
@ -11,36 +11,46 @@
<title>@yield('title')</title> <title>@yield('title')</title>
</head> </head>
@if($design == 'dark') <style>
<style> :root {
* { --primary-color: {{ $settings->primary_color }};
color: #cbd5e0 !important; }
}
</style> .border-primary {
@endif border-color: var(--primary-color);
}
</style>
@if($design == 'dark')
<style>
* {
color: #cbd5e0 !important;
}
</style>
@endif
<body class="{{ $design == 'light' ? 'bg-gray-200' : 'bg-gray-800' }} my-10 font-sans {{ $design == 'light' ? 'text-gray-700' : 'text-gray-400' }}"> <body class="{{ $design == 'light' ? 'bg-gray-200' : 'bg-gray-800' }} my-10 font-sans {{ $design == 'light' ? 'text-gray-700' : 'text-gray-400' }}">
<div class="grid grid-cols-6"> <div class="grid grid-cols-6">
<div class="col-start-2 col-span-4"> <div class="col-span-4 col-start-2">
<div class="{{ $design == 'light' ? 'bg-white' : 'bg-gray-900' }} shadow border-t-2 {{ $design == 'light' ? 'border-green-500' : 'border-gray-800' }}"> <div class="{{ $design == 'light' ? 'bg-white' : 'bg-gray-900' }} shadow border-t-2 {{ $design == 'light' ? 'border-primary' : 'border-gray-800' }}">
<div class="px-10"> <div class="px-10">
{{ $header }} {{ $header }}
</div> </div>
<div id="text" class="px-10 py-6 flex flex-col"> <div id="text" class="flex flex-col px-10 py-6">
@isset($greeting) @isset($greeting)
{{ $greeting }} {{ $greeting }}
@endisset @endisset
{{ $slot }} {{ $slot }}
@isset($signature) @isset($signature)
{{ $signature }} {{ $signature }}
@endisset @endisset
</div> </div>
</div> </div>
@isset($below_card) @isset($below_card)
<div id="bottomText" class="text-center my-4 px-10"> <div id="bottomText" class="px-10 my-4 text-center">
{{ $below_card }} {{ $below_card }}
</div> </div>
@endisset @endisset

View File

@ -86,7 +86,7 @@
{!! App\Models\Invoice::badgeForStatus($invoice->status) !!} {!! App\Models\Invoice::badgeForStatus($invoice->status) !!}
</td> </td>
<td class="flex items-center justify-end px-6 py-4 text-sm font-medium leading-5 whitespace-no-wrap"> <td class="flex items-center justify-end px-6 py-4 text-sm font-medium leading-5 whitespace-no-wrap">
@if($invoice->isPayable()) @if($invoice->isPayable() && $invoice->balance > 0)
<form action="{{ route('client.invoices.bulk') }}" method="post"> <form action="{{ route('client.invoices.bulk') }}" method="post">
@csrf @csrf
<input type="hidden" name="invoices[]" value="{{ $invoice->hashed_id }}"> <input type="hidden" name="invoices[]" value="{{ $invoice->hashed_id }}">

View File

@ -58,14 +58,32 @@
</div> </div>
@include('portal.ninja2020.gateways.authorize.credit_card') @include('portal.ninja2020.gateways.authorize.credit_card')
<div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6"> <div class="{{ ($gateway->token_billing == 'optin' || $gateway->token_billing == 'optout') ? 'sm:grid' : 'hidden' }} bg-gray-50 px-4 py-5 sm:grid-cols-3 sm:gap-4 sm:px-6">
<dt class="text-sm leading-5 font-medium text-gray-500"> <dt class="text-sm leading-5 font-medium text-gray-500">
{{ ctrans('texts.token_billing_checkbox') }} {{ ctrans('texts.token_billing_checkbox') }}
</dt> </dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2"> <dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
<input type="checkbox" class="form-checkbox" name="store_card_checkbox" <label class="mr-4">
id="store_card_checkbox"/> <input
type="radio"
class="form-radio cursor-pointer"
name="store_card_checkbox"
id="proxy_is_default"
value="true"
{{ ($gateway->token_billing == 'always' || $gateway->token_billing == 'optout') ? 'checked' : '' }} />
<span class="ml-1 cursor-pointer">{{ ctrans('texts.yes') }}</span>
</label>
<label>
<input
type="radio"
class="form-radio cursor-pointer"
name="store_card_checkbox"
id="proxy_is_default"
value="false"
{{ ($gateway->token_billing == 'off' || $gateway->token_billing == 'optin') ? 'checked' : '' }} />
<span class="ml-1 cursor-pointer">{{ ctrans('texts.no') }}</span>
</label>
</dd> </dd>
</div> </div>
<div class="bg-white px-4 py-5 flex justify-end"> <div class="bg-white px-4 py-5 flex justify-end">

View File

@ -84,12 +84,31 @@
</button> </button>
</div> </div>
@else @else
<div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 flex items-center"> <div class="{{ ($gateway->company_gateway->token_billing == 'optin' || $gateway->company_gateway->token_billing == 'optout') ? 'sm:grid' : 'hidden' }} bg-gray-50 px-4 py-5 sm:grid-cols-3 sm:gap-4 sm:px-6">
<dt class="text-sm leading-5 font-medium text-gray-500 mr-4"> <dt class="text-sm leading-5 font-medium text-gray-500">
{{ ctrans('texts.token_billing_checkbox') }} {{ ctrans('texts.token_billing_checkbox') }}
</dt> </dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2"> <dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
<input type="checkbox" id="store-card-checkbox" class="form-checkbox"> <label class="mr-4">
<input
type="radio"
class="form-radio cursor-pointer"
name="token-billing-checkbox"
id="proxy_is_default"
value="true"
{{ ($gateway->company_gateway->token_billing == 'always' || $gateway->company_gateway->token_billing == 'optout') ? 'checked' : '' }} />
<span class="ml-1 cursor-pointer">{{ ctrans('texts.yes') }}</span>
</label>
<label>
<input
type="radio"
class="form-radio cursor-pointer"
name="token-billing-checkbox"
id="proxy_is_default"
value="false"
{{ ($gateway->company_gateway->token_billing == 'off' || $gateway->company_gateway->token_billing == 'optin') ? 'checked' : '' }} />
<span class="ml-1 cursor-pointer">{{ ctrans('texts.no') }}</span>
</label>
</dd> </dd>
</div> </div>
<div class="bg-white px-4 py-5 flex justify-end"> <div class="bg-white px-4 py-5 flex justify-end">

Some files were not shown because too many files have changed in this diff Show More