mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-07 18:14:32 -04:00
commit
b326f73059
@ -29,7 +29,7 @@ class CloneQuoteToInvoiceFactory
|
|||||||
unset($quote_array['id']);
|
unset($quote_array['id']);
|
||||||
unset($quote_array['invitations']);
|
unset($quote_array['invitations']);
|
||||||
unset($quote_array['terms']);
|
unset($quote_array['terms']);
|
||||||
unset($quote_array['public_notes']);
|
// unset($quote_array['public_notes']);
|
||||||
unset($quote_array['footer']);
|
unset($quote_array['footer']);
|
||||||
unset($quote_array['design_id']);
|
unset($quote_array['design_id']);
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ class SubdomainController extends BaseController
|
|||||||
'preview',
|
'preview',
|
||||||
'invoiceninja',
|
'invoiceninja',
|
||||||
'cname',
|
'cname',
|
||||||
|
'sandbox',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
|
@ -38,6 +38,7 @@ use App\Repositories\BaseRepository;
|
|||||||
use App\Repositories\ClientRepository;
|
use App\Repositories\ClientRepository;
|
||||||
use App\Repositories\InvoiceRepository;
|
use App\Repositories\InvoiceRepository;
|
||||||
use App\Repositories\PaymentRepository;
|
use App\Repositories\PaymentRepository;
|
||||||
|
use App\Utils\Ninja;
|
||||||
use App\Utils\Traits\CleanLineItems;
|
use App\Utils\Traits\CleanLineItems;
|
||||||
use Illuminate\Bus\Queueable;
|
use Illuminate\Bus\Queueable;
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
@ -52,6 +53,7 @@ use League\Csv\Reader;
|
|||||||
use League\Csv\Statement;
|
use League\Csv\Statement;
|
||||||
use Symfony\Component\HttpFoundation\ParameterBag;
|
use Symfony\Component\HttpFoundation\ParameterBag;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Illuminate\Support\Facades\App;
|
||||||
|
|
||||||
class CSVImport implements ShouldQueue {
|
class CSVImport implements ShouldQueue {
|
||||||
|
|
||||||
@ -132,6 +134,10 @@ class CSVImport implements ShouldQueue {
|
|||||||
'company' => $this->company,
|
'company' => $this->company,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
App::forgetInstance('translator');
|
||||||
|
$t = app('translator');
|
||||||
|
$t->replace(Ninja::transformTranslations($this->company->settings));
|
||||||
|
|
||||||
$nmo = new NinjaMailerObject;
|
$nmo = new NinjaMailerObject;
|
||||||
$nmo->mailable = new ImportCompleted($this->company, $data);
|
$nmo->mailable = new ImportCompleted($this->company, $data);
|
||||||
$nmo->company = $this->company;
|
$nmo->company = $this->company;
|
||||||
|
@ -29,6 +29,9 @@ class PaymentObserver
|
|||||||
->where('event_id', Webhook::EVENT_CREATE_PAYMENT)
|
->where('event_id', Webhook::EVENT_CREATE_PAYMENT)
|
||||||
->exists();
|
->exists();
|
||||||
|
|
||||||
|
if($payment->invoices()->exists())
|
||||||
|
$payment->load('invoices');
|
||||||
|
|
||||||
if ($subscriptions) {
|
if ($subscriptions) {
|
||||||
WebhookHandler::dispatch(Webhook::EVENT_CREATE_PAYMENT, $payment, $payment->company);
|
WebhookHandler::dispatch(Webhook::EVENT_CREATE_PAYMENT, $payment, $payment->company);
|
||||||
}
|
}
|
||||||
|
@ -77,31 +77,36 @@ class Token
|
|||||||
$amount = array_sum(array_column($payment_hash->invoices(), 'amount')) + $payment_hash->fee_total;
|
$amount = array_sum(array_column($payment_hash->invoices(), 'amount')) + $payment_hash->fee_total;
|
||||||
$amount = round(($amount * pow(10, $this->payfast->client->currency()->precision)),0);
|
$amount = round(($amount * pow(10, $this->payfast->client->currency()->precision)),0);
|
||||||
|
|
||||||
$header =[
|
// $header =[
|
||||||
'merchant-id' => $this->payfast->company_gateway->getConfigField('merchantId'),
|
// 'merchant-id' => $this->payfast->company_gateway->getConfigField('merchantId'),
|
||||||
'timestamp' => now()->format('c'),
|
// 'timestamp' => now()->format('c'),
|
||||||
'version' => 'v1',
|
// 'version' => 'v1',
|
||||||
];
|
// ];
|
||||||
|
|
||||||
nlog($header);
|
// $body = [
|
||||||
|
// 'amount' => $amount,
|
||||||
|
// 'item_name' => 'purchase',
|
||||||
|
// 'item_description' => ctrans('texts.invoices') . ': ' . collect($payment_hash->invoices())->pluck('invoice_number'),
|
||||||
|
// // 'm_payment_id' => $payment_hash->hash,
|
||||||
|
// ];
|
||||||
|
|
||||||
$body = [
|
// $header['signature'] = md5( $this->generate_parameter_string(array_merge($header, $body), false) );
|
||||||
'amount' => $amount,
|
|
||||||
'item_name' => 'purchase',
|
|
||||||
'item_description' => ctrans('texts.invoices') . ': ' . collect($payment_hash->invoices())->pluck('invoice_number'),
|
|
||||||
'm_payment_id' => $payment_hash->hash,
|
|
||||||
'passphrase' => $this->payfast->company_gateway->getConfigField('passphrase'),
|
|
||||||
];
|
|
||||||
|
|
||||||
$header['signature'] = $this->genSig(array_merge($header, $body));
|
|
||||||
|
|
||||||
nlog($header['signature']);
|
|
||||||
nlog($header['timestamp']);
|
|
||||||
nlog($this->payfast->company_gateway->getConfigField('merchantId'));
|
|
||||||
|
|
||||||
$result = $this->send($header, $body, $cgt->token);
|
// $result = $this->send($header, $body, $cgt->token);
|
||||||
|
$api = new \PayFast\PayFastApi(
|
||||||
|
[
|
||||||
|
'merchantId' => $this->payfast->company_gateway->getConfigField('merchantId'),
|
||||||
|
'passPhrase' => $this->payfast->company_gateway->getConfigField('passPhrase'),
|
||||||
|
'testMode' => $this->payfast->company_gateway->getConfigField('testMode')
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
nlog($result);
|
$adhocArray = $api
|
||||||
|
->subscriptions
|
||||||
|
->adhoc($cgt->token, ['amount' => $amount, 'item_name' => 'purchase']);
|
||||||
|
|
||||||
|
|
||||||
|
nlog($adhocArray);
|
||||||
|
|
||||||
// /*Refactor and push to BaseDriver*/
|
// /*Refactor and push to BaseDriver*/
|
||||||
// if ($data['response'] != null && $data['response']->getMessages()->getResultCode() == 'Ok') {
|
// if ($data['response'] != null && $data['response']->getMessages()->getResultCode() == 'Ok') {
|
||||||
@ -143,6 +148,44 @@ class Token
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function generate_parameter_string( $api_data, $sort_data_before_merge = true, $skip_empty_values = true ) {
|
||||||
|
|
||||||
|
// if sorting is required the passphrase should be added in before sort.
|
||||||
|
if ( ! empty( $this->payfast->company_gateway->getConfigField('passPhrase') ) && $sort_data_before_merge )
|
||||||
|
$api_data['passphrase'] = $this->payfast->company_gateway->getConfigField('passPhrase');
|
||||||
|
|
||||||
|
if ( $sort_data_before_merge ) {
|
||||||
|
ksort( $api_data );
|
||||||
|
}
|
||||||
|
|
||||||
|
// concatenate the array key value pairs.
|
||||||
|
$parameter_string = '';
|
||||||
|
foreach ( $api_data as $key => $val ) {
|
||||||
|
|
||||||
|
if ( $skip_empty_values && empty( $val ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( 'signature' !== $key ) {
|
||||||
|
$val = urlencode( $val );
|
||||||
|
$parameter_string .= "$key=$val&";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// when not sorting passphrase should be added to the end before md5
|
||||||
|
if ( $sort_data_before_merge ) {
|
||||||
|
$parameter_string = rtrim( $parameter_string, '&' );
|
||||||
|
} elseif ( ! empty( $this->pass_phrase ) ) {
|
||||||
|
$parameter_string .= 'passphrase=' . urlencode( $this->payfast->company_gateway->getConfigField('passPhrase') );
|
||||||
|
} else {
|
||||||
|
$parameter_string = rtrim( $parameter_string, '&' );
|
||||||
|
}
|
||||||
|
|
||||||
|
nlog($parameter_string);
|
||||||
|
|
||||||
|
return $parameter_string;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private function genSig($data)
|
private function genSig($data)
|
||||||
{
|
{
|
||||||
$fields = [];
|
$fields = [];
|
||||||
|
@ -77,7 +77,7 @@ class PayFastPaymentDriver extends BaseDriver
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
} catch(Exception $e) {
|
} catch(\Exception $e) {
|
||||||
|
|
||||||
echo '##PAYFAST## There was an exception: '.$e->getMessage();
|
echo '##PAYFAST## There was an exception: '.$e->getMessage();
|
||||||
|
|
||||||
@ -161,6 +161,8 @@ class PayFastPaymentDriver extends BaseDriver
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nlog(http_build_query($fields));
|
||||||
|
|
||||||
return md5(http_build_query($fields));
|
return md5(http_build_query($fields));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ class AutoBillInvoice extends AbstractService
|
|||||||
|
|
||||||
/* Build payment hash */
|
/* Build payment hash */
|
||||||
$payment_hash = PaymentHash::create([
|
$payment_hash = PaymentHash::create([
|
||||||
'hash' => Str::random(128),
|
'hash' => Str::random(64),
|
||||||
'data' => ['invoices' => [['invoice_id' => $this->invoice->hashed_id, 'amount' => $amount]]],
|
'data' => ['invoices' => [['invoice_id' => $this->invoice->hashed_id, 'amount' => $amount]]],
|
||||||
'fee_total' => $fee,
|
'fee_total' => $fee,
|
||||||
'fee_invoice_id' => $this->invoice->id,
|
'fee_invoice_id' => $this->invoice->id,
|
||||||
|
@ -232,6 +232,9 @@ class HtmlEngine
|
|||||||
$data['$user.name'] = ['value' => $this->entity->user->present()->name(), 'label' => ctrans('texts.name')];
|
$data['$user.name'] = ['value' => $this->entity->user->present()->name(), 'label' => ctrans('texts.name')];
|
||||||
$data['$user.first_name'] = ['value' => $this->entity->user->first_name, 'label' => ctrans('texts.first_name')];
|
$data['$user.first_name'] = ['value' => $this->entity->user->first_name, 'label' => ctrans('texts.first_name')];
|
||||||
$data['$user.last_name'] = ['value' => $this->entity->user->last_name, 'label' => ctrans('texts.last_name')];
|
$data['$user.last_name'] = ['value' => $this->entity->user->last_name, 'label' => ctrans('texts.last_name')];
|
||||||
|
$data['$created_by_user'] = &$data['$user.name'];
|
||||||
|
$data['$assigned_to_user'] = ['value' => $this->entity->assigned_user ? $this->entity->assigned_user->present()->name() : '', 'label' => ctrans('texts.name')];
|
||||||
|
|
||||||
$data['$user_iban'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'company1', $this->settings->custom_value1, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'company1')];
|
$data['$user_iban'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'company1', $this->settings->custom_value1, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'company1')];
|
||||||
$data['$invoice.custom1'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'invoice1', $this->entity->custom_value1, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'invoice1')];
|
$data['$invoice.custom1'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'invoice1', $this->entity->custom_value1, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'invoice1')];
|
||||||
$data['$invoice.custom2'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'invoice2', $this->entity->custom_value2, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'invoice2')];
|
$data['$invoice.custom2'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'invoice2', $this->entity->custom_value2, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'invoice2')];
|
||||||
|
60
database/migrations/2021_09_23_100629_add_currencies.php
Normal file
60
database/migrations/2021_09_23_100629_add_currencies.php
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\Currency;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class AddCurrencies extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
|
||||||
|
Model::unguard();
|
||||||
|
|
||||||
|
|
||||||
|
$currencies = [
|
||||||
|
['id' => 105, 'name' => 'Gambia Dalasi', 'code' => 'GMD', 'symbol' => 'D', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['id' => 106, 'name' => 'Paraguayan Guarani', 'code' => 'PYG', 'symbol' => '₲', 'precision' => '0', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['id' => 107, 'name' => 'Malawi Kwacha','code' => 'MWK', 'symbol' => 'MK', 'precision' => '2','thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['id' => 108, 'name' => 'Zimbabwean Dollar', 'code' => 'ZWL', 'symbol' => 'Z$', 'precision' => '0', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['id' => 109, 'name' => 'Cambodian Riel', 'code' => 'KHR', 'symbol' => '៛', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['id' => 110, 'name' => 'Vanuatu Vatu','code' => 'VUV', 'symbol' => 'VT', 'precision' => '0','thousand_separator' => ',','decimal_separator' => '.'],
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($currencies as $currency) {
|
||||||
|
$record = Currency::whereCode($currency['code'])->first();
|
||||||
|
if ($record) {
|
||||||
|
$record->name = $currency['name'];
|
||||||
|
$record->symbol = $currency['symbol'];
|
||||||
|
$record->precision = $currency['precision'];
|
||||||
|
$record->thousand_separator = $currency['thousand_separator'];
|
||||||
|
$record->decimal_separator = $currency['decimal_separator'];
|
||||||
|
if (isset($currency['swap_currency_symbol'])) {
|
||||||
|
$record->swap_currency_symbol = $currency['swap_currency_symbol'];
|
||||||
|
}
|
||||||
|
$record->save();
|
||||||
|
} else {
|
||||||
|
Currency::create($currency);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -97,7 +97,7 @@ class PaymentLibrariesSeeder extends Seeder
|
|||||||
|
|
||||||
Gateway::query()->update(['visible' => 0]);
|
Gateway::query()->update(['visible' => 0]);
|
||||||
|
|
||||||
Gateway::whereIn('id', [1,7,15,20,39,46,55,50,57])->update(['visible' => 1]);
|
Gateway::whereIn('id', [1,7,11,15,20,39,46,55,50,57])->update(['visible' => 1]);
|
||||||
|
|
||||||
if (Ninja::isHosted()) {
|
if (Ninja::isHosted()) {
|
||||||
Gateway::whereIn('id', [20])->update(['visible' => 0]);
|
Gateway::whereIn('id', [20])->update(['visible' => 0]);
|
||||||
|
@ -77,7 +77,7 @@
|
|||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if(!empty($company->present()->website()))
|
@if(!is_null($company) && !empty($company->present()->website()))
|
||||||
<div class="mt-5 text-center">
|
<div class="mt-5 text-center">
|
||||||
<a class="button-link text-sm" href="{{ $company->present()->website() }}">
|
<a class="button-link text-sm" href="{{ $company->present()->website() }}">
|
||||||
{{ ctrans('texts.back_to', ['url' => parse_url($company->present()->website())['host'] ?? $company->present()->website() ]) }}
|
{{ ctrans('texts.back_to', ['url' => parse_url($company->present()->website())['host'] ?? $company->present()->website() ]) }}
|
||||||
|
68
tests/Unit/RelationExistsTest.php
Normal file
68
tests/Unit/RelationExistsTest.php
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://opensource.org/licenses/AAL
|
||||||
|
*/
|
||||||
|
namespace Tests\Unit;
|
||||||
|
|
||||||
|
use App\Factory\CloneQuoteToInvoiceFactory;
|
||||||
|
use App\Models\Client;
|
||||||
|
use App\Models\Credit;
|
||||||
|
use App\Models\Expense;
|
||||||
|
use App\Models\Invoice;
|
||||||
|
use App\Models\Payment;
|
||||||
|
use App\Models\Product;
|
||||||
|
use App\Models\Quote;
|
||||||
|
use App\Models\RecurringExpense;
|
||||||
|
use App\Models\RecurringInvoice;
|
||||||
|
use App\Models\Task;
|
||||||
|
use App\Models\Vendor;
|
||||||
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
|
use Tests\MockAccountData;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
class RelationExistsTest extends TestCase
|
||||||
|
{
|
||||||
|
use MockAccountData;
|
||||||
|
use DatabaseTransactions;
|
||||||
|
|
||||||
|
private $models = [
|
||||||
|
Invoice::class,
|
||||||
|
Client::class,
|
||||||
|
Expense::class,
|
||||||
|
Credit::class,
|
||||||
|
Payment::class,
|
||||||
|
RecurringInvoice::class,
|
||||||
|
RecurringExpense::class,
|
||||||
|
Product::class,
|
||||||
|
Quote::class,
|
||||||
|
Task::class,
|
||||||
|
Vendor::class,
|
||||||
|
];
|
||||||
|
|
||||||
|
public function setUp() :void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->makeTestData();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAssignedUserRelationExists()
|
||||||
|
{
|
||||||
|
|
||||||
|
foreach($this->models as $model){
|
||||||
|
|
||||||
|
$class = new $model;
|
||||||
|
|
||||||
|
$this->assertTrue(method_exists($class, 'assigned_user'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user