mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-05-24 02:14:21 -04:00
Fixes for credits
This commit is contained in:
parent
742b49c75a
commit
11e082d443
@ -29,6 +29,7 @@ class InvoiceItemSum
|
||||
use Discounter;
|
||||
use Taxer;
|
||||
|
||||
//@phpstan-ignore-next-line
|
||||
private array $eu_tax_jurisdictions = [
|
||||
'AT', // Austria
|
||||
'BE', // Belgium
|
||||
@ -170,7 +171,7 @@ class InvoiceItemSum
|
||||
private function shouldCalculateTax(): self
|
||||
{
|
||||
|
||||
if (!$this->invoice->company?->calculate_taxes || $this->invoice->company->account->isFreeHostedClient()) {
|
||||
if (!$this->invoice->company?->calculate_taxes || $this->invoice->company->account->isFreeHostedClient()) { //@phpstan-ignore-line
|
||||
$this->calc_tax = false;
|
||||
return $this;
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ class InvoiceItemSumInclusive
|
||||
use Discounter;
|
||||
use Taxer;
|
||||
|
||||
|
||||
//@phpstan-ignore-next-line
|
||||
private array $eu_tax_jurisdictions = [
|
||||
'AT', // Austria
|
||||
'BE', // Belgium
|
||||
@ -98,6 +98,7 @@ class InvoiceItemSumInclusive
|
||||
|
||||
private $total_taxes;
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
private $item;
|
||||
|
||||
private $line_items;
|
||||
@ -399,7 +400,7 @@ class InvoiceItemSumInclusive
|
||||
private function shouldCalculateTax(): self
|
||||
{
|
||||
|
||||
if (!$this->invoice->company->calculate_taxes || $this->invoice->company->account->isFreeHostedClient()) {
|
||||
if (!$this->invoice->company?->calculate_taxes || $this->invoice->company->account->isFreeHostedClient()) {//@phpstan-ignore-line
|
||||
$this->calc_tax = false;
|
||||
return $this;
|
||||
}
|
||||
|
@ -280,186 +280,172 @@ class MigrationController extends BaseController
|
||||
}
|
||||
}
|
||||
|
||||
if (app()->environment() === 'local') {
|
||||
}
|
||||
|
||||
try {
|
||||
return response()->json([
|
||||
'_id' => Str::uuid(),
|
||||
'method' => config('queue.default'),
|
||||
'started_at' => now(),
|
||||
], 200);
|
||||
} finally {
|
||||
// Controller logic here
|
||||
|
||||
foreach ($companies as $company) {
|
||||
if (! is_array($company)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$company = (array) $company;
|
||||
|
||||
$user = auth()->user();
|
||||
|
||||
$company_count = $user->account->companies()->count();
|
||||
$fresh_company = false;
|
||||
|
||||
// Look for possible existing company (based on company keys).
|
||||
$existing_company = Company::query()->whereRaw('BINARY `company_key` = ?', [$company['company_key']])->first();
|
||||
|
||||
App::forgetInstance('translator');
|
||||
$t = app('translator');
|
||||
$t->replace(Ninja::transformTranslations($user->account->companies()->first()->settings));
|
||||
App::setLocale($user->account->companies()->first()->getLocale());
|
||||
|
||||
if (! $existing_company && $company_count >= 10) {
|
||||
$nmo = new NinjaMailerObject();
|
||||
$nmo->mailable = new MaxCompanies($user->account->companies()->first());
|
||||
$nmo->company = $user->account->companies()->first();
|
||||
$nmo->settings = $user->account->companies()->first()->settings;
|
||||
$nmo->to_user = $user;
|
||||
|
||||
if(!$this->silent_migration) {
|
||||
NinjaMailerJob::dispatch($nmo, true);
|
||||
}
|
||||
|
||||
return;
|
||||
} elseif ($existing_company && $company_count > 10) {
|
||||
$nmo = new NinjaMailerObject();
|
||||
$nmo->mailable = new MaxCompanies($user->account->companies()->first());
|
||||
$nmo->company = $user->account->companies()->first();
|
||||
$nmo->settings = $user->account->companies()->first()->settings;
|
||||
$nmo->to_user = $user;
|
||||
|
||||
if(!$this->silent_migration) {
|
||||
NinjaMailerJob::dispatch($nmo, true);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$checks = [
|
||||
'existing_company' => $existing_company ? (bool) 1 : false,
|
||||
'force' => array_key_exists('force', $company) ? (bool) $company['force'] : false,
|
||||
];
|
||||
|
||||
// If there's existing company and ** no ** force is provided - skip migration.
|
||||
if ($checks['existing_company'] == true && $checks['force'] == false) {
|
||||
nlog('Migrating: Existing company without force. (CASE_01)');
|
||||
|
||||
$nmo = new NinjaMailerObject();
|
||||
$nmo->mailable = new ExistingMigration($existing_company);
|
||||
$nmo->company = $user->account->companies()->first();
|
||||
$nmo->settings = $user->account->companies()->first();
|
||||
$nmo->to_user = $user;
|
||||
|
||||
if(!$this->silent_migration) {
|
||||
NinjaMailerJob::dispatch($nmo, true);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'_id' => Str::uuid(),
|
||||
'method' => config('queue.default'),
|
||||
'started_at' => now(),
|
||||
], 200);
|
||||
}
|
||||
|
||||
// If there's existing company and force ** is provided ** - purge the company and migrate again.
|
||||
if ($checks['existing_company'] == true && $checks['force'] == true) {
|
||||
nlog('purging the existing company here');
|
||||
$this->purgeCompanyWithForceFlag($existing_company);
|
||||
|
||||
$account = auth()->user()->account;
|
||||
$fresh_company = (new ImportMigrations())->getCompany($account);
|
||||
$fresh_company->is_disabled = true;
|
||||
$fresh_company->save();
|
||||
|
||||
$account->default_company_id = $fresh_company->id;
|
||||
$account->save();
|
||||
|
||||
$fresh_company_token = new CompanyToken();
|
||||
$fresh_company_token->user_id = $user->id;
|
||||
$fresh_company_token->company_id = $fresh_company->id;
|
||||
$fresh_company_token->account_id = $account->id;
|
||||
$fresh_company_token->name = $request->token_name ?? Str::random(12);
|
||||
$fresh_company_token->token = $request->token ?? Str::random(64);
|
||||
$fresh_company_token->is_system = true;
|
||||
$fresh_company_token->save();
|
||||
|
||||
/** @var \App\Models\User $user */
|
||||
$user->companies()->attach($fresh_company->id, [
|
||||
'account_id' => $account->id,
|
||||
'is_owner' => 1,
|
||||
'is_admin' => 1,
|
||||
'is_locked' => 0,
|
||||
'notifications' => CompanySettings::notificationDefaults(),
|
||||
'permissions' => '',
|
||||
'settings' => null,
|
||||
]);
|
||||
}
|
||||
|
||||
// If there's no existing company migrate just normally.
|
||||
if ($checks['existing_company'] == false) {
|
||||
nlog('creating fresh company');
|
||||
|
||||
$account = auth()->user()->account;
|
||||
$fresh_company = (new ImportMigrations())->getCompany($account);
|
||||
|
||||
$fresh_company->is_disabled = true;
|
||||
$fresh_company->save();
|
||||
|
||||
$fresh_company_token = new CompanyToken();
|
||||
$fresh_company_token->user_id = $user->id;
|
||||
$fresh_company_token->company_id = $fresh_company->id;
|
||||
$fresh_company_token->account_id = $account->id;
|
||||
$fresh_company_token->name = $request->token_name ?? Str::random(12);
|
||||
$fresh_company_token->token = $request->token ?? Str::random(64);
|
||||
$fresh_company_token->is_system = true;
|
||||
|
||||
$fresh_company_token->save();
|
||||
|
||||
/** @var \App\Models\User $user */
|
||||
$user->companies()->attach($fresh_company->id, [
|
||||
'account_id' => $account->id,
|
||||
'is_owner' => 1,
|
||||
'is_admin' => 1,
|
||||
'is_locked' => 0,
|
||||
'notifications' => CompanySettings::notificationDefaults(),
|
||||
'permissions' => '',
|
||||
'settings' => null,
|
||||
]);
|
||||
}
|
||||
|
||||
$migration_file = $request->file($company['company_index'])
|
||||
->storeAs(
|
||||
'migrations',
|
||||
$request->file($company['company_index'])->getClientOriginalName(),
|
||||
'public'
|
||||
);
|
||||
|
||||
if (app()->environment() == 'testing') {
|
||||
nlog('environment is testing = bailing out now');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
nlog('starting migration job');
|
||||
nlog($migration_file);
|
||||
|
||||
if (Ninja::isHosted()) {
|
||||
StartMigration::dispatch($migration_file, $user, $fresh_company, $this->silent_migration)->onQueue('migration');
|
||||
} else {
|
||||
StartMigration::dispatch($migration_file, $user, $fresh_company, $this->silent_migration);
|
||||
}
|
||||
foreach ($companies as $company) {
|
||||
if (! is_array($company)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'_id' => Str::uuid(),
|
||||
'method' => config('queue.default'),
|
||||
'started_at' => now(),
|
||||
], 200);
|
||||
$company = (array) $company;
|
||||
|
||||
$user = auth()->user();
|
||||
|
||||
$company_count = $user->account->companies()->count();
|
||||
$fresh_company = false;
|
||||
|
||||
// Look for possible existing company (based on company keys).
|
||||
$existing_company = Company::query()->whereRaw('BINARY `company_key` = ?', [$company['company_key']])->first();
|
||||
|
||||
App::forgetInstance('translator');
|
||||
$t = app('translator');
|
||||
$t->replace(Ninja::transformTranslations($user->account->companies()->first()->settings));
|
||||
App::setLocale($user->account->companies()->first()->getLocale());
|
||||
|
||||
if (! $existing_company && $company_count >= 10) {
|
||||
$nmo = new NinjaMailerObject();
|
||||
$nmo->mailable = new MaxCompanies($user->account->companies()->first());
|
||||
$nmo->company = $user->account->companies()->first();
|
||||
$nmo->settings = $user->account->companies()->first()->settings;
|
||||
$nmo->to_user = $user;
|
||||
|
||||
if(!$this->silent_migration) {
|
||||
NinjaMailerJob::dispatch($nmo, true);
|
||||
}
|
||||
|
||||
return;
|
||||
} elseif ($existing_company && $company_count > 10) {
|
||||
$nmo = new NinjaMailerObject();
|
||||
$nmo->mailable = new MaxCompanies($user->account->companies()->first());
|
||||
$nmo->company = $user->account->companies()->first();
|
||||
$nmo->settings = $user->account->companies()->first()->settings;
|
||||
$nmo->to_user = $user;
|
||||
|
||||
if(!$this->silent_migration) {
|
||||
NinjaMailerJob::dispatch($nmo, true);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$checks = [
|
||||
'existing_company' => $existing_company ? (bool) 1 : false,
|
||||
'force' => array_key_exists('force', $company) ? (bool) $company['force'] : false,
|
||||
];
|
||||
|
||||
// If there's existing company and ** no ** force is provided - skip migration.
|
||||
if ($checks['existing_company'] == true && $checks['force'] == false) {
|
||||
nlog('Migrating: Existing company without force. (CASE_01)');
|
||||
|
||||
$nmo = new NinjaMailerObject();
|
||||
$nmo->mailable = new ExistingMigration($existing_company);
|
||||
$nmo->company = $user->account->companies()->first();
|
||||
$nmo->settings = $user->account->companies()->first();
|
||||
$nmo->to_user = $user;
|
||||
|
||||
if(!$this->silent_migration) {
|
||||
NinjaMailerJob::dispatch($nmo, true);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'_id' => Str::uuid(),
|
||||
'method' => config('queue.default'),
|
||||
'started_at' => now(),
|
||||
], 200);
|
||||
}
|
||||
|
||||
// If there's existing company and force ** is provided ** - purge the company and migrate again.
|
||||
if ($checks['existing_company'] == true && $checks['force'] == true) {
|
||||
nlog('purging the existing company here');
|
||||
$this->purgeCompanyWithForceFlag($existing_company);
|
||||
|
||||
$account = auth()->user()->account;
|
||||
$fresh_company = (new ImportMigrations())->getCompany($account);
|
||||
$fresh_company->is_disabled = true;
|
||||
$fresh_company->save();
|
||||
|
||||
$account->default_company_id = $fresh_company->id;
|
||||
$account->save();
|
||||
|
||||
$fresh_company_token = new CompanyToken();
|
||||
$fresh_company_token->user_id = $user->id;
|
||||
$fresh_company_token->company_id = $fresh_company->id;
|
||||
$fresh_company_token->account_id = $account->id;
|
||||
$fresh_company_token->name = $request->token_name ?? Str::random(12);
|
||||
$fresh_company_token->token = $request->token ?? Str::random(64);
|
||||
$fresh_company_token->is_system = true;
|
||||
$fresh_company_token->save();
|
||||
|
||||
/** @var \App\Models\User $user */
|
||||
$user->companies()->attach($fresh_company->id, [
|
||||
'account_id' => $account->id,
|
||||
'is_owner' => 1,
|
||||
'is_admin' => 1,
|
||||
'is_locked' => 0,
|
||||
'notifications' => CompanySettings::notificationDefaults(),
|
||||
'permissions' => '',
|
||||
'settings' => null,
|
||||
]);
|
||||
}
|
||||
|
||||
// If there's no existing company migrate just normally.
|
||||
if ($checks['existing_company'] == false) {
|
||||
nlog('creating fresh company');
|
||||
|
||||
$account = auth()->user()->account;
|
||||
$fresh_company = (new ImportMigrations())->getCompany($account);
|
||||
|
||||
$fresh_company->is_disabled = true;
|
||||
$fresh_company->save();
|
||||
|
||||
$fresh_company_token = new CompanyToken();
|
||||
$fresh_company_token->user_id = $user->id;
|
||||
$fresh_company_token->company_id = $fresh_company->id;
|
||||
$fresh_company_token->account_id = $account->id;
|
||||
$fresh_company_token->name = $request->token_name ?? Str::random(12);
|
||||
$fresh_company_token->token = $request->token ?? Str::random(64);
|
||||
$fresh_company_token->is_system = true;
|
||||
|
||||
$fresh_company_token->save();
|
||||
|
||||
/** @var \App\Models\User $user */
|
||||
$user->companies()->attach($fresh_company->id, [
|
||||
'account_id' => $account->id,
|
||||
'is_owner' => 1,
|
||||
'is_admin' => 1,
|
||||
'is_locked' => 0,
|
||||
'notifications' => CompanySettings::notificationDefaults(),
|
||||
'permissions' => '',
|
||||
'settings' => null,
|
||||
]);
|
||||
}
|
||||
|
||||
$migration_file = $request->file($company['company_index'])
|
||||
->storeAs(
|
||||
'migrations',
|
||||
$request->file($company['company_index'])->getClientOriginalName(),
|
||||
'public'
|
||||
);
|
||||
|
||||
if (app()->environment() == 'testing') {
|
||||
nlog('environment is testing = bailing out now');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
nlog('starting migration job');
|
||||
nlog($migration_file);
|
||||
|
||||
if (Ninja::isHosted()) {
|
||||
StartMigration::dispatch($migration_file, $user, $fresh_company, $this->silent_migration)->onQueue('migration');
|
||||
} else {
|
||||
StartMigration::dispatch($migration_file, $user, $fresh_company, $this->silent_migration);
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'_id' => Str::uuid(),
|
||||
'method' => config('queue.default'),
|
||||
'started_at' => now(),
|
||||
], 200);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -22,8 +22,6 @@ use Illuminate\Support\Str;
|
||||
|
||||
class OneTimeTokenController extends BaseController
|
||||
{
|
||||
private $contexts = [
|
||||
];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -19,7 +19,6 @@ use Illuminate\Http\Request;
|
||||
*/
|
||||
class PostMarkController extends BaseController
|
||||
{
|
||||
private $invitation;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -234,24 +234,6 @@ class SetupController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
private function testPhantom()
|
||||
{
|
||||
try {
|
||||
$key = config('ninja.phantomjs_key');
|
||||
$url = 'https://www.invoiceninja.org/';
|
||||
|
||||
$phantom_url = "https://phantomjscloud.com/api/browser/v2/{$key}/?request=%7Burl:%22{$url}%22,renderType:%22pdf%22%7D";
|
||||
$pdf = CurlUtils::get($phantom_url);
|
||||
|
||||
Storage::disk(config('filesystems.default'))->put('test.pdf', $pdf);
|
||||
Storage::disk('local')->put('test.pdf', $pdf);
|
||||
|
||||
return response(['url' => Storage::disk('local')->url('test.pdf')], 200);
|
||||
} catch (Exception $e) {
|
||||
return response([], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function clearCompiledCache()
|
||||
{
|
||||
$cacheCompiled = base_path('bootstrap/cache/compiled.php');
|
||||
|
@ -277,7 +277,7 @@ class InvoiceTransformer extends BaseTransformer
|
||||
if($key == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/** @var array $row */
|
||||
if(is_array($row[5])) {
|
||||
$csv = str_getcsv($row[5][0], ";");
|
||||
$row[5] = array_combine(explode(",", $csv[0]), explode(",", $csv[1]));
|
||||
|
@ -40,7 +40,7 @@ class CreateRawPdf
|
||||
|
||||
public Invoice | Credit | Quote | RecurringInvoice | PurchaseOrder $entity;
|
||||
|
||||
public $company;
|
||||
public \App\Models\Company $company;
|
||||
|
||||
public $contact;
|
||||
|
||||
@ -55,6 +55,7 @@ class CreateRawPdf
|
||||
{
|
||||
|
||||
$this->invitation = $invitation;
|
||||
$this->company = $invitation->company;
|
||||
|
||||
if ($invitation instanceof InvoiceInvitation) {
|
||||
$this->entity = $invitation->invoice;
|
||||
@ -115,7 +116,14 @@ class CreateRawPdf
|
||||
}
|
||||
if ($this->entity_string == "invoice" && $this->entity->client->getSetting("merge_e_invoice_to_pdf")) {
|
||||
$pdf = (new MergeEDocument($this->entity, $pdf))->handle();
|
||||
}
|
||||
|
||||
$merge_docs = $this->entity->client ? $this->entity->client->getSetting('embed_documents') : $this->company->getSetting('embed_documents');
|
||||
|
||||
if($merge_docs && ($this->entity->documents()->where('is_public', true)->count() > 0 || $this->company->documents()->where('is_public', true)->count() > 0)) {
|
||||
$pdf = $this->entity->documentMerge($pdf);
|
||||
}
|
||||
|
||||
return $pdf;
|
||||
}
|
||||
|
||||
|
@ -192,7 +192,7 @@ class CreateUbl implements ShouldQueue
|
||||
/**
|
||||
* @param $item
|
||||
* @param $invoice_total
|
||||
* @return float|int
|
||||
* @return float
|
||||
*/
|
||||
private function getItemTaxable($item, $invoice_total)
|
||||
{
|
||||
|
@ -60,7 +60,7 @@ use Laracasts\Presenter\PresentableTrait;
|
||||
* @property bool $is_deleted
|
||||
* @property string|null $last_login
|
||||
* @property string|null $signature
|
||||
* @property string $password
|
||||
* @property string|null $password
|
||||
* @property string $language_id
|
||||
* @property string|null $remember_token
|
||||
* @property string|null $custom_value1
|
||||
|
@ -53,7 +53,7 @@ class CreditCard
|
||||
* Credit card payment page.
|
||||
*
|
||||
* @param array $data
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
* @return array
|
||||
*/
|
||||
|
||||
private function threeDParameters(array $data)
|
||||
|
@ -307,7 +307,7 @@ class PayPalWebhook implements ShouldQueue
|
||||
|
||||
});
|
||||
|
||||
return $gateway ?? false;
|
||||
return $gateway ?? null;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
@ -284,6 +284,10 @@ class PayPalPPCPPaymentDriver extends PayPalBasePaymentDriver
|
||||
|
||||
$r = $this->gatewayRequest('/v2/checkout/orders', 'post', $order);
|
||||
|
||||
if(!isset($r->json()['id'])) {
|
||||
$this->handleProcessingFailure($r->json());
|
||||
}
|
||||
|
||||
$this->payment_hash->withData("orderID", $r->json()['id']);
|
||||
|
||||
return $r->json()['id'];
|
||||
|
@ -59,7 +59,7 @@ class PaymentRepository extends BaseRepository
|
||||
* @param Payment $payment The $payment entity
|
||||
* @return Payment The updated/created payment object
|
||||
*/
|
||||
private function applyPayment(array $data, Payment $payment): ?Payment
|
||||
private function applyPayment(array $data, Payment $payment): Payment
|
||||
{
|
||||
$is_existing_payment = true;
|
||||
$client = false;
|
||||
|
@ -219,27 +219,6 @@ class CreditService
|
||||
|
||||
public function deletePdf()
|
||||
{
|
||||
$this->credit->invitations->each(function ($invitation) {
|
||||
// (new UnlinkFile(config('filesystems.default'), $this->credit->client->credit_filepath($invitation).$this->credit->numberFormatter().'.pdf'))->handle();
|
||||
|
||||
//30-06-2023
|
||||
try {
|
||||
// if (Storage::disk(config('filesystems.default'))->exists($this->invoice->client->invoice_filepath($invitation).$this->invoice->numberFormatter().'.pdf')) {
|
||||
Storage::disk(config('filesystems.default'))->delete($this->credit->client->credit_filepath($invitation).$this->credit->numberFormatter().'.pdf');
|
||||
// }
|
||||
|
||||
// if (Ninja::isHosted() && Storage::disk('public')->exists($this->invoice->client->invoice_filepath($invitation).$this->invoice->numberFormatter().'.pdf')) {
|
||||
if (Ninja::isHosted()) {
|
||||
Storage::disk('public')->delete($this->credit->client->credit_filepath($invitation).$this->credit->numberFormatter().'.pdf');
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
nlog($e->getMessage());
|
||||
}
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -273,11 +252,14 @@ class CreditService
|
||||
|
||||
public function deleteCredit()
|
||||
{
|
||||
$paid_to_date = $this->credit->invoice_id ? $this->credit->balance : 0;
|
||||
|
||||
$this->credit
|
||||
->client
|
||||
->service()
|
||||
->adjustCreditBalance($this->credit->balance * -1)
|
||||
->save();
|
||||
->client
|
||||
->service()
|
||||
->updatePaidToDate($paid_to_date)
|
||||
->adjustCreditBalance($this->credit->balance * -1)
|
||||
->save();
|
||||
|
||||
return $this;
|
||||
}
|
||||
@ -285,9 +267,13 @@ class CreditService
|
||||
|
||||
public function restoreCredit()
|
||||
{
|
||||
|
||||
$paid_to_date = $this->credit->invoice_id ? $this->credit->balance : 0;
|
||||
|
||||
$this->credit
|
||||
->client
|
||||
->service()
|
||||
->updatePaidToDate($paid_to_date * -1)
|
||||
->adjustCreditBalance($this->credit->balance)
|
||||
->save();
|
||||
|
||||
|
@ -405,7 +405,7 @@ class RoEInvoice extends AbstractService
|
||||
/**
|
||||
* @param $item
|
||||
* @param $invoice_total
|
||||
* @return float|int
|
||||
* @return float
|
||||
*/
|
||||
private function getItemTaxable($item, $invoice_total)
|
||||
{
|
||||
|
@ -406,7 +406,7 @@ class EmailDefaults
|
||||
* @param string $markdown The body to convert
|
||||
* @return string The parsed markdown response
|
||||
*/
|
||||
private function parseMarkdownToHtml(string $markdown): ?string
|
||||
private function parseMarkdownToHtml(string $markdown): string
|
||||
{
|
||||
$converter = new CommonMarkConverter([
|
||||
'allow_unsafe_links' => false,
|
||||
|
@ -110,8 +110,6 @@ trait CleanLineItems
|
||||
$total += ($item['cost'] * $item['quantity']);
|
||||
}
|
||||
|
||||
nlog($total);
|
||||
|
||||
return $total;
|
||||
}
|
||||
}
|
||||
|
@ -43,6 +43,102 @@ class CreditTest extends TestCase
|
||||
$this->makeTestData();
|
||||
}
|
||||
|
||||
public function testPaidToDateAdjustments()
|
||||
{
|
||||
|
||||
$c = Client::factory()->create([
|
||||
'company_id' => $this->company->id,
|
||||
'user_id' => $this->user->id,
|
||||
'balance' => 0,
|
||||
]);
|
||||
|
||||
$ii = new InvoiceItem();
|
||||
$ii->cost = 100;
|
||||
$ii->quantity = 1;
|
||||
$ii->product_key = 'xx';
|
||||
$ii->notes = 'yy';
|
||||
|
||||
$i = \App\Models\Invoice::factory()->create([
|
||||
'company_id' => $this->company->id,
|
||||
'user_id' => $this->user->id,
|
||||
'client_id' => $c->id,
|
||||
'tax_name1' => '',
|
||||
'tax_name2' => '',
|
||||
'tax_name3' => '',
|
||||
'tax_rate1' => 0,
|
||||
'tax_rate2' => 0,
|
||||
'tax_rate3' => 0,
|
||||
'discount' => 0,
|
||||
'line_items' => [
|
||||
$ii
|
||||
],
|
||||
'status_id' => 1,
|
||||
]);
|
||||
|
||||
$i = $i->calc()->getInvoice();
|
||||
|
||||
$this->assertEquals(0, $i->balance);
|
||||
$this->assertEquals(100, $i->amount);
|
||||
|
||||
$i->service()->markSent()->save();
|
||||
|
||||
$this->assertEquals(100, $i->balance);
|
||||
|
||||
$i->service()->markPaid()->save();
|
||||
$i = $i->fresh();
|
||||
$c = $c->fresh();
|
||||
|
||||
$this->assertEquals(0, $i->balance);
|
||||
$this->assertEquals(0, $c->balance);
|
||||
|
||||
$this->assertEquals(100, $c->paid_to_date);
|
||||
|
||||
$i->service()->handleReversal()->save();
|
||||
|
||||
|
||||
$data = $i->toArray();
|
||||
$data['invoice_id'] = $i->hashed_id;
|
||||
$data['user_id'] = $this->encodePrimaryKey($i->user_id);
|
||||
$data['client_id'] = $this->encodePrimaryKey($i->client_id);
|
||||
$data['status_id'] = 1;
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->postJson("/api/v1/credits?mark_sent=true", $data);
|
||||
|
||||
$response->assertStatus(200);
|
||||
$arr = $response->json();
|
||||
|
||||
$cr_id = $arr['data']['id'];
|
||||
|
||||
$i = $i->fresh();
|
||||
$c = $c->fresh();
|
||||
|
||||
$credit = $i->credits()->first();
|
||||
|
||||
$this->assertNotNull($credit);
|
||||
|
||||
$this->assertEquals(0, $i->balance);
|
||||
$this->assertEquals(100, $c->credit_balance);
|
||||
$this->assertEquals(0, $c->paid_to_date);
|
||||
|
||||
$credit->service()->deleteCredit()->save();
|
||||
|
||||
$c = $c->fresh();
|
||||
|
||||
$this->assertEquals(100, $c->paid_to_date);
|
||||
$this->assertEquals(0, $c->credit_balance);
|
||||
|
||||
$credit->service()->restoreCredit()->save();
|
||||
|
||||
$c = $c->fresh();
|
||||
|
||||
$this->assertEquals(0, $c->paid_to_date);
|
||||
$this->assertEquals(100, $c->credit_balance);
|
||||
|
||||
}
|
||||
|
||||
public function testCreditPaymentsPaidToDates()
|
||||
{
|
||||
$c = Client::factory()->create([
|
||||
|
Loading…
x
Reference in New Issue
Block a user