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

Merge remote-tracking branch 'upstream/v2' into v2-1006-checkout-com

This commit is contained in:
Benjamin Beganović 2020-06-15 14:26:59 +02:00
commit 72cd7ca91a
41 changed files with 97926 additions and 97208 deletions

View File

@ -43,6 +43,7 @@ MAIL_FROM_ADDRESS='user@example.com'
MAIL_FROM_NAME='Self Hosted User'
POSTMARK_API_TOKEN=
REQUIRE_HTTPS=true
GOOGLE_MAPS_API_KEY=
API_SECRET=superdoopersecrethere

View File

@ -49,8 +49,6 @@ class Kernel extends ConsoleKernel
$schedule->job(new UpdateExchangeRates)->daily();
$schedule->job(new CheckDbStatus())->everyFiveMinutes();
/* Run hosted specific jobs */
if(Ninja::isHosted()) {
$schedule->job(new AdjustEmailQuota())->daily();

View File

@ -33,7 +33,7 @@ class CompanySettings extends BaseSettings
public $enable_client_portal_dashboard = true; //implemented
public $signature_on_pdf = false;
public $document_email_attachment = false;
public $send_portal_password = false;
//public $send_portal_password = false;
public $portal_design_id = '1';
@ -113,7 +113,7 @@ class CompanySettings extends BaseSettings
public $invoice_terms = '';
public $quote_terms = '';
public $invoice_taxes = 0;
public $enabled_item_tax_rates = 0;
// public $enabled_item_tax_rates = 0;
public $invoice_design_id = 'VolejRejNm';
public $quote_design_id = 'VolejRejNm';
public $credit_design_id = 'VolejRejNm';
@ -274,7 +274,7 @@ class CompanySettings extends BaseSettings
'email_template_statement' => 'string',
'email_subject_statement' => 'string',
'signature_on_pdf' => 'bool',
'send_portal_password' => 'bool',
// 'send_portal_password' => 'bool',
'quote_footer' => 'string',
'page_size' => 'string',
'font_size' => 'int',
@ -344,7 +344,7 @@ class CompanySettings extends BaseSettings
'invoice_design_id' => 'string',
'invoice_fields' => 'string',
'invoice_taxes' => 'int',
'enabled_item_tax_rates' => 'int',
//'enabled_item_tax_rates' => 'int',
'invoice_footer' => 'string',
'invoice_labels' => 'string',
'invoice_terms' => 'string',

View File

@ -33,7 +33,7 @@ class FreeCompanySettings extends BaseSettings
public $custom_value3 = '';
public $custom_value4 = '';
public $date_format_id = '';
public $enabled_item_tax_rates = 0;
// public $enabled_item_tax_rates = 0;
public $expense_number_pattern = '';
public $expense_number_counter = 1;
public $inclusive_taxes = false;

View File

@ -91,7 +91,7 @@ class InvoiceItemSum
}
private function sumLineItem()
{
{ //todo need to support quantities less than the precision amount
$this->setLineTotal($this->formatValue($this->item->cost, $this->currency->precision) * $this->formatValue($this->item->quantity, $this->currency->precision));
return $this;
}

View File

@ -265,8 +265,8 @@ class BaseController extends Controller
'company.payments.paymentables',
'company.quotes.invitations.contact',
'company.quotes.invitations.company',
'company.credits',
'company.payment_terms',
'company.credits.invitations.company',
'company.payment_terms.company',
//'company.credits.invitations.contact',
//'company.credits.invitations.company',
'company.vendors.contacts',
@ -291,7 +291,7 @@ class BaseController extends Controller
* Thresholds for displaying large account on first load
*/
if (request()->has('first_load') && request()->input('first_load') == 'true') {
if (auth()->user()->getCompany()->invoices->count() > 1000 || auth()->user()->getCompany()->products->count() > 1000) {
if (auth()->user()->getCompany()->invoices->count() > 1000 || auth()->user()->getCompany()->products->count() > 1000 || auth()->user()->getCompany()->clients->count() > 1000) {
$data = $mini_load;
} else {
$data = $first_load;

View File

@ -120,7 +120,7 @@ class PaymentController extends Controller
return $gateway
->driver(auth()->user()->client)
->setPaymentMethod()
->setPaymentMethod($payment_method_id)
->processPaymentView($data);
}

View File

@ -66,7 +66,6 @@
* @OA\Property(property="invoice_terms", type="string", example="Invoice Terms are...", description="The default invoice terms"),
* @OA\Property(property="quote_terms", type="string", example="Quote Terms are...", description="The default quote terms"),
* @OA\Property(property="invoice_taxes", type="number", example="1", description="Taxes can be applied to the invoice"),
* @OA\Property(property="enabled_item_tax_rates", type="number", example="1", description="Taxes can be applied to the invoice items"),
* @OA\Property(property="invoice_design_id", type="string", example="1", description="The default design id (invoice, quote etc)"),
* @OA\Property(property="quote_design_id", type="string", example="1", description="The default design id (invoice, quote etc)"),
* @OA\Property(property="invoice_footer", type="string", example="1", description="The default invoice footer"),
@ -130,7 +129,6 @@
* @OA\Property(property="email_template_statement", type="string", example="template matter", description="____________"),
* @OA\Property(property="email_subject_statement", type="string", example="subject matter", description="____________"),
* @OA\Property(property="signature_on_pdf", type="boolean", example=false, description="____________"),
* @OA\Property(property="send_portal_password", type="boolean", example=false, description="____________"),
* @OA\Property(property="quote_footer", type="string", example="the quote footer", description="____________"),
* @OA\Property(property="email_subject_custom1", type="string", example="Custom Subject 1", description="____________"),
* @OA\Property(property="email_subject_custom2", type="string", example="Custom Subject 2", description="____________"),

View File

@ -37,6 +37,7 @@ class Cors
$response->headers->set('Access-Control-Allow-Origin', '*');
$response->headers->set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
$response->headers->set('Access-Control-Allow-Headers', 'X-API-SECRET,X-API-TOKEN,X-API-PASSWORD,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range');
$response->headers->set('Access-Control-Expose-Headers', 'X-APP-VERSION');
$response->headers->set('X-APP-VERSION', config('ninja.app_version'));
$response->headers->set('X-API-VERSION', config('ninja.api_version'));

View File

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

View File

@ -44,11 +44,9 @@ class CheckDbStatus implements ShouldQueue
*/
public function handle()
{
info("checking db status");
DbStatus::dispatch('db-ninja-01', 'db.status.db-ninja-01');
DbStatus::dispatch('db-ninja-02', 'db.status.db-ninja-02');
DbStatus::dispatchNow('db-ninja-01', 'db.status.db-ninja-01');
DbStatus::dispatchNow('db-ninja-02', 'db.status.db-ninja-02');
}

View File

@ -47,6 +47,9 @@ class UploadAvatar implements ShouldQueue
$path = Storage::putFile('public/' . $this->directory, new File(sys_get_temp_dir().'/'.$tmp_file));
info($path);
info($tmp_file);
$url = Storage::url($path);
//return file path

View File

@ -70,6 +70,7 @@ class Credit extends BaseModel
protected $casts = [
'line_items' => 'object',
'backup' => 'object',
'updated_at' => 'timestamp',
'created_at' => 'timestamp',
'deleted_at' => 'timestamp',

View File

@ -25,5 +25,7 @@ class Currency extends StaticModel
'updated_at' => 'timestamp',
'created_at' => 'timestamp',
'deleted_at' => 'timestamp',
//'precision' => 'string',
'precision' => 'integer',
];
}

View File

@ -103,6 +103,7 @@ class Invoice extends BaseModel
protected $casts = [
'line_items' => 'object',
'backup' => 'object',
'updated_at' => 'timestamp',
'created_at' => 'timestamp',
'deleted_at' => 'timestamp',

View File

@ -76,6 +76,7 @@ class Quote extends BaseModel
'due_date' => 'date:Y-m-d',
'partial_due_date' => 'date:Y-m-d',
'line_items' => 'object',
'backup' => 'object',
'updated_at' => 'timestamp',
'created_at' => 'timestamp',
'deleted_at' => 'timestamp',

View File

@ -101,6 +101,7 @@ class RecurringInvoice extends BaseModel
protected $casts = [
'settings' => 'object',
'line_items' => 'object',
'backup' => 'object',
'updated_at' => 'timestamp',
'created_at' => 'timestamp',
'deleted_at' => 'timestamp',

View File

@ -83,6 +83,7 @@ class RecurringQuote extends BaseModel
protected $casts = [
'line_items' => 'object',
'backup' => 'object',
'settings' => 'object',
'updated_at' => 'timestamp',
'created_at' => 'timestamp',

View File

@ -16,8 +16,8 @@ abstract class AbstractPaymentDriver
abstract public function authorize($payment_method);
abstract public function purchase();
abstract public function purchase($amount, $return_client_response = false);
abstract public function refund();
abstract public function refund($amount, $transaction_reference, $return_client_response = false);
}

View File

@ -0,0 +1,104 @@
<?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\PaymentDrivers\Authorize;
use App\PaymentDrivers\AuthorizePaymentDriver;
use net\authorize\api\contract\v1\CreateTransactionRequest;
use net\authorize\api\contract\v1\CustomerProfilePaymentType;
use net\authorize\api\contract\v1\PaymentProfileType;
use net\authorize\api\contract\v1\TransactionRequestType;
use net\authorize\api\controller\CreateTransactionController;
/**
* Class ChargePaymentProfile
* @package App\PaymentDrivers\Authorize
*
*/
class ChargePaymentProfile
{
public function __construct(AuthorizePaymentDriver $authorize)
{
$this->authorize = $authorize;
}
function chargeCustomerProfile($profile_id, $payment_profile_id, $amount)
{
$this->authorize->init();
// Set the transaction's refId
$refId = 'ref' . time();
$profileToCharge = new CustomerProfilePaymentType();
$profileToCharge->setCustomerProfileId($profile_id);
$paymentProfile = new PaymentProfileType();
$paymentProfile->setPaymentProfileId($payment_profile_id);
$profileToCharge->setPaymentProfile($paymentProfile);
$transactionRequestType = new TransactionRequestType();
$transactionRequestType->setTransactionType("authCaptureTransaction");
$transactionRequestType->setAmount($amount);
$transactionRequestType->setProfile($profileToCharge);
$request = new CreateTransactionRequest();
$request->setMerchantAuthentication($this->authorize->merchant_authentication);
$request->setRefId( $refId);
$request->setTransactionRequest( $transactionRequestType);
$controller = new CreateTransactionController($request);
$response = $controller->executeWithApiResponse($this->authorize->mode());
if($response != null &&$response->getMessages()->getResultCode() == "Ok")
{
$tresponse = $response->getTransactionResponse();
if ($tresponse != null && $tresponse->getMessages() != null)
{
echo " Transaction Response code : " . $tresponse->getResponseCode() . "\n";
echo "Charge Customer Profile APPROVED :" . "\n";
echo " Charge Customer Profile AUTH CODE : " . $tresponse->getAuthCode() . "\n";
echo " Charge Customer Profile TRANS ID : " . $tresponse->getTransId() . "\n";
echo " Code : " . $tresponse->getMessages()[0]->getCode() . "\n";
echo " Description : " . $tresponse->getMessages()[0]->getDescription() . "\n";
}
else
{
echo "Transaction Failed \n";
if($tresponse->getErrors() != null)
{
echo " Error code : " . $tresponse->getErrors()[0]->getErrorCode() . "\n";
echo " Error message : " . $tresponse->getErrors()[0]->getErrorText() . "\n";
}
}
}
else
{
echo "Transaction Failed \n";
$tresponse = $response->getTransactionResponse();
if($tresponse != null && $tresponse->getErrors() != null)
{
echo " Error code : " . $tresponse->getErrors()[0]->getErrorCode() . "\n";
echo " Error message : " . $tresponse->getErrors()[0]->getErrorText() . "\n";
}
else
{
echo " Error code : " . $response->getMessages()->getMessage()[0]->getCode() . "\n";
echo " Error message : " . $response->getMessages()->getMessage()[0]->getText() . "\n";
}
}
}
}

View File

@ -0,0 +1,113 @@
<?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\PaymentDrivers\Authorize;
use App\PaymentDrivers\AuthorizePaymentDriver;
use net\authorize\api\contract\v1\CreateTransactionRequest;
use net\authorize\api\contract\v1\CustomerProfilePaymentType;
use net\authorize\api\contract\v1\PaymentProfileType;
use net\authorize\api\contract\v1\TransactionRequestType;
use net\authorize\api\controller\CreateTransactionController;
/**
* Class RefundTransaction
* @package App\PaymentDrivers\Authorize
*
*/
class RefundTransaction
{
public function __construct(AuthorizePaymentDriver $authorize)
{
$this->authorize = $authorize;
}
function refundTransaction($transaction_reference, $amount, $payment_profile_id, $profile_id)
{
$this->authorize->init();
// Set the transaction's refId
$refId = 'ref' . time();
$paymentProfile = new PaymentProfileType();
$paymentProfile->setPaymentProfileId( $payment_profile_id );
// set customer profile
$customerProfile = new CustomerProfilePaymentType();
$customerProfile->setCustomerProfileId( $profile_id );
$customerProfile->setPaymentProfile( $paymentProfile );
//create a transaction
$transactionRequest = new TransactionRequestType();
$transactionRequest->setTransactionType("refundTransaction");
$transactionRequest->setAmount($amount);
$transactionRequest->setProfile($customerProfile);
$transactionRequest->setRefTransId($transaction_reference);
$request = new CreateTransactionRequest();
$request->setMerchantAuthentication($this->authorize->merchant_authentication);
$request->setRefId($refId);
$request->setTransactionRequest($transactionRequest);
$controller = new CreateTransactionController($request);
$response = $controller->executeWithApiResponse($this->authorize->mode());
if ($response != null)
{
if($response->getMessages()->getResultCode() == "Ok")
{
$tresponse = $response->getTransactionResponse();
if ($tresponse != null && $tresponse->getMessages() != null)
{
echo " Transaction Response code : " . $tresponse->getResponseCode() . "\n";
echo "Refund SUCCESS: " . $tresponse->getTransId() . "\n";
echo " Code : " . $tresponse->getMessages()[0]->getCode() . "\n";
echo " Description : " . $tresponse->getMessages()[0]->getDescription() . "\n";
}
else
{
echo "Transaction Failed \n";
if($tresponse->getErrors() != null)
{
echo " Error code : " . $tresponse->getErrors()[0]->getErrorCode() . "\n";
echo " Error message : " . $tresponse->getErrors()[0]->getErrorText() . "\n";
}
}
}
else
{
echo "Transaction Failed \n";
$tresponse = $response->getTransactionResponse();
if($tresponse != null && $tresponse->getErrors() != null)
{
echo " Error code : " . $tresponse->getErrors()[0]->getErrorCode() . "\n";
echo " Error message : " . $tresponse->getErrors()[0]->getErrorText() . "\n";
}
else
{
echo " Error code : " . $response->getMessages()->getMessage()[0]->getCode() . "\n";
echo " Error message : " . $response->getMessages()->getMessage()[0]->getText() . "\n";
}
}
}
else
{
echo "No response returned \n";
}
return $response;
}
}

View File

@ -86,23 +86,30 @@ class AuthorizePaymentDriver extends BaseDriver
public function authorizeResponseView(array $data)
{
return (new AuthorizePaymentMethod($this))->authorizeResponseView($data['gateway_type_id'], $data);
}
public function authorize($payment_method)
{
return $this->authorizeView($payment_method);
}
public function purchase()
public function processPaymentView($data)
{
}
public function refund()
public function processPaymentResponse($request)
{
}
public function purchase($amount, $return_client_response = false)
{
return false;
}
public function refund($amount, $transaction_reference, $return_client_response = false)
{
}

View File

@ -17,7 +17,6 @@ use App\Models\CompanyGateway;
use App\PaymentDrivers\AbstractPaymentDriver;
use App\Utils\Traits\MakesHash;
use App\Utils\Traits\SystemLogTrait;
use Omnipay\Omnipay;
/**
* Class BaseDriver
@ -33,17 +32,21 @@ class BaseDriver extends AbstractPaymentDriver
public $company_gateway;
/* The Invitation */
protected $invitation;
public $invitation;
/* Gateway capabilities */
protected $refundable = false;
public $refundable = false;
/* Token billing */
protected $token_billing = false;
public $token_billing = false;
/* Authorise payment methods */
protected $can_authorise_credit_card = false;
public $can_authorise_credit_card = false;
/* The client */
public $client;
public $payment_method;
public function __construct(CompanyGateway $company_gateway, Client $client = null, $invitation = false)
{
@ -54,10 +57,52 @@ class BaseDriver extends AbstractPaymentDriver
$this->client = $client;
}
/**
* Authorize a payment method.
*
* Returns a reusable token for storage for future payments
* @param const $payment_method the GatewayType::constant
* @return view Return a view for collecting payment method information
*/
public function authorize($payment_method) {}
public function purchase() {}
/**
* Executes purchase attempt for a given amount
*
* @param float $amount The amount to be collected
* @param boolean $return_client_response Whether the method needs to return a response (otherwise we assume an unattended payment)
* @return mixed
*/
public function purchase($amount, $return_client_response = false) {}
public function refund() {}
/**
* Executes a refund attempt for a given amount with a transaction_reference
*
* @param float $amount The amount to be refunded
* @param string $transaction_reference The transaction reference
* @param boolean $return_client_response Whether the method needs to return a response (otherwise we assume an unattended payment)
* @return mixed
*/
public function refund($amount, $transaction_reference, $return_client_response = false) {}
/**
* Set the inbound request payment method type for access.
*
* @param int $payment_method_id The Payment Method ID
*/
public function setPaymentMethod($payment_method_id)
{
$this->payment_method = $payment_method_id;
return $this;
}
/**
* Get the payment method ID
*
* @return int The payment method ID
*/
public function getPaymentMethod()
{
return $this->payment_method;
}
}

View File

@ -45,6 +45,9 @@ class HandleCancellation extends AbstractService
}
$adjustment = $this->invoice->balance*-1;
$this->backupCancellation($adjustment);
//set invoice balance to 0
$this->invoice->ledger()->updateInvoiceBalance($adjustment, "Invoice cancellation");
@ -56,6 +59,58 @@ class HandleCancellation extends AbstractService
event(new InvoiceWasCancelled($this->invoice));
return $this->invoice;
}
public function reverse()
{
$cancellation = $this->invoice->backup->cancellation;
$adjustment = $cancellation->adjustment*-1;
$this->invoice->ledger()->updateInvoiceBalance($adjustment, "Invoice cancellation REVERSAL");
/* Reverse the invoice status and balance */
$this->invoice->balance += $adjustment;
$this->invoice->status_id = $cancellation->status_id;
$this->invoice->client->service()->updateBalance($adjustment)->save();
/* Pop the cancellation out of the backup*/
$backup = $this->invoice->backup;
unset($backup->cancellation);
$this->invoice->backup = $backup;
$this->invoice->save();
return $this->invoice;
}
/**
* Backup the cancellation in case we ever need to reverse it.
*
* @param float $adjustment The amount the balance has been reduced by to cancel the invoice
* @return void
*/
private function backupCancellation($adjustment)
{
if(!is_object($this->invoice->backup)){
$backup = new \stdClass;
$this->invoice->backup = $backup;
}
$cancellation = new \stdClass;
$cancellation->adjustment = $adjustment;
$cancellation->status_id = $this->invoice->status_id;
$invoice_backup = $this->invoice->backup;
$invoice_backup->cancellation = $cancellation;
$this->invoice->backup = $invoice_backup;
$this->invoice->save();
}
}

