mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-10 21:22:58 +01:00
commit
8b399b3f64
@ -16,6 +16,9 @@ use App\Events\Invoice\InvoiceWasViewed;
|
||||
use App\Events\Misc\InvitationWasViewed;
|
||||
use App\Events\Quote\QuoteWasViewed;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Client;
|
||||
use App\Models\ClientContact;
|
||||
use App\Models\Payment;
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\Traits\MakesDates;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
@ -113,4 +116,18 @@ class InvitationController extends Controller
|
||||
public function routerForIframe(string $entity, string $client_hash, string $invitation_key)
|
||||
{
|
||||
}
|
||||
|
||||
public function paymentRouter(string $contact_key, string $payment_id)
|
||||
{
|
||||
$contact = ClientContact::where('contact_key', $contact_key)->firstOrFail();
|
||||
$payment = Payment::find($this->decodePrimaryKey($payment_id));
|
||||
|
||||
if($payment->client_id != $contact->client_id)
|
||||
abort(403, 'You are not authorized to view this resource');
|
||||
|
||||
auth()->guard('contact')->login($contact, true);
|
||||
|
||||
return redirect()->route('client.payments.show', $payment->hashed_id);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -69,9 +69,13 @@ class CompanyController extends BaseController
|
||||
*/
|
||||
public function __construct(CompanyRepository $company_repo)
|
||||
{
|
||||
|
||||
parent::__construct();
|
||||
|
||||
$this->company_repo = $company_repo;
|
||||
|
||||
$this->middleware('password_protected')->only(['destroy']);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -477,7 +481,7 @@ class CompanyController extends BaseController
|
||||
*/
|
||||
public function destroy(DestroyCompanyRequest $request, Company $company)
|
||||
{
|
||||
|
||||
|
||||
if(Ninja::isHosted() && config('ninja.ninja_default_company_id') == $company->id)
|
||||
return response()->json(['message' => 'Cannot purge this company'], 400);
|
||||
|
||||
|
@ -127,12 +127,11 @@ class EmailController extends BaseController
|
||||
|
||||
$entity_obj->invitations->each(function ($invitation) use ($data, $entity_string, $entity_obj, $template) {
|
||||
|
||||
if ($invitation->contact->send_email && $invitation->contact->email) {
|
||||
if (!$invitation->contact->trashed() && $invitation->contact->send_email && $invitation->contact->email) {
|
||||
|
||||
$entity_obj->service()->markSent()->save();
|
||||
|
||||
EmailEntity::dispatch($invitation->fresh(), $invitation->company, $template, $data);
|
||||
// ->delay(now()->addSeconds(45));
|
||||
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,8 @@ class ImportJsonController extends BaseController
|
||||
$file_location = $request->file('files')
|
||||
->storeAs(
|
||||
'migrations',
|
||||
$request->file('files')->getClientOriginalName()
|
||||
$request->file('files')->getClientOriginalName(),
|
||||
config('filesystems.default'),
|
||||
);
|
||||
|
||||
if(Ninja::isHosted())
|
||||
|
@ -25,6 +25,7 @@ use App\Utils\Ninja;
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Facades\App;
|
||||
|
||||
class MigrationController extends BaseController
|
||||
{
|
||||
@ -263,6 +264,10 @@ class MigrationController extends BaseController
|
||||
// Look for possible existing company (based on company keys).
|
||||
$existing_company = Company::whereRaw('BINARY `company_key` = ?', [$company->company_key])->first();
|
||||
|
||||
App::forgetInstance('translator');
|
||||
$t = app('translator');
|
||||
$t->replace(Ninja::transformTranslations($user->account->companies()->first()->settings));
|
||||
|
||||
if(!$existing_company && $company_count >=10) {
|
||||
|
||||
$nmo = new NinjaMailerObject;
|
||||
|
@ -213,7 +213,7 @@ class PostMarkController extends BaseController
|
||||
$request->input('MessageID')
|
||||
);
|
||||
|
||||
LightLogs::create($bounce)->batch();
|
||||
LightLogs::create($spam)->batch();
|
||||
|
||||
SystemLogger::dispatch($request->all(), SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_SPAM_COMPLAINT, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client, $this->invitation->company);
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ class UpdateAutoBilling extends Component
|
||||
|
||||
public function updateAutoBilling(): void
|
||||
{
|
||||
if ($this->invoice->auto_bill === 'optin' || $this->invoice->auto_bill === 'optout') {
|
||||
if ($this->invoice->auto_bill == 'optin' || $this->invoice->auto_bill == 'optout') {
|
||||
$this->invoice->auto_bill_enabled = !$this->invoice->auto_bill_enabled;
|
||||
$this->invoice->save();
|
||||
}
|
||||
|
@ -52,7 +52,8 @@ class PasswordProtection
|
||||
$x_api_password = base64_decode($request->header('X-API-PASSWORD-BASE64'));
|
||||
}
|
||||
|
||||
if (Cache::get(auth()->user()->hashed_id.'_'.auth()->user()->account_id.'_logged_in')) {
|
||||
// If no password supplied - then we just check if their authentication is in cache //
|
||||
if (Cache::get(auth()->user()->hashed_id.'_'.auth()->user()->account_id.'_logged_in') && !$x_api_password) {
|
||||
|
||||
Cache::put(auth()->user()->hashed_id.'_'.auth()->user()->account_id.'_logged_in', Str::random(64), $timeout);
|
||||
|
||||
|
@ -101,8 +101,8 @@ class UpdateRecurringInvoiceRequest extends Request
|
||||
$input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : [];
|
||||
}
|
||||
|
||||
if (isset($input['auto_bill'])) {
|
||||
$input['auto_bill_enabled'] = $this->setAutoBillFlag($input['auto_bill']);
|
||||
if (array_key_exists('auto_bill', $input) && isset($input['auto_bill']) && $this->setAutoBillFlag($input['auto_bill'])) {
|
||||
$input['auto_bill_enabled'] = true;
|
||||
}
|
||||
|
||||
if (array_key_exists('documents', $input)) {
|
||||
@ -123,13 +123,8 @@ class UpdateRecurringInvoiceRequest extends Request
|
||||
*/
|
||||
private function setAutoBillFlag($auto_bill) :bool
|
||||
{
|
||||
if ($auto_bill == 'always') {
|
||||
if ($auto_bill == 'always')
|
||||
return true;
|
||||
}
|
||||
|
||||
// if($auto_bill == '')
|
||||
// off / optin / optout will reset the status of this field to off to allow
|
||||
// the client to choose whether to auto_bill or not.
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ class BaseTransformer
|
||||
$number = 0;
|
||||
}
|
||||
|
||||
return Number::parseStringFloat($number);
|
||||
return Number::parseFloat($number);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -25,7 +25,7 @@ class ExpenseTransformer extends BaseTransformer {
|
||||
'date' => isset( $data['expense.date'] ) ? date( 'Y-m-d', strtotime( $data['expense.date'] ) ) : null,
|
||||
'public_notes' => $this->getString( $data, 'expense.public_notes' ),
|
||||
'private_notes' => $this->getString( $data, 'expense.private_notes' ),
|
||||
'expense_category_id' => isset( $data['expense.category'] ) ? $this->getExpenseCategoryId( $data['expense.category'] ) : null,
|
||||
'category_id' => isset( $data['expense.category'] ) ? $this->getExpenseCategoryId( $data['expense.category'] ) : null,
|
||||
'project_id' => isset( $data['expense.project'] ) ? $this->getProjectId( $data['expense.project'] ) : null,
|
||||
'payment_type_id' => isset( $data['expense.payment_type'] ) ? $this->getPaymentTypeId( $data['expense.payment_type'] ) : null,
|
||||
'payment_date' => isset( $data['expense.payment_date'] ) ? date( 'Y-m-d', strtotime( $data['expense.payment_date'] ) ) : null,
|
||||
|
@ -498,6 +498,7 @@ class CompanyExport implements ShouldQueue
|
||||
|
||||
if(Ninja::isHosted()) {
|
||||
Storage::disk(config('filesystems.default'))->put('backups/'.$file_name, file_get_contents($zip_path));
|
||||
unlink($zip_path);
|
||||
}
|
||||
|
||||
App::forgetInstance('translator');
|
||||
|
@ -224,7 +224,7 @@ class CompanyImport implements ShouldQueue
|
||||
// if(mime_content_type(Storage::path($this->file_location)) == 'text/plain')
|
||||
// return Storage::path($this->file_location);
|
||||
|
||||
$path = TempFile::filePath(Storage::get($this->file_location), basename($this->file_location));
|
||||
$path = TempFile::filePath(Storage::disk(config('filesystems.default'))->get($this->file_location), basename($this->file_location));
|
||||
|
||||
$zip = new ZipArchive();
|
||||
$archive = $zip->open($path);
|
||||
@ -235,7 +235,7 @@ class CompanyImport implements ShouldQueue
|
||||
$zip->close();
|
||||
$file_location = "{$file_path}/backup.json";
|
||||
|
||||
if (! file_exists($file_location))
|
||||
if (! file_exists($file_path))
|
||||
throw new NonExistingMigrationFile('Backup file does not exist, or is corrupted.');
|
||||
|
||||
return $file_location;
|
||||
@ -568,7 +568,7 @@ class CompanyImport implements ShouldQueue
|
||||
{
|
||||
|
||||
$this->genericImport(GroupSetting::class,
|
||||
['user_id', 'company_id', 'id', 'hashed_id',],
|
||||
['user_id', 'company_id', 'id', 'hashed_id'],
|
||||
[['users' => 'user_id']],
|
||||
'group_settings',
|
||||
'name');
|
||||
@ -580,7 +580,7 @@ class CompanyImport implements ShouldQueue
|
||||
{
|
||||
|
||||
$this->genericImport(Subscription::class,
|
||||
['user_id', 'assigned_user_id', 'company_id', 'id', 'hashed_id',],
|
||||
['user_id', 'assigned_user_id', 'company_id', 'id', 'hashed_id'],
|
||||
[['group_settings' => 'group_id'], ['users' => 'user_id'], ['users' => 'assigned_user_id']],
|
||||
'subscriptions',
|
||||
'name');
|
||||
|
@ -224,7 +224,7 @@ class NinjaMailerJob implements ShouldQueue
|
||||
return true;
|
||||
|
||||
/* On the hosted platform we set default contacts a @example.com email address - we shouldn't send emails to these types of addresses */
|
||||
if(Ninja::isHosted() && strpos($this->nmo->to_user->email, '@example.com') !== false)
|
||||
if(Ninja::isHosted() && $this->nmo->to_user && strpos($this->nmo->to_user->email, '@example.com') !== false)
|
||||
return true;
|
||||
|
||||
/* GMail users are uncapped */
|
||||
|
@ -55,8 +55,8 @@ class QuoteWorkflowSettings implements ShouldQueue
|
||||
});
|
||||
}
|
||||
|
||||
if ($this->client->getSetting('auto_archive_quote')) {
|
||||
$this->base_repository->archive($this->quote);
|
||||
}
|
||||
// if ($this->client->getSetting('auto_archive_quote')) {
|
||||
// $this->base_repository->archive($this->quote);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ class SendRecurring implements ShouldQueue
|
||||
nlog("Invoice {$invoice->number} created");
|
||||
|
||||
$invoice->invitations->each(function ($invitation) use ($invoice) {
|
||||
if ($invitation->contact && strlen($invitation->contact->email) >=1 && $invoice->client->getSetting('auto_email_invoice')) {
|
||||
if ($invitation->contact && !$invitation->contact->trashed() && strlen($invitation->contact->email) >=1 && $invoice->client->getSetting('auto_email_invoice')) {
|
||||
|
||||
try{
|
||||
EmailEntity::dispatch($invitation, $invoice->company);
|
||||
|
@ -262,8 +262,6 @@ class Import implements ShouldQueue
|
||||
/*After a migration first some basic jobs to ensure the system is up to date*/
|
||||
VersionCheck::dispatch();
|
||||
|
||||
|
||||
|
||||
// CreateCompanyPaymentTerms::dispatchNow($sp035a66, $spaa9f78);
|
||||
// CreateCompanyTaskStatuses::dispatchNow($this->company, $this->user);
|
||||
|
||||
|
@ -63,7 +63,7 @@ class SendFailedEmails implements ShouldQueue
|
||||
$invitation = $job_meta_array['entity_name']::where('key', $job_meta_array['invitation_key'])->with('contact')->first();
|
||||
|
||||
if ($invitation->invoice) {
|
||||
if ($invitation->contact->send_email && $invitation->contact->email) {
|
||||
if (!$invitation->contact->trashed() && $invitation->contact->send_email && $invitation->contact->email) {
|
||||
EmailEntity::dispatch($invitation, $invitation->company, $job_meta_array['reminder_template']);
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use ZipArchive;
|
||||
use Illuminate\Support\Facades\App;
|
||||
|
||||
class StartMigration implements ShouldQueue
|
||||
{
|
||||
@ -122,6 +123,10 @@ class StartMigration implements ShouldQueue
|
||||
$this->company->update_products = $update_product_flag;
|
||||
$this->company->save();
|
||||
|
||||
App::forgetInstance('translator');
|
||||
$t = app('translator');
|
||||
$t->replace(Ninja::transformTranslations($this->company->settings));
|
||||
|
||||
} catch (NonExistingMigrationFile | ProcessingMigrationArchiveFailed | ResourceNotAvailableForMigration | MigrationValidatorFailed | ResourceDependencyMissing | \Exception $e) {
|
||||
|
||||
$this->company->update_products = $update_product_flag;
|
||||
|
@ -55,6 +55,10 @@ class SystemLogger implements ShouldQueue
|
||||
MultiDB::setDb($this->company->db);
|
||||
|
||||
$client_id = $this->client ? $this->client->id : null;
|
||||
|
||||
if(!$this->client && !$this->company->owner())
|
||||
return;
|
||||
|
||||
$user_id = $this->client ? $this->client->user_id : $this->company->owner()->id;
|
||||
|
||||
$sl = [
|
||||
|
@ -24,6 +24,7 @@ use Illuminate\Broadcasting\InteractsWithSockets;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\App;
|
||||
|
||||
class SendVerificationNotification implements ShouldQueue
|
||||
{
|
||||
@ -53,6 +54,10 @@ class SendVerificationNotification implements ShouldQueue
|
||||
|
||||
$event->user->service()->invite($event->company);
|
||||
|
||||
App::forgetInstance('translator');
|
||||
$t = app('translator');
|
||||
$t->replace(Ninja::transformTranslations($event->company->settings));
|
||||
|
||||
$nmo = new NinjaMailerObject;
|
||||
$nmo->mailable = new UserAdded($event->company, $event->creating_user, $event->user);
|
||||
$nmo->company = $event->company;
|
||||
|
@ -132,7 +132,6 @@ class InvoiceEmailEngine extends BaseEmailEngine
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
return $this;
|
||||
|
@ -45,8 +45,8 @@ class SupportMessageSent extends Mailable
|
||||
|
||||
$log_file->seek(PHP_INT_MAX);
|
||||
$last_line = $log_file->key();
|
||||
|
||||
$lines = new LimitIterator($log_file, $last_line - 100, $last_line);
|
||||
|
||||
$log_lines = iterator_to_array($lines);
|
||||
}
|
||||
|
||||
@ -76,6 +76,7 @@ class SupportMessageSent extends Mailable
|
||||
'system_info' => $system_info,
|
||||
'laravel_log' => $log_lines,
|
||||
'logo' => $company->present()->logo(),
|
||||
'settings' => $company->settings
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use App\Jobs\Invoice\CreateUbl;
|
||||
use App\Models\Account;
|
||||
use App\Models\Client;
|
||||
use App\Models\ClientContact;
|
||||
use App\Models\User;
|
||||
@ -116,6 +118,13 @@ class TemplateEmail extends Mailable
|
||||
|
||||
}
|
||||
|
||||
if($this->invitation->invoice && $settings->ubl_email_attachment && $this->company->account->hasFeature(Account::FEATURE_DOCUMENTS)){
|
||||
|
||||
$ubl_string = CreateUbl::dispatchNow($this->invitation->invoice);
|
||||
$this->attachData($ubl_string, $this->invitation->invoice->getFileName('xml'));
|
||||
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,15 @@ class GroupSetting extends StaticModel
|
||||
'settings',
|
||||
];
|
||||
|
||||
protected $appends = [
|
||||
'hashed_id',
|
||||
];
|
||||
|
||||
public function getHashedIdAttribute()
|
||||
{
|
||||
return $this->encodePrimaryKey($this->id);
|
||||
}
|
||||
|
||||
protected $touches = [];
|
||||
|
||||
public function company()
|
||||
|
@ -84,10 +84,6 @@ class Invoice extends BaseModel
|
||||
'custom_surcharge2',
|
||||
'custom_surcharge3',
|
||||
'custom_surcharge4',
|
||||
// 'custom_surcharge_tax1',
|
||||
// 'custom_surcharge_tax2',
|
||||
// 'custom_surcharge_tax3',
|
||||
// 'custom_surcharge_tax4',
|
||||
'design_id',
|
||||
'assigned_user_id',
|
||||
'exchange_rate',
|
||||
|
@ -287,8 +287,24 @@ class Payment extends BaseModel
|
||||
event(new PaymentWasVoided($this, $this->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||
}
|
||||
|
||||
public function getLink()
|
||||
// public function getLink()
|
||||
// {
|
||||
// return route('client.payments.show', $this->hashed_id);
|
||||
// }
|
||||
|
||||
public function getLink() :string
|
||||
{
|
||||
return route('client.payments.show', $this->hashed_id);
|
||||
|
||||
if(Ninja::isHosted()){
|
||||
$domain = isset($this->company->portal_domain) ? $this->company->portal_domain : $this->company->domain();
|
||||
}
|
||||
else
|
||||
$domain = config('ninja.app_url');
|
||||
|
||||
return $domain.'/client/payment/'. $this->client->contacts()->first()->contact_key .'/' .$this->hashed_id;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -389,6 +389,7 @@ class BaseDriver extends AbstractPaymentDriver
|
||||
|
||||
$invoices->each(function ($invoice) {
|
||||
|
||||
if (!$invitation->contact->trashed() && $invitation->contact->send_email && $invitation->contact->email) {
|
||||
$invoice->service()->deletePdf();
|
||||
});
|
||||
|
||||
@ -455,7 +456,7 @@ class BaseDriver extends AbstractPaymentDriver
|
||||
|
||||
$invoices->first()->invitations->each(function ($invitation) use ($nmo){
|
||||
|
||||
if ($invitation->contact->send_email && $invitation->contact->email) {
|
||||
if (!$invitation->contact->trashed() && $invitation->contact->send_email && $invitation->contact->email) {
|
||||
|
||||
$nmo->to_user = $invitation->contact;
|
||||
NinjaMailerJob::dispatch($nmo);
|
||||
|
@ -271,4 +271,68 @@ class ACH
|
||||
$this->wepay_payment_driver->storeGatewayToken($data);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function tokenBilling($token, $payment_hash)
|
||||
{
|
||||
|
||||
$token_meta = $token->meta;
|
||||
|
||||
if(!property_exists($token_meta, 'state') || $token_meta->state != "authorized")
|
||||
return redirect()->route('client.payment_methods.verification', ['payment_method' => $token->hashed_id, 'method' => GatewayType::BANK_TRANSFER]);
|
||||
|
||||
$amount = array_sum(array_column($this->wepay_payment_driver->payment_hash->invoices(), 'amount')) + $this->wepay_payment_driver->payment_hash->fee_total;
|
||||
|
||||
$app_fee = (config('ninja.wepay.fee_cc_multiplier') * $amount) + config('ninja.wepay.fee_fixed');
|
||||
|
||||
$response = $this->wepay_payment_driver->wepay->request('checkout/create', array(
|
||||
'unique_id' => Str::random(40),
|
||||
'account_id' => $this->wepay_payment_driver->company_gateway->getConfigField('accountId'),
|
||||
'amount' => $amount,
|
||||
'currency' => $this->wepay_payment_driver->client->getCurrencyCode(),
|
||||
'short_description' => 'Goods and Services',
|
||||
'type' => 'goods',
|
||||
'fee' => [
|
||||
'fee_payer' => config('ninja.wepay.fee_payer'),
|
||||
'app_fee' => $app_fee,
|
||||
],
|
||||
'payment_method' => array(
|
||||
'type' => 'payment_bank',
|
||||
'payment_bank' => array(
|
||||
'id' => $token->token
|
||||
)
|
||||
)
|
||||
));
|
||||
|
||||
/* Merge all data and store in the payment hash*/
|
||||
$state = [
|
||||
'server_response' => $response,
|
||||
'payment_hash' => $this->wepay_payment_driver->payment_hash,
|
||||
];
|
||||
|
||||
$this->wepay_payment_driver->payment_hash->data = array_merge((array) $this->wepay_payment_driver->payment_hash->data, $state);
|
||||
$this->wepay_payment_driver->payment_hash->save();
|
||||
|
||||
if(in_array($response->state, ['authorized', 'captured'])){
|
||||
//success
|
||||
nlog("success");
|
||||
$payment_status = $response->state == 'authorized' ? Payment::STATUS_COMPLETED : Payment::STATUS_PENDING;
|
||||
|
||||
return $this->processSuccessfulPayment($response, $payment_status, GatewayType::BANK_TRANSFER, true);
|
||||
}
|
||||
|
||||
if(in_array($response->state, ['released', 'cancelled', 'failed', 'expired'])){
|
||||
//some type of failure
|
||||
nlog("failure");
|
||||
|
||||
$payment_status = $response->state == 'cancelled' ? Payment::STATUS_CANCELLED : Payment::STATUS_FAILED;
|
||||
|
||||
$this->processUnSuccessfulPayment($response, $payment_status);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -261,7 +261,8 @@ https://developer.wepay.com/api/api-calls/checkout
|
||||
|
||||
private function storePaymentMethod($response, $payment_method_id)
|
||||
{
|
||||
nlog("storing card");
|
||||
nlog("storing card");
|
||||
|
||||
$payment_meta = new \stdClass;
|
||||
$payment_meta->exp_month = (string) $response->expiration_month;
|
||||
$payment_meta->exp_year = (string) $response->expiration_year;
|
||||
@ -281,5 +282,60 @@ nlog("storing card");
|
||||
|
||||
|
||||
|
||||
public function tokenBilling($cgt, $payment_hash)
|
||||
{
|
||||
|
||||
$amount = array_sum(array_column($this->wepay_payment_driver->payment_hash->invoices(), 'amount')) + $this->wepay_payment_driver->payment_hash->fee_total;
|
||||
|
||||
|
||||
$app_fee = (config('ninja.wepay.fee_cc_multiplier') * $amount) + config('ninja.wepay.fee_fixed');
|
||||
// charge the credit card
|
||||
$response = $this->wepay_payment_driver->wepay->request('checkout/create', array(
|
||||
'unique_id' => Str::random(40),
|
||||
'account_id' => $this->wepay_payment_driver->company_gateway->getConfigField('accountId'),
|
||||
'amount' => $amount,
|
||||
'currency' => $this->wepay_payment_driver->client->getCurrencyCode(),
|
||||
'short_description' => 'Goods and services',
|
||||
'type' => 'goods',
|
||||
'fee' => [
|
||||
'fee_payer' => config('ninja.wepay.fee_payer'),
|
||||
'app_fee' => $app_fee,
|
||||
],
|
||||
'payment_method' => array(
|
||||
'type' => 'credit_card',
|
||||
'credit_card' => array(
|
||||
'id' => $cgt->token
|
||||
)
|
||||
)
|
||||
));
|
||||
|
||||
/* Merge all data and store in the payment hash*/
|
||||
$state = [
|
||||
'server_response' => $response,
|
||||
'payment_hash' => $payment_hash,
|
||||
];
|
||||
|
||||
$this->wepay_payment_driver->payment_hash->data = array_merge((array) $this->wepay_payment_driver->payment_hash->data, $state);
|
||||
$this->wepay_payment_driver->payment_hash->save();
|
||||
|
||||
|
||||
if(in_array($response->state, ['authorized', 'captured'])){
|
||||
//success
|
||||
nlog("success");
|
||||
$payment_status = $response->state == 'authorized' ? Payment::STATUS_COMPLETED : Payment::STATUS_PENDING;
|
||||
|
||||
return $this->processSuccessfulPayment($response, $payment_status, GatewayType::CREDIT_CARD, true);
|
||||
}
|
||||
|
||||
if(in_array($response->state, ['released', 'cancelled', 'failed', 'expired'])){
|
||||
//some type of failure
|
||||
nlog("failure");
|
||||
|
||||
$payment_status = $response->state == 'cancelled' ? Payment::STATUS_CANCELLED : Payment::STATUS_FAILED;
|
||||
|
||||
$this->processUnSuccessfulPayment($response, $payment_status);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ trait WePayCommon
|
||||
{
|
||||
|
||||
|
||||
private function processSuccessfulPayment($response, $payment_status, $gateway_type)
|
||||
private function processSuccessfulPayment($response, $payment_status, $gateway_type, $return_payment = false)
|
||||
{
|
||||
|
||||
if($gateway_type == GatewayType::BANK_TRANSFER)
|
||||
@ -48,6 +48,9 @@ trait WePayCommon
|
||||
$this->wepay_payment_driver->client->company,
|
||||
);
|
||||
|
||||
if($return_payment)
|
||||
return $payment;
|
||||
|
||||
return redirect()->route('client.payments.show', ['payment' => $this->wepay_payment_driver->encodePrimaryKey($payment->id)]);
|
||||
}
|
||||
|
||||
|
@ -119,14 +119,14 @@ class WePayPaymentDriver extends BaseDriver
|
||||
$contact = $client->primary_contact()->first() ? $client->primary_contact()->first() : $lient->contacts->first();
|
||||
$data['contact'] = $contact;
|
||||
|
||||
return $this->payment_method->authorizeView($data); //this is your custom implementation from here
|
||||
return $this->payment_method->authorizeView($data);
|
||||
}
|
||||
|
||||
public function authorizeResponse($request)
|
||||
{
|
||||
$this->init();
|
||||
|
||||
return $this->payment_method->authorizeResponse($request); //this is your custom implementation from here
|
||||
return $this->payment_method->authorizeResponse($request);
|
||||
}
|
||||
|
||||
public function verificationView(ClientGatewayToken $cgt)
|
||||
@ -147,19 +147,23 @@ class WePayPaymentDriver extends BaseDriver
|
||||
{
|
||||
$this->init();
|
||||
|
||||
return $this->payment_method->paymentView($data); //this is your custom implementation from here
|
||||
return $this->payment_method->paymentView($data);
|
||||
}
|
||||
|
||||
public function processPaymentResponse($request)
|
||||
{
|
||||
$this->init();
|
||||
|
||||
return $this->payment_method->paymentResponse($request); //this is your custom implementation from here
|
||||
return $this->payment_method->paymentResponse($request);
|
||||
}
|
||||
|
||||
public function tokenBilling(ClientGatewayToken $cgt, PaymentHash $payment_hash)
|
||||
{
|
||||
return $this->payment_method->yourTokenBillingImplmentation(); //this is your custom implementation from here
|
||||
$this->init();
|
||||
$this->setPaymentMethod($cgt->gateway_type_id);
|
||||
$this->setPaymentHash($payment_hash);
|
||||
|
||||
return $this->payment_method->tokenBilling($cgt, $payment_hash);
|
||||
}
|
||||
|
||||
public function processWebhookRequest(PaymentWebhookRequest $request, Payment $payment = null)
|
||||
|
@ -44,7 +44,7 @@ class SendEmail
|
||||
}
|
||||
|
||||
$this->credit->invitations->each(function ($invitation) {
|
||||
if ($invitation->contact->send_email && $invitation->contact->email) {
|
||||
if (!$invitation->contact->trashed() && $invitation->contact->send_email && $invitation->contact->email) {
|
||||
$email_builder = (new CreditEmail())->build($invitation, $this->reminder_template);
|
||||
|
||||
// EmailCredit::dispatchNow($email_builder, $invitation, $invitation->company);
|
||||
|
@ -192,6 +192,8 @@ class InvoiceService
|
||||
|
||||
public function handleCancellation()
|
||||
{
|
||||
$this->removeUnpaidGatewayFees();
|
||||
|
||||
$this->invoice = (new HandleCancellation($this->invoice))->run();
|
||||
|
||||
return $this;
|
||||
@ -199,6 +201,8 @@ class InvoiceService
|
||||
|
||||
public function markDeleted()
|
||||
{
|
||||
$this->removeUnpaidGatewayFees();
|
||||
|
||||
$this->invoice = (new MarkInvoiceDeleted($this->invoice))->run();
|
||||
|
||||
return $this;
|
||||
@ -213,6 +217,8 @@ class InvoiceService
|
||||
|
||||
public function reverseCancellation()
|
||||
{
|
||||
$this->removeUnpaidGatewayFees();
|
||||
|
||||
$this->invoice = (new HandleCancellation($this->invoice))->reverse();
|
||||
|
||||
return $this;
|
||||
@ -278,11 +284,14 @@ class InvoiceService
|
||||
|
||||
public function updateStatus()
|
||||
{
|
||||
if ((int)$this->invoice->balance == 0) {
|
||||
if($this->invoice->status_id == Invoice::STATUS_DRAFT)
|
||||
return $this;
|
||||
|
||||
// if ((int)$this->invoice->balance == 0) {
|
||||
|
||||
$this->setStatus(Invoice::STATUS_PAID)->workFlow();
|
||||
// InvoiceWorkflowSettings::dispatchNow($this->invoice);
|
||||
}
|
||||
// $this->setStatus(Invoice::STATUS_PAID)->workFlow();
|
||||
|
||||
// }
|
||||
|
||||
if ($this->invoice->balance > 0 && $this->invoice->balance < $this->invoice->amount) {
|
||||
$this->setStatus(Invoice::STATUS_PARTIAL);
|
||||
|
@ -26,6 +26,8 @@ class MarkInvoiceDeleted extends AbstractService
|
||||
|
||||
private $total_payments = 0;
|
||||
|
||||
private $balance_adjustment = 0;
|
||||
|
||||
public function __construct(Invoice $invoice)
|
||||
{
|
||||
$this->invoice = $invoice;
|
||||
@ -51,7 +53,7 @@ class MarkInvoiceDeleted extends AbstractService
|
||||
private function adjustLedger()
|
||||
{
|
||||
// $this->invoice->ledger()->updatePaymentBalance($this->adjustment_amount * -1, 'Invoice Deleted - reducing ledger balance'); //reduces the payment balance by payment totals
|
||||
$this->invoice->ledger()->updatePaymentBalance($this->invoice->balance * -1, 'Invoice Deleted - reducing ledger balance'); //reduces the payment balance by payment totals
|
||||
$this->invoice->ledger()->updatePaymentBalance($this->balance_adjustment * -1, 'Invoice Deleted - reducing ledger balance'); //reduces the payment balance by payment totals
|
||||
|
||||
return $this;
|
||||
}
|
||||
@ -65,7 +67,7 @@ class MarkInvoiceDeleted extends AbstractService
|
||||
|
||||
private function adjustBalance()
|
||||
{
|
||||
$this->invoice->client->service()->updateBalance($this->invoice->balance * -1)->save(); //reduces the client balance by the invoice amount.
|
||||
$this->invoice->client->service()->updateBalance($this->balance_adjustment * -1)->save(); //reduces the client balance by the invoice amount.
|
||||
|
||||
return $this;
|
||||
}
|
||||
@ -122,11 +124,14 @@ class MarkInvoiceDeleted extends AbstractService
|
||||
}
|
||||
|
||||
|
||||
$this->total_payments = $this->invoice->payments->sum('amount') - $this->invoice->payments->sum('refunded');;
|
||||
$this->total_payments = $this->invoice->payments->sum('amount') - $this->invoice->payments->sum('refunded');
|
||||
|
||||
$this->balance_adjustment = $this->invoice->balance;
|
||||
|
||||
//$this->total_payments = $this->invoice->payments->sum('amount - refunded');
|
||||
|
||||
nlog("adjustment amount = {$this->adjustment_amount}");
|
||||
nlog("total payments = {$this->total_payments}");
|
||||
// nlog("adjustment amount = {$this->adjustment_amount}");
|
||||
// nlog("total payments = {$this->total_payments}");
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ class SendEmail extends AbstractService
|
||||
}
|
||||
|
||||
$this->invoice->invitations->each(function ($invitation) {
|
||||
if ($invitation->contact->send_email && $invitation->contact->email) {
|
||||
if (!$invitation->contact->trashed() && $invitation->contact->send_email && $invitation->contact->email) {
|
||||
EmailEntity::dispatchNow($invitation, $invitation->company, $this->reminder_template);
|
||||
}
|
||||
});
|
||||
|
@ -81,8 +81,14 @@ class RefundPayment
|
||||
|
||||
if ($response['success'] == false) {
|
||||
$this->payment->save();
|
||||
throw new PaymentRefundFailed($response['description']);
|
||||
|
||||
if(array_key_exists('description', $response))
|
||||
throw new PaymentRefundFailed($response['description']);
|
||||
else
|
||||
throw new PaymentRefundFailed();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
$this->payment->refunded += $this->total_refund;
|
||||
|
@ -42,7 +42,7 @@ class SendEmail
|
||||
}
|
||||
|
||||
$this->quote->invitations->each(function ($invitation) {
|
||||
if ($invitation->contact->send_email && $invitation->contact->email) {
|
||||
if (!$invitation->contact->trashed() && $invitation->contact->send_email && $invitation->contact->email) {
|
||||
EmailEntity::dispatchNow($invitation, $invitation->company, $this->reminder_template);
|
||||
}
|
||||
});
|
||||
|
@ -47,8 +47,9 @@ trait Inviteable
|
||||
{
|
||||
$entity_type = Str::snake(class_basename($this->entityType()));
|
||||
|
||||
if(Ninja::isHosted())
|
||||
if(Ninja::isHosted()){
|
||||
$domain = isset($this->company->portal_domain) ? $this->company->portal_domain : $this->company->domain();
|
||||
}
|
||||
else
|
||||
$domain = config('ninja.app_url');
|
||||
|
||||
|
@ -145,4 +145,4 @@
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true
|
||||
}
|
||||
}
|
@ -372,9 +372,12 @@ CREATE TABLE `companies` (
|
||||
`expense_inclusive_taxes` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`session_timeout` int(11) NOT NULL DEFAULT '0',
|
||||
`oauth_password_required` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`invoice_task_datelog` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`invoice_task_datelog` tinyint(1) NOT NULL DEFAULT '1',
|
||||
`default_password_timeout` int(11) NOT NULL DEFAULT '30',
|
||||
`show_task_end_date` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`markdown_enabled` tinyint(1) NOT NULL DEFAULT '1',
|
||||
`use_comma_as_decimal_place` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`report_include_drafts` tinyint(1) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `companies_company_key_unique` (`company_key`),
|
||||
KEY `companies_industry_id_foreign` (`industry_id`),
|
||||
@ -1959,3 +1962,14 @@ INSERT INTO `migrations` VALUES (80,'2021_06_24_095942_payments_table_currency_n
|
||||
INSERT INTO `migrations` VALUES (81,'2021_06_24_115919_update_designs',2);
|
||||
INSERT INTO `migrations` VALUES (82,'2021_07_08_115919_update_designs',3);
|
||||
INSERT INTO `migrations` VALUES (83,'2021_07_10_085821_activate_payfast_payment_driver',3);
|
||||
INSERT INTO `migrations` VALUES (84,'2021_07_19_074503_set_invoice_task_datelog_true_in_companies_table',4);
|
||||
INSERT INTO `migrations` VALUES (85,'2021_07_20_095537_activate_paytrace_payment_driver',4);
|
||||
INSERT INTO `migrations` VALUES (86,'2021_07_21_213344_change_english_languages_tables',4);
|
||||
INSERT INTO `migrations` VALUES (87,'2021_07_21_234227_activate_eway_payment_driver',4);
|
||||
INSERT INTO `migrations` VALUES (88,'2021_08_03_115024_activate_mollie_payment_driver',4);
|
||||
INSERT INTO `migrations` VALUES (89,'2021_08_05_235942_add_zelle_payment_type',4);
|
||||
INSERT INTO `migrations` VALUES (90,'2021_08_07_222435_add_markdown_enabled_column_to_companies_table',4);
|
||||
INSERT INTO `migrations` VALUES (91,'2021_08_10_034407_add_more_languages',4);
|
||||
INSERT INTO `migrations` VALUES (92,'2021_08_18_220124_use_comma_as_decimal_place_companies_table',4);
|
||||
INSERT INTO `migrations` VALUES (93,'2021_08_24_115919_update_designs',4);
|
||||
INSERT INTO `migrations` VALUES (94,'2021_08_25_093105_report_include_drafts_in_companies_table',5);
|
||||
|
@ -1,4 +1,4 @@
|
||||
@component('email.template.admin', ['logo' => $logo ?? 'https://www.invoiceninja.com/wp-content/uploads/2015/10/logo-white-horizontal-1.png'])
|
||||
@component('email.template.admin', ['settings' => $settings, 'logo' => $logo ?? 'https://www.invoiceninja.com/wp-content/uploads/2015/10/logo-white-horizontal-1.png'])
|
||||
{{-- Body --}}
|
||||
{{ $support_message }}
|
||||
|
||||
|
@ -41,7 +41,7 @@
|
||||
</span>
|
||||
</th>
|
||||
<th class="px-6 py-3 border-b border-gray-200 bg-primary text-left text-xs leading-4 font-medium text-white uppercase tracking-wider">
|
||||
<span role="button" wire:click="sortBy('type_id')" class="cursor-pointer">
|
||||
<span role="button" wire:click="sortBy('gateway_type_id')" class="cursor-pointer">
|
||||
{{ ctrans('texts.payment_type_id') }}
|
||||
</span>
|
||||
</th>
|
||||
|
@ -47,7 +47,9 @@ Route::group(['middleware' => ['api_db', 'token_auth', 'locale'], 'prefix' => 'a
|
||||
|
||||
Route::post('companies/purge/{company}', 'MigrationController@purgeCompany')->middleware('password_protected');
|
||||
Route::post('companies/purge_save_settings/{company}', 'MigrationController@purgeCompanySaveSettings')->middleware('password_protected');
|
||||
|
||||
Route::resource('companies', 'CompanyController'); // name = (companies. index / create / show / update / destroy / edit
|
||||
|
||||
Route::put('companies/{company}/upload', 'CompanyController@upload');
|
||||
|
||||
Route::get('company_ledger', 'CompanyLedgerController@index')->name('company_ledger.index');
|
||||
|
@ -25,6 +25,8 @@ Route::get('client/key_login/{contact_key}', 'ClientPortal\ContactHashLoginContr
|
||||
Route::get('client/magic_link/{magic_link}', 'ClientPortal\ContactHashLoginController@magicLink')->name('client.contact_magic_link')->middleware(['domain_db','contact_key_login']);
|
||||
Route::get('documents/{document_hash}', 'ClientPortal\DocumentController@publicDownload')->name('documents.public_download')->middleware(['document_db']);
|
||||
Route::get('error', 'ClientPortal\ContactHashLoginController@errorPage')->name('client.error');
|
||||
Route::get('client/payment/{contact_key}/{payment_id}', 'ClientPortal\InvitationController@paymentRouter')->middleware(['domain_db','contact_key_login']);
|
||||
|
||||
|
||||
Route::group(['middleware' => ['auth:contact', 'locale', 'check_client_existence','domain_db'], 'prefix' => 'client', 'as' => 'client.'], function () {
|
||||
Route::get('dashboard', 'ClientPortal\DashboardController@index')->name('dashboard'); // name = (dashboard. index / create / show / update / destroy / edit
|
||||
@ -95,6 +97,7 @@ Route::group(['middleware' => ['invite_db'], 'prefix' => 'client', 'as' => 'clie
|
||||
Route::get('credit/{invitation_key}/download_pdf', 'CreditController@downloadPdf')->name('credit.download_invitation_key');
|
||||
Route::get('{entity}/{invitation_key}/download', 'ClientPortal\InvitationController@routerForDownload');
|
||||
Route::get('{entity}/{client_hash}/{invitation_key}', 'ClientPortal\InvitationController@routerForIframe')->name('invoice.client_hash_and_invitation_key'); //should never need this
|
||||
|
||||
});
|
||||
|
||||
Route::get('phantom/{entity}/{invitation_key}', '\App\Utils\PhantomJS\Phantom@displayInvitation')->middleware(['invite_db', 'phantom_secret'])->name('phantom_view');
|
||||
|
@ -54,11 +54,11 @@ class CancelInvoiceTest extends TestCase
|
||||
|
||||
$this->assertEquals(Invoice::STATUS_SENT, $this->invoice->status_id);
|
||||
|
||||
$this->invoice->service()->handleCancellation()->save();
|
||||
$this->invoice->fresh()->service()->handleCancellation()->save();
|
||||
|
||||
$this->assertEquals(0, $this->invoice->fresh()->balance);
|
||||
$this->assertEquals($this->client->fresh()->balance, ($client_balance - $invoice_balance));
|
||||
$this->assertNotEquals($client_balance, $this->client->fresh()->balance);
|
||||
$this->assertEquals(Invoice::STATUS_CANCELLED, $this->invoice->status_id);
|
||||
$this->assertEquals(Invoice::STATUS_CANCELLED, $this->invoice->fresh()->status_id);
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\DataMapper\CompanySettings;
|
||||
use App\Http\Middleware\PasswordProtection;
|
||||
use App\Models\Company;
|
||||
use App\Models\CompanyToken;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
@ -47,6 +48,8 @@ class CompanyTest extends TestCase
|
||||
|
||||
public function testCompanyList()
|
||||
{
|
||||
$this->withoutMiddleware(PasswordProtection::class);
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
@ -117,6 +120,7 @@ class CompanyTest extends TestCase
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
'X-API-PASSWORD' => 'ALongAndBriliantPassword',
|
||||
])->delete('/api/v1/companies/'.$this->encodePrimaryKey($company->id))
|
||||
->assertStatus(200);
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ use App\Factory\ClientFactory;
|
||||
use App\Factory\CreditFactory;
|
||||
use App\Factory\InvoiceFactory;
|
||||
use App\Helpers\Invoice\InvoiceSum;
|
||||
use App\Models\ClientContact;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Payment;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
@ -63,6 +64,14 @@ class RefundTest extends TestCase
|
||||
$client = ClientFactory::create($this->company->id, $this->user->id);
|
||||
$client->save();
|
||||
|
||||
$contact = ClientContact::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
'client_id' => $client->id,
|
||||
'company_id' => $this->company->id,
|
||||
'is_primary' => 1,
|
||||
'send_email' => true,
|
||||
]);
|
||||
|
||||
$this->invoice = InvoiceFactory::create($this->company->id, $this->user->id); //stub the company and user_id
|
||||
$this->invoice->client_id = $client->id;
|
||||
$this->invoice->status_id = Invoice::STATUS_SENT;
|
||||
@ -138,6 +147,15 @@ class RefundTest extends TestCase
|
||||
$client = ClientFactory::create($this->company->id, $this->user->id);
|
||||
$client->save();
|
||||
|
||||
$contact = ClientContact::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
'client_id' => $client->id,
|
||||
'company_id' => $this->company->id,
|
||||
'is_primary' => 1,
|
||||
'send_email' => true,
|
||||
]);
|
||||
|
||||
|
||||
$this->invoice = InvoiceFactory::create($this->company->id, $this->user->id); //stub the company and user_id
|
||||
$this->invoice->client_id = $client->id;
|
||||
$this->invoice->status_id = Invoice::STATUS_SENT;
|
||||
@ -227,6 +245,14 @@ class RefundTest extends TestCase
|
||||
$client = ClientFactory::create($this->company->id, $this->user->id);
|
||||
$client->save();
|
||||
|
||||
$contact = ClientContact::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
'client_id' => $client->id,
|
||||
'company_id' => $this->company->id,
|
||||
'is_primary' => 1,
|
||||
'send_email' => true,
|
||||
]);
|
||||
|
||||
$this->invoice = InvoiceFactory::create($this->company->id, $this->user->id); //stub the company and user_id
|
||||
$this->invoice->client_id = $client->id;
|
||||
$this->invoice->status_id = Invoice::STATUS_SENT;
|
||||
@ -303,6 +329,15 @@ class RefundTest extends TestCase
|
||||
$client = ClientFactory::create($this->company->id, $this->user->id);
|
||||
$client->save();
|
||||
|
||||
$contact = ClientContact::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
'client_id' => $client->id,
|
||||
'company_id' => $this->company->id,
|
||||
'is_primary' => 1,
|
||||
'send_email' => true,
|
||||
]);
|
||||
|
||||
|
||||
$this->invoice = InvoiceFactory::create($this->company->id, $this->user->id); //stub the company and user_id
|
||||
$this->invoice->client_id = $client->id;
|
||||
$this->invoice->status_id = Invoice::STATUS_SENT;
|
||||
@ -388,6 +423,15 @@ class RefundTest extends TestCase
|
||||
$client = ClientFactory::create($this->company->id, $this->user->id);
|
||||
$client->save();
|
||||
|
||||
$contact = ClientContact::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
'client_id' => $client->id,
|
||||
'company_id' => $this->company->id,
|
||||
'is_primary' => 1,
|
||||
'send_email' => true,
|
||||
]);
|
||||
|
||||
|
||||
$this->invoice = InvoiceFactory::create($this->company->id, $this->user->id); //stub the company and user_id
|
||||
$this->invoice->client_id = $client->id;
|
||||
$this->invoice->status_id = Invoice::STATUS_SENT;
|
||||
@ -497,6 +541,15 @@ class RefundTest extends TestCase
|
||||
$client = ClientFactory::create($this->company->id, $this->user->id);
|
||||
$client->save();
|
||||
|
||||
$contact = ClientContact::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
'client_id' => $client->id,
|
||||
'company_id' => $this->company->id,
|
||||
'is_primary' => 1,
|
||||
'send_email' => true,
|
||||
]);
|
||||
|
||||
|
||||
$this->invoice = InvoiceFactory::create($this->company->id, $this->user->id); //stub the company and user_id
|
||||
$this->invoice->client_id = $client->id;
|
||||
$this->invoice->status_id = Invoice::STATUS_SENT;
|
||||
|
@ -41,6 +41,27 @@ class NumberTest extends TestCase
|
||||
$this->assertEquals(2.15, $rounded);
|
||||
}
|
||||
|
||||
//this method proved an error! removing this method from production
|
||||
// public function testImportFloatConversion()
|
||||
// {
|
||||
|
||||
// $amount = '€7,99';
|
||||
|
||||
// $converted_amount = Number::parseStringFloat($amount);
|
||||
|
||||
// $this->assertEquals(799, $converted_amount);
|
||||
|
||||
// }
|
||||
|
||||
public function testParsingStringCurrency()
|
||||
{
|
||||
$amount = '€7,99';
|
||||
|
||||
$converted_amount = Number::parseFloat($amount);
|
||||
|
||||
$this->assertEquals(7.99, $converted_amount);
|
||||
}
|
||||
|
||||
// public function testParsingFloats()
|
||||
// {
|
||||
// Currency::all()->each(function ($currency) {
|
||||
|
Loading…
Reference in New Issue
Block a user