Merge pull request #6707 from turbo124/v5-develop

Adding currencies
This commit is contained in:
David Bomba 2021-09-24 08:52:07 +10:00 committed by GitHub
commit b326f73059
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 212 additions and 26 deletions

View File

@ -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']);

View File

@ -29,6 +29,7 @@ class SubdomainController extends BaseController
'preview', 'preview',
'invoiceninja', 'invoiceninja',
'cname', 'cname',
'sandbox',
]; ];
public function __construct() public function __construct()

View File

@ -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;

View File

@ -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);
} }

View File

@ -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 = [];

View File

@ -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));
} }

View File

@ -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,

View File

@ -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')];

View 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()
{
}
}

View File

@ -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]);

View File

@ -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() ]) }}

View 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'));
}
}
}