View File

@ -44,12 +44,14 @@ class HandleReversal extends AbstractService
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();
@ -88,10 +90,12 @@ class HandleReversal extends AbstractService
$credit->service()->markSent()->save();
}
/* Set invoice balance to 0 */
$this->invoice->ledger()->updateInvoiceBalance($balance_remaining*-1, $notes)->save();
$this->invoice->balance= 0;
/* Set invoice balance to 0 */
if($this->invoice->balance != 0)
$this->invoice->ledger()->updateInvoiceBalance($balance_remaining*-1, $notes)->save();
$this->invoice->balance=0;
/* Set invoice status to reversed... somehow*/
$this->invoice->service()->setStatus(Invoice::STATUS_REVERSED)->save();
@ -109,6 +113,42 @@ class HandleReversal extends AbstractService
return $this->invoice;
//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
// }
}
// The client paid to date amount is reduced by the calculated amount of (invoice balance - invoice amount).

View File

@ -129,6 +129,13 @@ class InvoiceService
return $this;
}
public function reverseCancellation()
{
$this->invoice = (new HandleCancellation($this->invoice))->reverse();
return $this;
}
public function markViewed()
{
$this->invoice->last_viewed = Carbon::now()->format('Y-m-d H:i');

View File

@ -121,6 +121,7 @@ class CompanyTransformer extends EntityTransformer
'slack_webhook_url' => (string)$company->slack_webhook_url,
'google_analytics_url' => (string)$company->google_analytics_key, //@deprecate
'google_analytics_key' => (string)$company->google_analytics_key,
'enabled_item_tax_rates' => (int) $company->enabled_item_tax_rates
];
}

