mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Merge branch 'v5-develop' of https://github.com/turbo124/invoiceninja into v5-develop
This commit is contained in:
commit
de9154b1bf
@ -28,6 +28,15 @@ class ExpenseMap
|
||||
9 => 'expense.transaction_reference',
|
||||
10 => 'expense.public_notes',
|
||||
11 => 'expense.private_notes',
|
||||
12 => 'expense.tax_name1',
|
||||
13 => 'expense.tax_rate1',
|
||||
14 => 'expense.tax_name2',
|
||||
15 => 'expense.tax_rate2',
|
||||
16 => 'expense.tax_name3',
|
||||
17 => 'expense.tax_rate3',
|
||||
18 => 'expense.uses_inclusive_taxes',
|
||||
19 => 'expense.payment_date',
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
@ -46,6 +55,15 @@ class ExpenseMap
|
||||
9 => 'texts.transaction_reference',
|
||||
10 => 'texts.public_notes',
|
||||
11 => 'texts.private_notes',
|
||||
12 => 'texts.tax_name1',
|
||||
13 => 'texts.tax_rate1',
|
||||
14 => 'texts.tax_name2',
|
||||
15 => 'texts.tax_rate2',
|
||||
16 => 'texts.tax_name3',
|
||||
17 => 'texts.tax_rate3',
|
||||
18 => 'texts.uses_inclusive_taxes',
|
||||
19 => 'texts.payment_date',
|
||||
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ class ExpenseTransformer extends BaseTransformer
|
||||
'client_id' => isset($data['expense.client'])
|
||||
? $this->getClientId($data['expense.client'])
|
||||
: null,
|
||||
'date' => strlen($this->getString($data, 'expense.date') > 1) ? date('Y-m-d', strtotime($this->getString($data, 'expense.date'))) : now()->format('Y-m-d'),
|
||||
'date' => strlen($this->getString($data, 'expense.date') > 1) ? date('Y-m-d', strtotime(str_replace("/","-",$data['expense.date']))) : now()->format('Y-m-d'),
|
||||
'public_notes' => $this->getString($data, 'expense.public_notes'),
|
||||
'private_notes' => $this->getString($data, 'expense.private_notes'),
|
||||
'category_id' => isset($data['expense.category'])
|
||||
@ -55,7 +55,7 @@ class ExpenseTransformer extends BaseTransformer
|
||||
? $this->getPaymentTypeId($data['expense.payment_type'])
|
||||
: null,
|
||||
'payment_date' => isset($data['expense.payment_date'])
|
||||
? date('Y-m-d', strtotime($data['expense.payment_date']))
|
||||
? date('Y-m-d', strtotime(str_replace("/","-",$data['expense.payment_date'])))
|
||||
: null,
|
||||
'custom_value1' => $this->getString($data, 'expense.custom_value1'),
|
||||
'custom_value2' => $this->getString($data, 'expense.custom_value2'),
|
||||
@ -66,6 +66,14 @@ class ExpenseTransformer extends BaseTransformer
|
||||
'expense.transaction_reference'
|
||||
),
|
||||
'should_be_invoiced' => $clientId ? true : false,
|
||||
'uses_inclusive_taxes' => (bool) $this->getString($data, 'expense.uses_inclusive_taxes'),
|
||||
'tax_name1' => $this->getString($data, 'expense.tax_name1'),
|
||||
'tax_rate1' => $this->getFloat($data, 'expense.tax_rate1'),
|
||||
'tax_name2' => $this->getString($data, 'expense.tax_name2'),
|
||||
'tax_rate2' => $this->getFloat($data, 'expense.tax_rate2'),
|
||||
'tax_name3' => $this->getString($data, 'expense.tax_name3'),
|
||||
'tax_rate3' => $this->getFloat($data, 'expense.tax_rate3'),
|
||||
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -57,10 +57,10 @@ class InvoiceTransformer extends BaseTransformer
|
||||
'discount' => $this->getFloat($invoice_data, 'invoice.discount'),
|
||||
'po_number' => $this->getString($invoice_data, 'invoice.po_number'),
|
||||
'date' => isset($invoice_data['invoice.date'])
|
||||
? date('Y-m-d', strtotime($invoice_data['invoice.date']))
|
||||
? date('Y-m-d', strtotime(str_replace("/","-",$invoice_data['invoice.date'])))
|
||||
: now()->format('Y-m-d'),
|
||||
'due_date' => isset($invoice_data['invoice.due_date'])
|
||||
? date('Y-m-d', strtotime($invoice_data['invoice.due_date']))
|
||||
? date('Y-m-d', strtotime(str_replace("/","-",$invoice_data['invoice.due_date'])))
|
||||
: null,
|
||||
'terms' => $this->getString($invoice_data, 'invoice.terms'),
|
||||
'public_notes' => $this->getString(
|
||||
|
@ -57,10 +57,10 @@ class QuoteTransformer extends BaseTransformer
|
||||
'discount' => $this->getFloat($quote_data, 'quote.discount'),
|
||||
'po_number' => $this->getString($quote_data, 'quote.po_number'),
|
||||
'date' => isset($quote_data['quote.date'])
|
||||
? date('Y-m-d', strtotime($quote_data['quote.date']))
|
||||
? date('Y-m-d', strtotime(str_replace("/","-",$quote_data['quote.date'])))
|
||||
: now()->format('Y-m-d'),
|
||||
'due_date' => isset($quote_data['quote.due_date'])
|
||||
? date('Y-m-d', strtotime($quote_data['quote.due_date']))
|
||||
? date('Y-m-d', strtotime(str_replace("/","-",$quote_data['quote.due_date'])))
|
||||
: null,
|
||||
'terms' => $this->getString($quote_data, 'quote.terms'),
|
||||
'public_notes' => $this->getString(
|
||||
|
86
app/Notifications/Ninja/DomainFailureNotification.php
Normal file
86
app/Notifications/Ninja/DomainFailureNotification.php
Normal file
@ -0,0 +1,86 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Notifications\Ninja;
|
||||
|
||||
use App\Models\Account;
|
||||
use App\Models\Client;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Messages\SlackMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class DomainFailureNotification extends Notification
|
||||
{
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
protected string $domain;
|
||||
|
||||
public function __construct(string $domain)
|
||||
{
|
||||
$this->domain = $domain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function via($notifiable)
|
||||
{
|
||||
return ['slack'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return MailMessage
|
||||
*/
|
||||
public function toMail($notifiable)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($notifiable)
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
|
||||
public function toSlack($notifiable)
|
||||
{
|
||||
$content = "Domain Certificate failure:\n";
|
||||
$content .= "{$this->domain}\n";
|
||||
|
||||
return (new SlackMessage)
|
||||
->success()
|
||||
->from(ctrans('texts.notification_bot'))
|
||||
->image('https://app.invoiceninja.com/favicon.png')
|
||||
->content($content);
|
||||
}
|
||||
}
|
@ -79,8 +79,6 @@ class NewAccountNotification extends Notification
|
||||
{
|
||||
$content = "New Trial Started\n";
|
||||
$content .= "{$this->client->name}\n";
|
||||
$content .= "Account key: {$this->account->key}\n";
|
||||
$content .= "Users: {$this->account->users()->pluck('email')}\n";
|
||||
$content .= "Contacts: {$this->client->contacts()->pluck('email')}\n";
|
||||
|
||||
|
||||
|
@ -165,6 +165,18 @@ class ACH
|
||||
$data['payment_method_id'] = GatewayType::BANK_TRANSFER;
|
||||
$data['customer'] = $this->stripe->findOrCreateCustomer();
|
||||
$data['amount'] = $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency());
|
||||
$amount = $data['total']['amount_with_fee'];
|
||||
|
||||
$invoice = Invoice::whereIn('id', $this->transformKeys(array_column($this->stripe->payment_hash->invoices(), 'invoice_id')))
|
||||
->withTrashed()
|
||||
->first();
|
||||
|
||||
if ($invoice) {
|
||||
$description = "Invoice {$invoice->number} for {$amount} for client {$this->stripe->client->present()->name()}";
|
||||
} else {
|
||||
$description = "Payment with no invoice for amount {$amount} for client {$this->stripe->client->present()->name()}";
|
||||
}
|
||||
|
||||
|
||||
$intent = false;
|
||||
|
||||
@ -176,6 +188,11 @@ class ACH
|
||||
'setup_future_usage' => 'off_session',
|
||||
'customer' => $data['customer']->id,
|
||||
'payment_method_types' => ['us_bank_account'],
|
||||
'description' => $description,
|
||||
'metadata' => [
|
||||
'payment_hash' => $this->stripe->payment_hash->hash,
|
||||
'gateway_type_id' => GatewayType::BANK_TRANSFER,
|
||||
],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ namespace App\PaymentDrivers\Stripe\Jobs;
|
||||
|
||||
use App\Jobs\Util\SystemLogger;
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\ClientGatewayToken;
|
||||
use App\Models\Company;
|
||||
use App\Models\CompanyGateway;
|
||||
use App\Models\GatewayType;
|
||||
@ -21,6 +22,7 @@ use App\Models\Payment;
|
||||
use App\Models\PaymentHash;
|
||||
use App\Models\PaymentType;
|
||||
use App\Models\SystemLog;
|
||||
use App\PaymentDrivers\Stripe\UpdatePaymentMethods;
|
||||
use App\PaymentDrivers\Stripe\Utilities;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
@ -53,7 +55,7 @@ class PaymentIntentWebhook implements ShouldQueue
|
||||
|
||||
public function handle()
|
||||
{
|
||||
|
||||
|
||||
MultiDB::findAndSetDbByCompanyKey($this->company_key);
|
||||
|
||||
$company = Company::where('company_key', $this->company_key)->first();
|
||||
@ -145,7 +147,18 @@ class PaymentIntentWebhook implements ShouldQueue
|
||||
|
||||
$this->updateCreditCardPayment($payment_hash, $client);
|
||||
}
|
||||
elseif(array_key_exists('payment_method_types', $this->stripe_request['object']) && optional($this->stripe_request['object']['charges']['data'][0]['metadata']['payment_hash']) && in_array('us_bank_account', $this->stripe_request['object']['payment_method_types']))
|
||||
{
|
||||
nlog("hash found");
|
||||
|
||||
$hash = $this->stripe_request['object']['charges']['data'][0]['metadata']['payment_hash'];
|
||||
|
||||
$payment_hash = PaymentHash::where('hash', $hash)->first();
|
||||
$invoice = Invoice::with('client')->find($payment_hash->fee_invoice_id);
|
||||
$client = $invoice->client;
|
||||
|
||||
$this->updateAchPayment($payment_hash, $client);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -161,6 +174,81 @@ class PaymentIntentWebhook implements ShouldQueue
|
||||
|
||||
}
|
||||
|
||||
private function updateAchPayment($payment_hash, $client)
|
||||
{
|
||||
$company_gateway = CompanyGateway::find($this->company_gateway_id);
|
||||
$payment_method_type = optional($this->stripe_request['object']['charges']['data'][0]['metadata'])['gateway_type_id'];
|
||||
$driver = $company_gateway->driver($client)->init()->setPaymentMethod($payment_method_type);
|
||||
|
||||
$payment_hash->data = array_merge((array) $payment_hash->data, $this->stripe_request);
|
||||
$payment_hash->save();
|
||||
$driver->setPaymentHash($payment_hash);
|
||||
|
||||
$data = [
|
||||
'payment_method' => $payment_hash->data->object->payment_method,
|
||||
'payment_type' => PaymentType::ACH,
|
||||
'amount' => $payment_hash->data->amount_with_fee,
|
||||
'transaction_reference' => $this->stripe_request['object']['charges']['data'][0]['id'],
|
||||
'gateway_type_id' => GatewayType::BANK_TRANSFER,
|
||||
];
|
||||
|
||||
$payment = $driver->createPayment($data, Payment::STATUS_COMPLETED);
|
||||
|
||||
SystemLogger::dispatch(
|
||||
['response' => $this->stripe_request, 'data' => $data],
|
||||
SystemLog::CATEGORY_GATEWAY_RESPONSE,
|
||||
SystemLog::EVENT_GATEWAY_SUCCESS,
|
||||
SystemLog::TYPE_STRIPE,
|
||||
$client,
|
||||
$client->company,
|
||||
);
|
||||
|
||||
try {
|
||||
|
||||
$customer = $driver->getCustomer($this->stripe_request['object']['charges']['data'][0]['customer']);
|
||||
$method = $driver->getStripePaymentMethod($this->stripe_request['object']['charges']['data'][0]['payment_method']);
|
||||
$payment_method = $this->stripe_request['object']['charges']['data'][0]['payment_method'];
|
||||
|
||||
$token_exists = ClientGatewayToken::where([
|
||||
'gateway_customer_reference' => $customer->id,
|
||||
'token' => $payment_method,
|
||||
'client_id' => $client->id,
|
||||
'company_id' => $client->company_id,
|
||||
])->exists();
|
||||
|
||||
/* Already exists return */
|
||||
if ($token_exists) {
|
||||
return;
|
||||
}
|
||||
|
||||
$payment_meta = new \stdClass;
|
||||
$payment_meta->brand = (string) \sprintf('%s (%s)', $method->us_bank_account['bank_name'], ctrans('texts.ach'));
|
||||
$payment_meta->last4 = (string) $method->us_bank_account['last4'];
|
||||
$payment_meta->type = GatewayType::BANK_TRANSFER;
|
||||
$payment_meta->state = 'verified';
|
||||
|
||||
$data = [
|
||||
'payment_meta' => $payment_meta,
|
||||
'token' => $payment_method,
|
||||
'payment_method_id' => GatewayType::BANK_TRANSFER,
|
||||
];
|
||||
|
||||
$additional_data = ['gateway_customer_reference' => $customer->id];
|
||||
|
||||
if ($customer->default_source === $method->id) {
|
||||
$additional_data = ['gateway_customer_reference' => $customer->id, 'is_default' => 1];
|
||||
}
|
||||
|
||||
$driver->storeGatewayToken($data, $additional_data);
|
||||
|
||||
}
|
||||
catch(\Exception $e){
|
||||
nlog("failed to import payment methods");
|
||||
nlog($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function updateCreditCardPayment($payment_hash, $client)
|
||||
{
|
||||
$company_gateway = CompanyGateway::find($this->company_gateway_id);
|
||||
|
@ -70,7 +70,7 @@ class UpdatePaymentMethods
|
||||
$this->importBankAccounts($customer, $client);
|
||||
}
|
||||
|
||||
private function importBankAccounts($customer, $client)
|
||||
public function importBankAccounts($customer, $client)
|
||||
{
|
||||
$sources = $customer->sources;
|
||||
|
||||
|
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('products', function (Blueprint $table) {
|
||||
$table->index(['product_key', 'company_id']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('products', function (Blueprint $table) {
|
||||
//
|
||||
});
|
||||
}
|
||||
};
|
@ -207,8 +207,10 @@
|
||||
gateway_response.value = JSON.stringify(paymentIntent);
|
||||
document.getElementById('server-response').submit();
|
||||
|
||||
} else if (paymentIntent.next_action?.type === "verify_with_microdeposits") {
|
||||
|
||||
} else if (paymentIntent.next_action?.type === "verify_with_microdeposits" || paymentIntent.next_action?.type === "requires_source_action") {
|
||||
errors.textContent = "You will receive an email with details on how to verify your bank account and process payment.";
|
||||
errors.hidden = false;
|
||||
document.getElementById('new-bank').style.visibility = 'hidden'
|
||||
}
|
||||
});
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user