Merge pull request #8672 from turbo124/v5-develop

Fixes for reminders - timezone offsets
This commit is contained in:
David Bomba 2023-07-27 17:36:15 +10:00 committed by GitHub
commit 44bf2d851e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 335 additions and 256 deletions

View File

@ -454,7 +454,7 @@ class BaseExport
private function resolveTaskKey($column, $entity, $transformer)
{
nlog("searching for {$column}");
// nlog("searching for {$column}");
$transformed_entity = $transformer->transform($entity);
@ -499,7 +499,7 @@ class BaseExport
if(array_key_exists($column, $transformed_entity))
return $transformed_entity[$column];
nlog("export: Could not resolve vendor key: {$column}");
// nlog("export: Could not resolve vendor key: {$column}");
return '';
@ -547,7 +547,7 @@ class BaseExport
if(array_key_exists($column, $transformed_client))
return $transformed_client[$column];
nlog("export: Could not resolve client key: {$column}");
// nlog("export: Could not resolve client key: {$column}");
return '';
@ -555,7 +555,7 @@ class BaseExport
private function resolvePurchaseOrderKey($column, $entity, $transformer)
{
nlog("searching for {$column}");
// nlog("searching for {$column}");
$transformed_entity = $transformer->transform($entity);
@ -567,7 +567,7 @@ class BaseExport
private function resolveQuoteKey($column, $entity, $transformer)
{
nlog("searching for {$column}");
// nlog("searching for {$column}");
$transformed_entity = $transformer->transform($entity);
@ -581,7 +581,7 @@ class BaseExport
private function resolveInvoiceKey($column, $entity, $transformer)
{
nlog("searching for {$column}");
// nlog("searching for {$column}");
$transformed_invoice = false;
if($transformer instanceof PaymentTransformer) {
@ -643,24 +643,24 @@ class BaseExport
return $transformed_payment[$column];
}
nlog("export: Could not resolve payment key: {$column}");
// nlog("export: Could not resolve payment key: {$column}");
return '';
}
if($column == 'amount')
return $entity->payments()->exists() ? Number::formatMoney($entity->payments()->sum('paymentables.amount'), $entity->company) : ctrans('texts.unpaid');
return $entity->payments()->exists() ? $entity->payments()->sum('paymentables.amount') : ctrans('texts.unpaid');
if($column == 'refunded') {
return $entity->payments()->exists() ? Number::formatMoney($entity->payments()->sum('paymentables.refunded'), $entity->company) : 0;
return $entity->payments()->exists() ? $entity->payments()->sum('paymentables.refunded') : 0;
}
if($column == 'applied') {
$refunded = $entity->payments()->sum('paymentables.refunded');
$amount = $entity->payments()->sum('paymentables.amount');
return $entity->payments()->exists() ? Number::formatMoney(($amount - $refunded), $entity->company) : 0;
return $entity->payments()->exists() ? ($amount - $refunded) : 0;
}
$payment = $entity->payments()->first();

View File

@ -951,6 +951,9 @@ class BaseController extends Controller
if ($this->entity_type == BankIntegration::class && !$user->isSuperUser() && $user->hasIntersectPermissions(['create_bank_transaction','edit_bank_transaction','view_bank_transaction'])) {
$query->exclude(["balance"]);
} //allows us to selective display bank integrations back to the user if they can view / create bank transactions but without the bank balance being present in the response
elseif($this->entity_type == TaxRate::class && $user->hasIntersectPermissions(['create_invoice','edit_invoice','create_quote','edit_quote','create_purchase_order','edit_purchase_order'])){
// need to show tax rates if the user has the ability to create documents.
}
else {
$query->where('user_id', '=', $user->id);
}
@ -980,9 +983,6 @@ class BaseController extends Controller
$resource = new Collection($query, $transformer, $this->entity_type);
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
}
// else {
// $resource = new Collection($query, $transformer, $this->entity_type);
// }
return $this->response($this->manager->createData($resource)->toArray());
}

View File

@ -49,7 +49,7 @@ class ExpenseController extends BaseController
protected $entity_transformer = ExpenseTransformer::class;
/**
* @var ExpensRepository
* @var ExpenseRepository
*/
protected $expense_repo;
@ -72,7 +72,7 @@ class ExpenseController extends BaseController
* summary="Gets a list of expenses",
* description="Lists expenses, search and filters allow fine grained lists to be generated.
Query parameters can be added to performed more fine grained filtering of the expenses, these are handled by the ExpenseFilters class which defines the methods available",
* Query parameters can be added to performed more fine grained filtering of the expenses, these are handled by the ExpenseFilters class which defines the methods available",
* @OA\Parameter(ref="#/components/parameters/X-API-TOKEN"),
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
* @OA\Parameter(ref="#/components/parameters/include"),

View File

@ -11,13 +11,13 @@
namespace App\Http\Controllers;
use App\Models\User;
use Twilio\Rest\Client;
use App\Libraries\MultiDB;
use App\Http\Requests\Twilio\Confirm2faRequest;
use App\Http\Requests\Twilio\ConfirmSmsRequest;
use App\Http\Requests\Twilio\Generate2faRequest;
use App\Http\Requests\Twilio\GenerateSmsRequest;
use App\Libraries\MultiDB;
use App\Models\User;
use Twilio\Rest\Client;
class TwilioController extends BaseController
{
@ -29,11 +29,14 @@ class TwilioController extends BaseController
/**
* Display a listing of the resource.
*
* @return void
* @return \Illuminate\Http\JsonResponse;
*/
public function generate(GenerateSmsRequest $request)
{
$account = auth()->user()->company()->account;
/** @var \App\Models\User $user */
$user = auth()->user();
$account = $user->company()->account;
if (MultiDB::hasPhoneNumber($request->phone)) {
return response()->json(['message' => 'This phone number has already been verified with another account'], 400);
@ -65,11 +68,14 @@ class TwilioController extends BaseController
/**
* Show the form for creating a new resource.
*
* @return void
* @return \Illuminate\Http\JsonResponse;
*/
public function confirm(ConfirmSmsRequest $request)
{
$account = auth()->user()->company()->account;
/** @var \App\Models\User $user */
$user = auth()->user();
$account = $user->company()->account;
$sid = config('ninja.twilio_account_sid');
$token = config('ninja.twilio_auth_token');
@ -90,8 +96,9 @@ class TwilioController extends BaseController
$account->account_sms_verified = true;
$account->save();
//on confirmation we set the users phone number.
/** @var \App\Models\User $user */
$user = auth()->user();
$user->phone = $account->account_sms_verification_number;
$user->verified_phone_number = true;
$user->save();
@ -102,7 +109,12 @@ class TwilioController extends BaseController
return response()->json(['message' => 'SMS not verified'], 400);
}
/**
* generate2faResetCode
*
* @return \Illuminate\Http\JsonResponse;
*/
public function generate2faResetCode(Generate2faRequest $request)
{
$user = User::where('email', $request->email)->first();
@ -131,7 +143,13 @@ class TwilioController extends BaseController
return response()->json(['message' => 'Code sent.'], 200);
}
/**
* confirm2faResetCode
*
* @param Confirm2faRequest $request
* @return \Illuminate\Http\JsonResponse;
*/
public function confirm2faResetCode(Confirm2faRequest $request)
{
$user = User::where('email', $request->email)->first();
@ -171,16 +189,16 @@ class TwilioController extends BaseController
return response()->json(['message' => 'SMS not verified.'], 400);
}
public function validatePhoneNumber()
{
$sid = config('ninja.twilio_account_sid');
$token = config('ninja.twilio_auth_token');
// public function validatePhoneNumber()
// {
// $sid = config('ninja.twilio_account_sid');
// $token = config('ninja.twilio_auth_token');
$twilio = new Client($sid, $token);
// $twilio = new Client($sid, $token);
$phone_number = $twilio->lookups->v1->phoneNumbers("0417918829")
->fetch(["countryCode" => "AU"]);
// $phone_number = $twilio->lookups->v1->phoneNumbers("0417918829")
// ->fetch(["countryCode" => "AU"]);
print($phone_number);
}
// print($phone_number);
// }
}

View File

@ -80,6 +80,10 @@ class StoreRecurringInvoiceRequest extends Request
$input['due_date_days'] = 'terms';
}
if(!isset($input['next_send_date']) || $input['next_send_date'] == '') {
$input['next_send_date'] = now()->format('Y-m-d');
}
if (array_key_exists('next_send_date', $input) && is_string($input['next_send_date'])) {
$input['next_send_date_client'] = $input['next_send_date'];
}

View File

@ -74,6 +74,10 @@ class UpdateRecurringInvoiceRequest extends Request
$input['due_date_days'] = 'terms';
}
if(!isset($input['next_send_date']) || $input['next_send_date'] == '') {
$input['next_send_date'] = now()->format('Y-m-d');
}
if (array_key_exists('next_send_date', $input) && is_string($input['next_send_date'])) {
$input['next_send_date_client'] = $input['next_send_date'];
}

View File

@ -125,7 +125,7 @@ class ReminderJob implements ShouldQueue
}
$reminder_template = $invoice->calculateTemplate('invoice');
// nlog("reminder template = {$reminder_template}");
nlog("reminder template = {$reminder_template}");
$invoice->service()->touchReminder($reminder_template)->save();
$fees = $this->calcLateFee($invoice, $reminder_template);
@ -139,7 +139,7 @@ class ReminderJob implements ShouldQueue
if ($reminder_template == 'endless_reminder') {
$enabled_reminder = 'enable_reminder_endless';
}
if (in_array($reminder_template, ['reminder1', 'reminder2', 'reminder3', 'reminder_endless', 'endless_reminder']) &&
$invoice->client->getSetting($enabled_reminder) &&
$invoice->client->getSetting('send_reminders') &&

View File

@ -94,42 +94,6 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @method static \Illuminate\Database\Eloquent\Builder|Payment onlyTrashed()
* @method static \Illuminate\Database\Eloquent\Builder|Payment query()
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel scope()
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereAmount($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereApplied($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereAssignedUserId($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereClientContactId($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereClientId($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereCompanyGatewayId($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereCompanyId($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereCurrencyId($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereCustomValue1($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereCustomValue2($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereCustomValue3($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereCustomValue4($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereDate($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereDeletedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereExchangeCurrencyId($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereExchangeRate($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereGatewayTypeId($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereIdempotencyKey($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereInvitationId($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereIsDeleted($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereIsManual($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereMeta($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereNumber($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment wherePayerId($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment wherePrivateNotes($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereProjectId($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereRefunded($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereStatusId($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereTransactionId($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereTransactionReference($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereTypeId($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereUpdatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereUserId($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment whereVendorId($value)
* @method static \Illuminate\Database\Eloquent\Builder|Payment withTrashed()
* @method static \Illuminate\Database\Eloquent\Builder|Payment withoutTrashed()
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyLedger> $company_ledger
@ -137,61 +101,6 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Paymentable> $paymentables
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyLedger> $company_ledger
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Credit> $credits
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Paymentable> $paymentables
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyLedger> $company_ledger
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Credit> $credits
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Paymentable> $paymentables
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyLedger> $company_ledger
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Credit> $credits
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Paymentable> $paymentables
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyLedger> $company_ledger
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Credit> $credits
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Paymentable> $paymentables
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyLedger> $company_ledger
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Credit> $credits
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Paymentable> $paymentables
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyLedger> $company_ledger
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Credit> $credits
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Paymentable> $paymentables
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyLedger> $company_ledger
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Credit> $credits
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Paymentable> $paymentables
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyLedger> $company_ledger
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Credit> $credits
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Paymentable> $paymentables
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyLedger> $company_ledger
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Credit> $credits
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Paymentable> $paymentables
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyLedger> $company_ledger
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Credit> $credits
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Paymentable> $paymentables
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyLedger> $company_ledger
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Credit> $credits
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Paymentable> $paymentables
* @mixin \Eloquent
*/
class Payment extends BaseModel

View File

@ -114,67 +114,6 @@ use Laracasts\Presenter\PresentableTrait;
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice onlyTrashed()
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice query()
* @method static \Illuminate\Database\Eloquent\Builder|BaseModel scope()
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereAmount($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereAssignedUserId($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereAutoBill($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereAutoBillEnabled($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereBackup($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereBalance($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereClientId($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereCompanyId($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereCustomSurcharge1($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereCustomSurcharge2($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereCustomSurcharge3($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereCustomSurcharge4($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereCustomSurchargeTax1($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereCustomSurchargeTax2($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereCustomSurchargeTax3($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereCustomSurchargeTax4($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereCustomValue1($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereCustomValue2($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereCustomValue3($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereCustomValue4($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereDate($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereDeletedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereDesignId($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereDiscount($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereDueDate($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereDueDateDays($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereExchangeRate($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereFooter($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereFrequencyId($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereIsAmountDiscount($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereIsDeleted($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereLastSentDate($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereLastViewed($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereLineItems($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereNextSendDate($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereNextSendDateClient($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereNumber($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice wherePaidToDate($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice wherePartial($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice wherePartialDueDate($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice wherePoNumber($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice wherePrivateNotes($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereProjectId($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice wherePublicNotes($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereRemainingCycles($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereStatusId($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereSubscriptionId($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereTaxName1($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereTaxName2($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereTaxName3($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereTaxRate1($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereTaxRate2($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereTaxRate3($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereTerms($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereTotalTaxes($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereUpdatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereUserId($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereUsesInclusiveTaxes($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereVendorId($value)
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice withTrashed()
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice withoutTrashed()
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
@ -183,62 +122,6 @@ use Laracasts\Presenter\PresentableTrait;
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoiceInvitation> $invitations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property bool $is_proforma
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Backup> $history
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoiceInvitation> $invitations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @method static \Illuminate\Database\Eloquent\Builder|RecurringInvoice whereIsProforma($value)
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Backup> $history
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoiceInvitation> $invitations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Backup> $history
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoiceInvitation> $invitations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Backup> $history
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoiceInvitation> $invitations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Backup> $history
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoiceInvitation> $invitations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Backup> $history
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoiceInvitation> $invitations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Backup> $history
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoiceInvitation> $invitations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Backup> $history
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoiceInvitation> $invitations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Backup> $history
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoiceInvitation> $invitations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Backup> $history
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoiceInvitation> $invitations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Backup> $history
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoiceInvitation> $invitations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @mixin \Eloquent
*/
class RecurringInvoice extends BaseModel

View File

@ -57,7 +57,7 @@ use Illuminate\Foundation\Auth\User as Authenticatable;
* @property int|null $avatar_width
* @property int|null $avatar_height
* @property int|null $avatar_size
* @property int $is_deleted
* @property bool $is_deleted
* @property string|null $last_login
* @property string|null $signature
* @property string $password
@ -74,7 +74,7 @@ use Illuminate\Foundation\Auth\User as Authenticatable;
* @property int $has_password
* @property Carbon|null $oauth_user_token_expiry
* @property string|null $sms_verification_code
* @property int $verified_phone_number
* @property bool $verified_phone_number
* @property-read \App\Models\Account $account
* @property-read \App\Models\Company $company
* @property-read mixed $hashed_id

View File

@ -12,13 +12,15 @@
namespace App\Services\Invoice\EInvoice;
use App\Models\Invoice;
use App\Models\PaymentType;
use josemmo\Facturae\Facturae;
use App\Services\AbstractService;
use josemmo\Facturae\FacturaeItem;
use josemmo\Facturae\FacturaeParty;
use josemmo\Facturae\FacturaeCentre;
use josemmo\Facturae\FacturaePayment;
use Illuminate\Support\Facades\Storage;
use josemmo\Facturae\Common\FacturaeSigner;
use josemmo\Facturae\FacturaeCentre;
class FacturaEInvoice extends AbstractService
{
@ -169,6 +171,9 @@ class FacturaEInvoice extends AbstractService
->buildItems()
->setDiscount()
->setPoNumber()
->setLegalTerms()
->setPayments()
->setBillingPeriod()
->signDocument();
$disk = config('filesystems.default');
@ -228,6 +233,139 @@ class FacturaEInvoice extends AbstractService
return $this;
}
private function setLegalTerms(): self
{
$this->fac->addLegalLiteral(substr($this->invoice->public_notes,0,250));
return $this;
}
private function setBillingPeriod(): self
{
try {
if (\Carbon\Carbon::createFromFormat('Y-m-d', $this->invoice->custom_value3)->format('Y-m-d') === $this->invoice->custom_value3 &&
\Carbon\Carbon::createFromFormat('Y-m-d', $this->invoice->custom_value4)->format('Y-m-d') === $this->invoice->custom_value4
) {
$this->fac->setBillingPeriod(\Carbon\Carbon::parse($this->invoice->custom_value3)->format('Y-m-d'), \Carbon\Carbon::parse($this->invoice->custom_value4)->format('Y-m-d'));
}
}
catch(\Exception $e) {
nlog($e->getMessage());
}
return $this;
}
private function setPayments(): self
{
$this->invoice->payments()->each(function ($payment){
$payment_data = [
"dueDate" => \Carbon\Carbon::parse($payment->date)->format('Y-m-d'),
"amount" => $payment->pivot->amount,
];
$data = array_merge($this->resolvePaymentMethod($payment), $payment_data);
$this->fac->addPayment(new FacturaePayment($data));
});
return $this;
}
/**
*
* FacturaePayment::TYPE_CASH Cash
* FacturaePayment::TYPE_DEBIT Domiciled receipt
* FacturaePayment::TYPE_RECEIPT Receipt
* FacturaePayment::TYPE_TRANSFER Transfer
* FacturaePayment::TYPE_ACCEPTED_BILL_OF_EXCHANGE Letter Accepted
* FacturaePayment::TYPE_DOCUMENTARY_CREDIT Letter of credit
* FacturaePayment::TYPE_CONTRACT_AWARD contract award
* FacturaePayment::TYPE_BILL_OF_EXCHANGE Bill of exchange
* FacturaePayment::TYPE_TRANSFERABLE_IOU I will pay to order
* FacturaePayment::TYPE_IOU I Will Pay Not To Order
* FacturaePayment::TYPE_CHEQUE Check
* FacturaePayment::TYPE_REIMBURSEMENT Replacement
* FacturaePayment::TYPE_SPECIAL specials
* FacturaePayment::TYPE_SETOFF Compensation
* FacturaePayment::TYPE_POSTGIRO Money order
* FacturaePayment::TYPE_CERTIFIED_CHEQUE conformed check
* FacturaePayment::TYPE_BANKERS_DRAFT Bank check
* FacturaePayment::TYPE_CASH_ON_DELIVERY Cash on delivery
* FacturaePayment::TYPE_CARD Payment by card
*
* @param \App\Models\Payment $payment
* @return array
*/
private function resolvePaymentMethod(\App\Models\Payment $payment): array
{
$data = [];
match($payment->type_id){
PaymentType::BANK_TRANSFER => $method = FacturaePayment::TYPE_TRANSFER ,
PaymentType::CASH => $method = FacturaePayment::TYPE_CASH ,
PaymentType::ACH => $method = FacturaePayment::TYPE_TRANSFER ,
PaymentType::VISA => $method = FacturaePayment::TYPE_CARD ,
PaymentType::MASTERCARD => $method = FacturaePayment::TYPE_CARD ,
PaymentType::AMERICAN_EXPRESS => $method = FacturaePayment::TYPE_CARD ,
PaymentType::DISCOVER => $method = FacturaePayment::TYPE_CARD ,
PaymentType::DINERS => $method = FacturaePayment::TYPE_CARD ,
PaymentType::EUROCARD => $method = FacturaePayment::TYPE_CARD ,
PaymentType::NOVA => $method = FacturaePayment::TYPE_CARD ,
PaymentType::CREDIT_CARD_OTHER => $method = FacturaePayment::TYPE_CARD ,
PaymentType::PAYPAL => $method = FacturaePayment::TYPE_CARD ,
PaymentType::CHECK => $method = FacturaePayment::TYPE_CHEQUE ,
PaymentType::CARTE_BLANCHE => $method = FacturaePayment::TYPE_CARD ,
PaymentType::UNIONPAY => $method = FacturaePayment::TYPE_CARD ,
PaymentType::JCB => $method = FacturaePayment::TYPE_CARD ,
PaymentType::LASER => $method = FacturaePayment::TYPE_CARD ,
PaymentType::MAESTRO => $method = FacturaePayment::TYPE_CARD ,
PaymentType::SOLO => $method = FacturaePayment::TYPE_CARD ,
PaymentType::SWITCH => $method = FacturaePayment::TYPE_CARD ,
PaymentType::VENMO => $method = FacturaePayment::TYPE_CARD ,
PaymentType::ALIPAY => $method = FacturaePayment::TYPE_CARD ,
PaymentType::SOFORT => $method = FacturaePayment::TYPE_TRANSFER,
PaymentType::SEPA => $method = FacturaePayment::TYPE_TRANSFER,
PaymentType::GOCARDLESS => $method = FacturaePayment::TYPE_SPECIAL ,
PaymentType::CRYPTO => $method = FacturaePayment::TYPE_SPECIAL ,
PaymentType::CREDIT => $method = FacturaePayment::TYPE_DOCUMENTARY_CREDIT ,
PaymentType::ZELLE => $method = FacturaePayment::TYPE_SPECIAL ,
PaymentType::MOLLIE_BANK_TRANSFER => $method = FacturaePayment::TYPE_TRANSFER ,
PaymentType::KBC => $method = FacturaePayment::TYPE_SPECIAL ,
PaymentType::BANCONTACT => $method = FacturaePayment::TYPE_SPECIAL ,
PaymentType::IDEAL => $method = FacturaePayment::TYPE_SPECIAL ,
PaymentType::HOSTED_PAGE => $method = FacturaePayment::TYPE_SPECIAL ,
PaymentType::GIROPAY => $method = FacturaePayment::TYPE_SPECIAL ,
PaymentType::PRZELEWY24 => $method = FacturaePayment::TYPE_SPECIAL ,
PaymentType::EPS => $method = FacturaePayment::TYPE_SPECIAL ,
PaymentType::DIRECT_DEBIT => $method = FacturaePayment::TYPE_SPECIAL ,
PaymentType::BECS => $method = FacturaePayment::TYPE_SPECIAL ,
PaymentType::ACSS => $method = FacturaePayment::TYPE_SPECIAL ,
PaymentType::INSTANT_BANK_PAY => $method = FacturaePayment::TYPE_SPECIAL ,
PaymentType::FPX => $method = FacturaePayment::TYPE_SPECIAL ,
PaymentType::KLARNA => $method = FacturaePayment::TYPE_SPECIAL ,
PaymentType::Interac_E_Transfer => $method = FacturaePayment::TYPE_TRANSFER ,
PaymentType::BACS => $method = FacturaePayment::TYPE_SPECIAL ,
PaymentType::STRIPE_BANK_TRANSFER => $method = FacturaePayment::TYPE_TRANSFER ,
PaymentType::CASH_APP => $method = FacturaePayment::TYPE_SPECIAL ,
default => $method = FacturaePayment::TYPE_CARD ,
};
$data['method'] = $method;
if($method == FacturaePayment::TYPE_TRANSFER)
{
$data['iban'] = $payment->custom_value1;
$data['bic'] = $payment->custom_value2;
}
return $data;
}
private function buildItems(): self
{

View File

@ -14,6 +14,7 @@ namespace App\Services\Payment;
use App\Models\Credit;
use App\Models\Invoice;
use App\Models\Payment;
use App\Models\BankTransaction;
use Illuminate\Contracts\Container\BindingResolutionException;
class DeletePayment
@ -56,6 +57,11 @@ class DeletePayment
$this->payment->is_deleted = true;
$this->payment->delete();
// BankTransaction::where('payment_id', $this->payment->id)->cursor()->each(function ($bt){
// $bt->payment_id = null;
// $bt->save();
// });
return $this;
}

View File

@ -19,21 +19,31 @@ use Illuminate\Support\Carbon;
*/
trait MakesReminders
{
/**
*
* @param string $schedule_reminder
* @param string $num_days_reminder
* @return ?bool
*/
public function inReminderWindow($schedule_reminder, $num_days_reminder)
{
$offset = $this->client->timezone_offset();
// nlog($schedule_reminder. " ". $num_days_reminder);
// nlog("date = " . Carbon::parse($this->date)->addDays($num_days_reminder)->startOfDay()->addSeconds($offset));
// nlog("due date = " . Carbon::parse($this->due_date)->addDays($num_days_reminder)->startOfDay()->addSeconds($offset));
// nlog("now = " . Carbon::now()->startOfDay()->format('Y-m-d H:i:s'));
switch ($schedule_reminder) {
case 'after_invoice_date':
return Carbon::parse($this->date)->addDays($num_days_reminder)->startOfDay()->eq(Carbon::now()->startOfDay());
break;
return Carbon::parse($this->date)->addDays($num_days_reminder)->startOfDay()->addSeconds($offset)->eq(Carbon::now());
case 'before_due_date':
return Carbon::parse($this->due_date)->subDays($num_days_reminder)->startOfDay()->eq(Carbon::now()->startOfDay());
break;
return Carbon::parse($this->due_date)->subDays($num_days_reminder)->startOfDay()->addSeconds($offset)->eq(Carbon::now());
case 'after_due_date':
return Carbon::parse($this->due_date)->addDays($num_days_reminder)->startOfDay()->eq(Carbon::now()->startOfDay());
break;
return Carbon::parse($this->due_date)->addDays($num_days_reminder)->startOfDay()->addSeconds($offset)->eq(Carbon::now());
default:
return null;
break;
}
}

View File

@ -1226,7 +1226,7 @@ class ReportCsvGenerationTest extends TestCase
$this->assertEquals('bob', $this->getFirstValueByColumn($csv, 'Client Name'));
$this->assertEquals('12345', $this->getFirstValueByColumn($csv, 'Invoice Invoice Number'));
$this->assertEquals('$100.00', $this->getFirstValueByColumn($csv, 'Payment Amount'));
$this->assertEquals(100, $this->getFirstValueByColumn($csv, 'Payment Amount'));
$this->assertEquals(now()->addSeconds($this->company->timezone()->utc_offset)->format('Y-m-d'), $this->getFirstValueByColumn($csv, 'Payment Date'));

View File

@ -40,6 +40,8 @@ class RecurringInvoiceTest extends TestCase
use DatabaseTransactions;
use MockAccountData;
public $faker;
protected function setUp() :void
{
parent::setUp();
@ -58,6 +60,49 @@ class RecurringInvoiceTest extends TestCase
}
public function testNextSendDateCatch()
{
$line_items = [];
$item = InvoiceItemFactory::create();
$item->quantity = 1;
$item->cost = 10;
$item->task_id = $this->encodePrimaryKey($this->task->id);
$item->expense_id = $this->encodePrimaryKey($this->expense->id);
$item->notes = "Hello this is the month of :MONTH";
$line_items[] = $item;
$data = [
'frequency_id' => 1,
'status_id' => 2,
'discount' => 0,
'is_amount_discount' => 1,
'po_number' => '3434343',
'public_notes' => 'notes',
'is_deleted' => 0,
'custom_value1' => 0,
'custom_value2' => 0,
'custom_value3' => 0,
'custom_value4' => 0,
'status' => 1,
'client_id' => $this->encodePrimaryKey($this->client->id),
'line_items' => $line_items,
'remaining_cycles' => -1,
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->post('/api/v1/recurring_invoices/', $data)
->assertStatus(200);
$arr = $response->json();
$this->assertEquals(now()->startOfDay(), $arr['data']['next_send_date']);
}
public function testBulkIncreasePriceWithJob()
{

View File

@ -50,6 +50,68 @@ class ReminderTest extends TestCase
$this->withoutExceptionHandling();
}
public function testForReminderFiringCorrectly()
{
$this->invoice->next_send_date = null;
$this->invoice->date = now()->format('Y-m-d');
$this->invoice->last_sent_date = now();
$this->invoice->due_date = Carbon::now()->addDays(5)->format('Y-m-d');
$this->invoice->reminder_last_sent = null;
$this->invoice->save();
$settings = $this->company->settings;
$settings->enable_reminder1 = true;
$settings->schedule_reminder1 = 'after_invoice_date';
$settings->num_days_reminder1 = 2;
$settings->enable_reminder2 = false;
$settings->schedule_reminder2 = '';
$settings->num_days_reminder2 = 0;
$settings->enable_reminder3 = false;
$settings->schedule_reminder3 = '';
$settings->num_days_reminder3 = 0;
$settings->timezone_id = '109';
$settings->entity_send_time = 6;
$settings->endless_reminder_frequency_id = '';
$settings->enable_reminder_endless = false;
$this->client->company->settings = $settings;
$this->client->push();
$client_settings = $settings;
$client_settings->timezone_id = '5';
$client_settings->entity_send_time = 8;
$this->invoice->client->settings = $client_settings;
$this->invoice->push();
$this->invoice = $this->invoice->service()->markSent()->save();
$this->invoice->service()->setReminder($client_settings)->save();
$this->invoice = $this->invoice->fresh();
//due to UTC server time, we actually send the "day before"
$this->assertEquals(now()->addDays(1)->format('Y-m-d'), Carbon::parse($this->invoice->next_send_date)->format('Y-m-d'));
$this->travelTo(now()->startOfDay());
for($x=0; $x<46; $x++) {
// nlog("traveller {$x} ".now()->format('Y-m-d h:i:s'));
(new ReminderJob())->handle();
$this->invoice = $this->invoice->fresh();
$this->assertNull($this->invoice->reminder1_sent);
$this->assertNull($this->invoice->reminder_last_sent);
$this->travelTo(now()->addHours(1));
}
// nlog("traveller ".now()->format('Y-m-d'));
(new ReminderJob())->handle();
$this->invoice = $this->invoice->fresh();
$this->assertNotNull($this->invoice->reminder1_sent);
}
public function testForSingleEndlessReminder()
{
@ -133,7 +195,7 @@ class ReminderTest extends TestCase
nlog($next_send_date->format('Y-m-d h:i:s'));
nlog($calculatedReminderDate->format('Y-m-d h:i:s'));
$this->travelTo(now()->addDays(1));
$this->travelTo($calculatedReminderDate);
$reminder_template = $this->invoice->calculateTemplate('invoice');