View File

@ -17,7 +17,10 @@ trait ActionsInvoice
{
public function invoiceDeletable($invoice) :bool
{
if ($invoice->status_id <= Invoice::STATUS_SENT && $invoice->is_deleted == false && $invoice->deleted_at == null && $invoice->balance == 0) {
if ($invoice->status_id <= Invoice::STATUS_SENT &&
$invoice->is_deleted == false &&
$invoice->deleted_at == null &&
$invoice->balance == 0) {
return true;
}
@ -26,7 +29,10 @@ trait ActionsInvoice
public function invoiceCancellable($invoice) :bool
{
if (($invoice->status_id == Invoice::STATUS_SENT || $invoice->status_id == Invoice::STATUS_PARTIAL) && $invoice->is_deleted == false && $invoice->deleted_at == null) {
if (($invoice->status_id == Invoice::STATUS_SENT ||
$invoice->status_id == Invoice::STATUS_PARTIAL) &&
$invoice->is_deleted == false &&
$invoice->deleted_at == null) {
return true;
}
@ -35,7 +41,12 @@ trait ActionsInvoice
public function invoiceReversable($invoice) :bool
{
if (($invoice->status_id == Invoice::STATUS_SENT || $invoice->status_id == Invoice::STATUS_PARTIAL || $invoice->status_id == Invoice::STATUS_PAID) && $invoice->is_deleted == false && $invoice->deleted_at == null) {
if (($invoice->status_id == Invoice::STATUS_SENT ||
$invoice->status_id == Invoice::STATUS_PARTIAL ||
$invoice->status_id == Invoice::STATUS_CANCELLED ||
$invoice->status_id == Invoice::STATUS_PAID) &&
$invoice->is_deleted == false &&
$invoice->deleted_at == null) {
return true;
}

View File

@ -22,6 +22,7 @@
"ext-json": "*",
"asgrim/ofxparser": "^1.2",
"checkout/checkout-sdk-php": "^1.0",
"authorizenet/authorizenet": "^2.0",
"cleverit/ubl_invoice": "^1.3",
"composer/composer": "^1.10",
"czproject/git-php": "^3.17",
@ -53,7 +54,7 @@
"spatie/browsershot": "^3.29",
"staudenmeir/eloquent-has-many-deep": "^1.11",
"stripe/stripe-php": "^7.0",
"turbo124/beacon": "^0",
"turbo124/beacon": "^1",
"webpatser/laravel-countries": "dev-master#75992ad",
"yajra/laravel-datatables-oracle": "~9.0"
},

158
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "92303801b323e8ec67d40803e6b4127f",
"content-hash": "6441fc634b3600e7099ae8c02d6230b0",
"packages": [
{
"name": "asgrim/ofxparser",
@ -63,17 +63,60 @@
"time": "2018-10-29T10:10:13+00:00"
},
{
"name": "aws/aws-sdk-php",
"version": "3.140.4",
"name": "authorizenet/authorizenet",
"version": "2.0.0",
"source": {
"type": "git",
"url": "https://github.com/aws/aws-sdk-php.git",
"reference": "298ec070adad5760c4b90348219bb3e6bd7a9322"
"url": "https://github.com/AuthorizeNet/sdk-php.git",
"reference": "7fa78e6397d363296e462c3b348573c17175b7a8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/298ec070adad5760c4b90348219bb3e6bd7a9322",
"reference": "298ec070adad5760c4b90348219bb3e6bd7a9322",
"url": "https://api.github.com/repos/AuthorizeNet/sdk-php/zipball/7fa78e6397d363296e462c3b348573c17175b7a8",
"reference": "7fa78e6397d363296e462c3b348573c17175b7a8",
"shasum": ""
},
"require": {
"ext-curl": "*",
"ext-json": "*",
"php": ">=5.6"
},
"require-dev": {
"phpmd/phpmd": "~2.0",
"phpunit/phpunit": "~4.0"
},
"type": "library",
"autoload": {
"classmap": [
"lib"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"proprietary"
],
"description": "Official PHP SDK for Authorize.Net",
"homepage": "http://developer.authorize.net",
"keywords": [
"authorize.net",
"authorizenet",
"ecommerce",
"payment"
],
"time": "2019-01-14T13:32:41+00:00"
},
{
"name": "aws/aws-sdk-php",
"version": "3.142.1",
"source": {
"type": "git",
"url": "https://github.com/aws/aws-sdk-php.git",
"reference": "ab92ec111132712417cc97be06275553b10a76ab"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/ab92ec111132712417cc97be06275553b10a76ab",
"reference": "ab92ec111132712417cc97be06275553b10a76ab",
"shasum": ""
},
"require": {
@ -96,6 +139,7 @@
"ext-pcntl": "*",
"ext-sockets": "*",
"nette/neon": "^2.3",
"paragonie/random_compat": ">= 2",
"phpunit/phpunit": "^4.8.35|^5.4.3",
"psr/cache": "^1.0",
"psr/simple-cache": "^1.0",
@ -144,7 +188,7 @@
"s3",
"sdk"
],
"time": "2020-06-09T18:11:16+00:00"
"time": "2020-06-12T18:16:31+00:00"
},
{
"name": "checkout/checkout-sdk-php",
@ -4223,16 +4267,16 @@
},
{
"name": "php-http/discovery",
"version": "1.7.4",
"version": "1.8.0",
"source": {
"type": "git",
"url": "https://github.com/php-http/discovery.git",
"reference": "82dbef649ccffd8e4f22e1953c3a5265992b83c0"
"reference": "10d9019f393773345aedc0dc79e7fd678da874ee"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-http/discovery/zipball/82dbef649ccffd8e4f22e1953c3a5265992b83c0",
"reference": "82dbef649ccffd8e4f22e1953c3a5265992b83c0",
"url": "https://api.github.com/repos/php-http/discovery/zipball/10d9019f393773345aedc0dc79e7fd678da874ee",
"reference": "10d9019f393773345aedc0dc79e7fd678da874ee",
"shasum": ""
},
"require": {
@ -4284,7 +4328,7 @@
"message",
"psr7"
],
"time": "2020-01-03T11:25:47+00:00"
"time": "2020-06-14T10:44:12+00:00"
},
{
"name": "php-http/guzzle6-adapter",
@ -6018,16 +6062,16 @@
},
{
"name": "stripe/stripe-php",
"version": "v7.37.0",
"version": "v7.37.1",
"source": {
"type": "git",
"url": "https://github.com/stripe/stripe-php.git",
"reference": "246871743edb26c7a7657784205218daf7d99a73"
"reference": "e3e29131a131785c3d2f85556b0154e8170e9bba"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/stripe/stripe-php/zipball/246871743edb26c7a7657784205218daf7d99a73",
"reference": "246871743edb26c7a7657784205218daf7d99a73",
"url": "https://api.github.com/repos/stripe/stripe-php/zipball/e3e29131a131785c3d2f85556b0154e8170e9bba",
"reference": "e3e29131a131785c3d2f85556b0154e8170e9bba",
"shasum": ""
},
"require": {
@ -6071,7 +6115,7 @@
"payment processing",
"stripe"
],
"time": "2020-06-09T22:55:43+00:00"
"time": "2020-06-11T16:27:35+00:00"
},
{
"name": "swiftmailer/swiftmailer",
@ -6137,7 +6181,7 @@
},
{
"name": "symfony/console",
"version": "v4.4.9",
"version": "v4.4.10",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
@ -6228,7 +6272,7 @@
},
{
"name": "symfony/css-selector",
"version": "v5.1.0",
"version": "v5.1.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
@ -6295,7 +6339,7 @@
},
{
"name": "symfony/debug",
"version": "v4.4.9",
"version": "v4.4.10",
"source": {
"type": "git",
"url": "https://github.com/symfony/debug.git",
@ -6426,7 +6470,7 @@
},
{
"name": "symfony/error-handler",
"version": "v4.4.9",
"version": "v4.4.10",
"source": {
"type": "git",
"url": "https://github.com/symfony/error-handler.git",
@ -6497,7 +6541,7 @@
},
{
"name": "symfony/event-dispatcher",
"version": "v4.4.9",
"version": "v4.4.10",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
@ -6639,7 +6683,7 @@
},
{
"name": "symfony/filesystem",
"version": "v5.1.0",
"version": "v5.1.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
@ -6703,7 +6747,7 @@
},
{
"name": "symfony/finder",
"version": "v4.4.9",
"version": "v4.4.10",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
@ -6766,7 +6810,7 @@
},
{
"name": "symfony/http-foundation",
"version": "v4.4.9",
"version": "v4.4.10",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
@ -6835,16 +6879,16 @@
},
{
"name": "symfony/http-kernel",
"version": "v4.4.9",
"version": "v4.4.10",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-kernel.git",
"reference": "54526b598d7fc86a67850488b194a88a79ab8467"
"reference": "81d42148474e1852a333ed7a732f2a014af75430"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/54526b598d7fc86a67850488b194a88a79ab8467",
"reference": "54526b598d7fc86a67850488b194a88a79ab8467",
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/81d42148474e1852a333ed7a732f2a014af75430",
"reference": "81d42148474e1852a333ed7a732f2a014af75430",
"shasum": ""
},
"require": {
@ -6936,20 +6980,20 @@
"type": "tidelift"
}
],
"time": "2020-05-31T05:25:51+00:00"
"time": "2020-06-12T11:15:37+00:00"
},
{
"name": "symfony/mime",
"version": "v5.1.0",
"version": "v5.1.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/mime.git",
"reference": "56261f89385f9d13cf843a5101ac72131190bc91"
"reference": "c0c418f05e727606e85b482a8591519c4712cf45"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/mime/zipball/56261f89385f9d13cf843a5101ac72131190bc91",
"reference": "56261f89385f9d13cf843a5101ac72131190bc91",
"url": "https://api.github.com/repos/symfony/mime/zipball/c0c418f05e727606e85b482a8591519c4712cf45",
"reference": "c0c418f05e727606e85b482a8591519c4712cf45",
"shasum": ""
},
"require": {
@ -7013,11 +7057,11 @@
"type": "tidelift"
}
],
"time": "2020-05-25T12:33:44+00:00"
"time": "2020-06-09T15:07:35+00:00"
},
{
"name": "symfony/options-resolver",
"version": "v5.1.0",
"version": "v5.1.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/options-resolver.git",
@ -7671,7 +7715,7 @@
},
{
"name": "symfony/process",
"version": "v4.4.9",
"version": "v4.4.10",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
@ -7734,7 +7778,7 @@
},
{
"name": "symfony/routing",
"version": "v4.4.9",
"version": "v4.4.10",
"source": {
"type": "git",
"url": "https://github.com/symfony/routing.git",
@ -7896,7 +7940,7 @@
},
{
"name": "symfony/translation",
"version": "v4.4.9",
"version": "v4.4.10",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
@ -8057,7 +8101,7 @@
},
{
"name": "symfony/var-dumper",
"version": "v4.4.9",
"version": "v4.4.10",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
@ -8197,16 +8241,16 @@
},
{
"name": "turbo124/beacon",
"version": "0.83",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/turbo124/beacon.git",
"reference": "97157e507fcca352d1cc445b8a3a1970ec448eee"
"reference": "21e1ba46776fae8dc4bcf672890b257e3452be59"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/turbo124/beacon/zipball/97157e507fcca352d1cc445b8a3a1970ec448eee",
"reference": "97157e507fcca352d1cc445b8a3a1970ec448eee",
"url": "https://api.github.com/repos/turbo124/beacon/zipball/21e1ba46776fae8dc4bcf672890b257e3452be59",
"reference": "21e1ba46776fae8dc4bcf672890b257e3452be59",
"shasum": ""
},
"require": {
@ -8253,7 +8297,7 @@
"lightlogs",
"turbo124"
],
"time": "2020-06-09T07:24:25+00:00"
"time": "2020-06-10T22:55:22+00:00"
},
{
"name": "vlucas/phpdotenv",
@ -8980,16 +9024,16 @@
},
{
"name": "filp/whoops",
"version": "2.7.2",
"version": "2.7.3",
"source": {
"type": "git",
"url": "https://github.com/filp/whoops.git",
"reference": "17d0d3f266c8f925ebd035cd36f83cf802b47d4a"
"reference": "5d5fe9bb3d656b514d455645b3addc5f7ba7714d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/filp/whoops/zipball/17d0d3f266c8f925ebd035cd36f83cf802b47d4a",
"reference": "17d0d3f266c8f925ebd035cd36f83cf802b47d4a",
"url": "https://api.github.com/repos/filp/whoops/zipball/5d5fe9bb3d656b514d455645b3addc5f7ba7714d",
"reference": "5d5fe9bb3d656b514d455645b3addc5f7ba7714d",
"shasum": ""
},
"require": {
@ -9037,7 +9081,7 @@
"throwable",
"whoops"
],
"time": "2020-05-05T12:28:07+00:00"
"time": "2020-06-14T09:00:00+00:00"
},
{
"name": "hamcrest/hamcrest-php",
@ -10743,16 +10787,16 @@
},
{
"name": "swagger-api/swagger-ui",
"version": "v3.26.0",
"version": "v3.26.2",
"source": {
"type": "git",
"url": "https://github.com/swagger-api/swagger-ui.git",
"reference": "b9064157e710d0c56d4459b5a7c16751ad0ae72c"
"reference": "ae33deeaab47129844b89192d35762abf5cf80fb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/swagger-api/swagger-ui/zipball/b9064157e710d0c56d4459b5a7c16751ad0ae72c",
"reference": "b9064157e710d0c56d4459b5a7c16751ad0ae72c",
"url": "https://api.github.com/repos/swagger-api/swagger-ui/zipball/ae33deeaab47129844b89192d35762abf5cf80fb",
"reference": "ae33deeaab47129844b89192d35762abf5cf80fb",
"shasum": ""
},
"type": "library",
@ -10796,11 +10840,11 @@
"swagger",
"ui"
],
"time": "2020-06-05T00:57:11+00:00"
"time": "2020-06-12T13:09:03+00:00"
},
{
"name": "symfony/yaml",
"version": "v4.4.9",
"version": "v4.4.10",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",

View File

@ -36,7 +36,8 @@ return [
'system_logging' => [
'Turbo124\Beacon\Jobs\System\CpuMetric',
'Turbo124\Beacon\Jobs\System\HdMetric',
'Turbo124\Beacon\Jobs\System\MemMetric'
'Turbo124\Beacon\Jobs\System\MemMetric',
'App\Jobs\Ninja\CheckDbStatus',
],
];

View File

@ -9,6 +9,7 @@ return [
'version_url' => 'https://raw.githubusercontent.com/invoiceninja/invoiceninja/v2/VERSION.txt',
'app_name' => env('APP_NAME'),
'app_env' => env('APP_ENV', 'local'),
'require_https' => env('REQUIRE_HTTPS', true),
'app_url' => env('APP_URL', ''),
'app_domain' => env('APP_DOMAIN', ''),
'app_version' => '5.0.4',

View File

@ -454,6 +454,7 @@ class CreateUsersTable extends Migration
$t->boolean('is_deleted')->default(false);
$t->mediumText('line_items')->nullable();
$t->mediumText('backup')->nullable();
$t->text('footer')->nullable();
$t->text('public_notes')->nullable();
$t->text('private_notes')->nullable();
@ -530,6 +531,7 @@ class CreateUsersTable extends Migration
$t->boolean('is_deleted')->default(false);
$t->mediumText('line_items')->nullable();
$t->mediumText('backup')->nullable();
$t->text('footer')->nullable();
$t->text('public_notes')->nullable();
$t->text('private_notes')->nullable();
@ -633,6 +635,7 @@ class CreateUsersTable extends Migration
$t->boolean('is_deleted')->default(false);
$t->mediumText('line_items')->nullable();
$t->mediumText('backup')->nullable();
$t->text('footer')->nullable();
$t->text('public_notes')->nullable();
$t->text('private_notes')->nullable();
@ -699,6 +702,7 @@ class CreateUsersTable extends Migration
$t->boolean('is_deleted')->default(false);
$t->mediumText('line_items')->nullable();
$t->mediumText('backup')->nullable();
$t->text('footer')->nullable();
$t->text('public_notes')->nullable();
@ -770,7 +774,7 @@ class CreateUsersTable extends Migration
$t->boolean('is_deleted')->default(false);
$t->mediumText('line_items')->nullable();
$t->mediumText('backup')->nullable();
$t->text('footer')->nullable();
$t->text('public_notes')->nullable();

View File

@ -20,6 +20,10 @@ class AddGoogleRefreshTokenToUsersTable extends Migration
DB::statement("alter table users modify column oauth_user_token text");
Schema::table('companies', function (Blueprint $table){
$table->integer('enabled_item_tax_rates')->default(0);
});
}
/**

View File

@ -3,22 +3,22 @@ const MANIFEST = 'flutter-app-manifest';
const TEMP = 'flutter-temp-cache';
const CACHE_NAME = 'flutter-app-cache';
const RESOURCES = {
"favicon.ico": "51636d3a390451561744c42188ccd628",
"main.dart.js": "e27dfb6dc90e50f3956bc198256af1a7",
"assets/web/assets/fonts/Roboto-Regular.ttf": "3e1af3ef546b9e6ecef9f3ba197bf7d2",
"assets/NOTICES": "8e6e4a20b409c4109de20a91757d52a7",
"assets/fonts/MaterialIcons-Regular.ttf": "56d3ffdef7a25659eab6a68a3fbfaf16",
"assets/fonts/MaterialIcons-Regular.ttf": "56d3ffdef7a25659eab6a68a3fbfaf16",
"assets/fonts/Roboto-Regular.ttf": "3e1af3ef546b9e6ecef9f3ba197bf7d2",
"assets/FontManifest.json": "280b2f61f6810d59bd1bcd4cf01d3bf4",
"assets/packages/font_awesome_flutter/lib/fonts/fa-brands-400.ttf": "5a37ae808cf9f652198acde612b5328d",
"assets/packages/font_awesome_flutter/lib/fonts/fa-regular-400.ttf": "2bca5ec802e40d3f4b60343e346cedde",
"assets/packages/font_awesome_flutter/lib/fonts/fa-solid-900.ttf": "2aa350bd2aeab88b601a593f793734c0",
"assets/assets/images/logo.png": "090f69e23311a4b6d851b3880ae52541",
"assets/assets/images/google-icon.png": "0f118259ce403274f407f5e982e681c3",
"assets/NOTICES": "8e6e4a20b409c4109de20a91757d52a7",
"assets/FontManifest.json": "280b2f61f6810d59bd1bcd4cf01d3bf4",
"assets/packages/font_awesome_flutter/lib/fonts/fa-brands-400.ttf": "5a37ae808cf9f652198acde612b5328d",
"assets/packages/font_awesome_flutter/lib/fonts/fa-solid-900.ttf": "2aa350bd2aeab88b601a593f793734c0",
"assets/packages/font_awesome_flutter/lib/fonts/fa-regular-400.ttf": "2bca5ec802e40d3f4b60343e346cedde",
"assets/web/assets/fonts/Roboto-Regular.ttf": "3e1af3ef546b9e6ecef9f3ba197bf7d2",
"assets/AssetManifest.json": "43bc57fb55ca8ea2fc1975108be086c9",
"manifest.json": "4674b4d7b1f1471cb9a6d64634a8592a",
"main.dart.js": "ea6b5f16864003d4c0a35cf38e0c3f8f",
"manifest.json": "77215c1737c7639764e64a192be2f7b8",
"index.html": "57fdc91b6cf6f7a7eddf1419c5763c19",
"/": "57fdc91b6cf6f7a7eddf1419c5763c19"
"/": "57fdc91b6cf6f7a7eddf1419c5763c19",
"favicon.ico": "51636d3a390451561744c42188ccd628"
};
// The application shell files that are downloaded before a service worker can
@ -27,7 +27,7 @@ const CORE = [
"/",
"main.dart.js",
"index.html",
"assets/LICENSE",
"assets/NOTICES",
"assets/AssetManifest.json",
"assets/FontManifest.json"];
@ -156,8 +156,8 @@ async function downloadOffline() {
}
for (var resourceKey in Object.keys(RESOURCES)) {
if (!currentContent[resourceKey]) {
resources.add(resourceKey);
resources.push(resourceKey);
}
}
return Cache.addAll(resources);
return contentCache.addAll(resources);
}

194432
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

@ -17,11 +17,11 @@
"platform": "itunes",
"url": "https://testflight.apple.com/join/MJ6WpaXh"
}
]
],
"icons": [
{
"src": "images/logo.png",
"sizes": "397x397",
"sizes": "512x512",
"type": "image/png"
}
]

View File

@ -16,7 +16,7 @@
}
</script>
<script src="main.dart.js" type="application/javascript"></script>
<script src="main.dart.js?version={{ config('ninja.api_version') }}" type="application/javascript"></script>
<center style="font-family:Tahoma,Geneva,sans-serif;font-size:28px;color:white;padding-top:100px">
Loading...

View File

@ -81,7 +81,7 @@
</dd>
</div>
<div class="bg-white px-4 py-5 flex justify-end">
<button type="button" id="card_button">{{ ctrans('texts.add_payment_method') }}</button>
<button type="primary" id="card_button">{{ ctrans('texts.add_payment_method') }}</button>
</div>
</dl>
</div>

View File

@ -51,6 +51,6 @@ class CompareObjectTest extends TestCase
$this->assertEquals($settings->timezone_id, 1);
$this->assertEquals($settings->language_id, 1);
$this->assertEquals($settings->payment_terms, -1);
$this->assertFalse($settings->send_portal_password);
$this->assertFalse($settings->auto_archive_invoice);
}
}