This commit is contained in:
David Bomba 2023-02-21 20:04:45 +11:00
parent 52901a644c
commit badf68005a
6 changed files with 365 additions and 71 deletions

View File

@ -4193,7 +4193,7 @@
*/
public static function lock($name, $seconds = 0, $owner = null)
{
/** @var \Illuminate\Cache\FileStore $instance */
/** @var \Illuminate\Cache\RedisStore $instance */
return $instance->lock($name, $seconds, $owner);
}
/**
@ -4206,7 +4206,7 @@
*/
public static function restoreLock($name, $owner)
{
/** @var \Illuminate\Cache\FileStore $instance */
/** @var \Illuminate\Cache\RedisStore $instance */
return $instance->restoreLock($name, $owner);
}
/**
@ -4217,30 +4217,65 @@
*/
public static function flush()
{
/** @var \Illuminate\Cache\FileStore $instance */
/** @var \Illuminate\Cache\RedisStore $instance */
return $instance->flush();
}
/**
* Get the Filesystem instance.
* Get the Redis connection instance.
*
* @return \Illuminate\Filesystem\Filesystem
* @return \Illuminate\Redis\Connections\Connection
* @static
*/
public static function getFilesystem()
public static function connection()
{
/** @var \Illuminate\Cache\FileStore $instance */
return $instance->getFilesystem();
/** @var \Illuminate\Cache\RedisStore $instance */
return $instance->connection();
}
/**
* Get the working directory of the cache.
* Get the Redis connection instance that should be used to manage locks.
*
* @return string
* @return \Illuminate\Redis\Connections\Connection
* @static
*/
public static function getDirectory()
public static function lockConnection()
{
/** @var \Illuminate\Cache\FileStore $instance */
return $instance->getDirectory();
/** @var \Illuminate\Cache\RedisStore $instance */
return $instance->lockConnection();
}
/**
* Specify the name of the connection that should be used to store data.
*
* @param string $connection
* @return void
* @static
*/
public static function setConnection($connection)
{
/** @var \Illuminate\Cache\RedisStore $instance */
$instance->setConnection($connection);
}
/**
* Specify the name of the connection that should be used to manage locks.
*
* @param string $connection
* @return \Illuminate\Cache\RedisStore
* @static
*/
public static function setLockConnection($connection)
{
/** @var \Illuminate\Cache\RedisStore $instance */
return $instance->setLockConnection($connection);
}
/**
* Get the Redis database instance.
*
* @return \Illuminate\Contracts\Redis\Factory
* @static
*/
public static function getRedis()
{
/** @var \Illuminate\Cache\RedisStore $instance */
return $instance->getRedis();
}
/**
* Get the cache key prefix.
@ -4250,8 +4285,20 @@
*/
public static function getPrefix()
{
/** @var \Illuminate\Cache\FileStore $instance */
/** @var \Illuminate\Cache\RedisStore $instance */
return $instance->getPrefix();
}
/**
* Set the cache key prefix.
*
* @param string $prefix
* @return void
* @static
*/
public static function setPrefix($prefix)
{
/** @var \Illuminate\Cache\RedisStore $instance */
$instance->setPrefix($prefix);
}
}
@ -9854,45 +9901,44 @@
return $instance->setConnectionName($name);
}
/**
* Release a reserved job back onto the queue after (n) seconds.
* Migrate the delayed jobs that are ready to the regular queue.
*
* @param string $queue
* @param \Illuminate\Queue\Jobs\DatabaseJobRecord $job
* @param int $delay
* @return mixed
* @param string $from
* @param string $to
* @param int $limit
* @return array
* @static
*/
public static function release($queue, $job, $delay)
public static function migrateExpiredJobs($from, $to)
{
/** @var \Illuminate\Queue\DatabaseQueue $instance */
return $instance->release($queue, $job, $delay);
/** @var \Illuminate\Queue\RedisQueue $instance */
return $instance->migrateExpiredJobs($from, $to);
}
/**
* Delete a reserved job from the queue.
*
* @param string $queue
* @param string $id
* @param \Illuminate\Queue\Jobs\RedisJob $job
* @return void
* @throws \Throwable
* @static
*/
public static function deleteReserved($queue, $id)
public static function deleteReserved($queue, $job)
{
/** @var \Illuminate\Queue\DatabaseQueue $instance */
$instance->deleteReserved($queue, $id);
/** @var \Illuminate\Queue\RedisQueue $instance */
$instance->deleteReserved($queue, $job);
}
/**
* Delete a reserved job from the reserved queue and release it.
*
* @param string $queue
* @param \Illuminate\Queue\Jobs\DatabaseJob $job
* @param \Illuminate\Queue\Jobs\RedisJob $job
* @param int $delay
* @return void
* @static
*/
public static function deleteAndRelease($queue, $job, $delay)
{
/** @var \Illuminate\Queue\DatabaseQueue $instance */
/** @var \Illuminate\Queue\RedisQueue $instance */
$instance->deleteAndRelease($queue, $job, $delay);
}
/**
@ -9904,7 +9950,7 @@
*/
public static function clear($queue)
{
/** @var \Illuminate\Queue\DatabaseQueue $instance */
/** @var \Illuminate\Queue\RedisQueue $instance */
return $instance->clear($queue);
}
/**
@ -9916,19 +9962,30 @@
*/
public static function getQueue($queue)
{
/** @var \Illuminate\Queue\DatabaseQueue $instance */
/** @var \Illuminate\Queue\RedisQueue $instance */
return $instance->getQueue($queue);
}
/**
* Get the underlying database instance.
* Get the connection for the queue.
*
* @return \Illuminate\Database\Connection
* @return \Illuminate\Redis\Connections\Connection
* @static
*/
public static function getDatabase()
public static function getConnection()
{
/** @var \Illuminate\Queue\DatabaseQueue $instance */
return $instance->getDatabase();
/** @var \Illuminate\Queue\RedisQueue $instance */
return $instance->getConnection();
}
/**
* Get the underlying Redis instance.
*
* @return \Illuminate\Contracts\Redis\Factory
* @static
*/
public static function getRedis()
{
/** @var \Illuminate\Queue\RedisQueue $instance */
return $instance->getRedis();
}
/**
* Get the backoff for an object-based queue handler.
@ -9939,7 +9996,7 @@
*/
public static function getJobBackoff($job)
{ //Method inherited from \Illuminate\Queue\Queue
/** @var \Illuminate\Queue\DatabaseQueue $instance */
/** @var \Illuminate\Queue\RedisQueue $instance */
return $instance->getJobBackoff($job);
}
/**
@ -9951,7 +10008,7 @@
*/
public static function getJobExpiration($job)
{ //Method inherited from \Illuminate\Queue\Queue
/** @var \Illuminate\Queue\DatabaseQueue $instance */
/** @var \Illuminate\Queue\RedisQueue $instance */
return $instance->getJobExpiration($job);
}
/**
@ -9963,7 +10020,7 @@
*/
public static function createPayloadUsing($callback)
{ //Method inherited from \Illuminate\Queue\Queue
\Illuminate\Queue\DatabaseQueue::createPayloadUsing($callback);
\Illuminate\Queue\RedisQueue::createPayloadUsing($callback);
}
/**
* Get the container instance being used by the connection.
@ -9973,7 +10030,7 @@
*/
public static function getContainer()
{ //Method inherited from \Illuminate\Queue\Queue
/** @var \Illuminate\Queue\DatabaseQueue $instance */
/** @var \Illuminate\Queue\RedisQueue $instance */
return $instance->getContainer();
}
/**
@ -9985,7 +10042,7 @@
*/
public static function setContainer($container)
{ //Method inherited from \Illuminate\Queue\Queue
/** @var \Illuminate\Queue\DatabaseQueue $instance */
/** @var \Illuminate\Queue\RedisQueue $instance */
$instance->setContainer($container);
}
@ -17797,25 +17854,6 @@
/**
*
*
* @method static void createSubscription(array|string $channels, \Closure $callback, string $method = 'subscribe')
* @method static \Illuminate\Redis\Limiters\ConcurrencyLimiterBuilder funnel(string $name)
* @method static \Illuminate\Redis\Limiters\DurationLimiterBuilder throttle(string $name)
* @method static mixed client()
* @method static void subscribe(array|string $channels, \Closure $callback)
* @method static void psubscribe(array|string $channels, \Closure $callback)
* @method static mixed command(string $method, array $parameters = [])
* @method static void listen(\Closure $callback)
* @method static string|null getName()
* @method static \Illuminate\Redis\Connections\Connection setName(string $name)
* @method static \Illuminate\Contracts\Events\Dispatcher getEventDispatcher()
* @method static void setEventDispatcher(\Illuminate\Contracts\Events\Dispatcher $events)
* @method static void unsetEventDispatcher()
* @method static void macro(string $name, object|callable $macro)
* @method static void mixin(object $mixin, bool $replace = true)
* @method static bool hasMacro(string $name)
* @method static void flushMacros()
* @method static mixed macroCall(string $method, array $parameters)
* @see \Illuminate\Redis\RedisManager
*/
class Redis {
/**

View File

@ -36,6 +36,7 @@ use App\Services\PdfMaker\Design;
use App\Services\PdfMaker\Design as PdfDesignModel;
use App\Services\PdfMaker\Design as PdfMakerDesign;
use App\Services\PdfMaker\PdfMaker;
use App\Services\Preview\StubBuilder;
use App\Utils\HostedPDF\NinjaPdf;
use App\Utils\HtmlEngine;
use App\Utils\Ninja;
@ -176,6 +177,23 @@ class PreviewController extends BaseController
}
public function design(DesignPreviewRequest $request)
{
if (Ninja::isHosted() && !in_array($request->getHost(), ['preview.invoicing.co','staging.invoicing.co'])) {
return response()->json(['message' => 'This server cannot handle this request.'], 400);
}
$stub = new StubBuilder(auth()->user()->company(), auth()->user());
$stub->setEntityType($request->entity_type)
$pdf = $stub->build()->getPdf();
$response = Response::make($pdf, 200);
$response->header('Content-Type', 'application/pdf');
return $response;
}
public function oldDesign(DesignPreviewRequest $request)
{
if(Ninja::isHosted() && !in_array($request->getHost(), ['preview.invoicing.co','staging.invoicing.co'])){
return response()->json(['message' => 'This server cannot handle this request.'], 400);

View File

@ -42,8 +42,7 @@ class DesignPreviewRequest extends Request
public function rules()
{
$rules = [
'entity' => 'bail|sometimes|string',
'entity_id' => 'bail|sometimes|string',
'entity_type' => 'bail|required|in:invoice,quote,credit,purchase_order',
'settings_type' => 'bail|required|in:company,group,client',
'settings' => 'sometimes',
'group_id' => 'sometimes',

View File

@ -0,0 +1,239 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Services\Preview;
use App\Models\User;
use App\Models\Client;
use App\Models\Vendor;
use App\Models\Company;
use App\Models\Invoice;
use App\Utils\HtmlEngine;
use App\Jobs\Util\PreviewPdf;
use App\Models\ClientContact;
use App\Models\VendorContact;
use App\Utils\PhantomJS\Phantom;
use App\Models\InvoiceInvitation;
use App\Services\PdfMaker\Design;
use App\Utils\HostedPDF\NinjaPdf;
use Illuminate\Support\Facades\DB;
use App\Services\PdfMaker\PdfMaker;
use App\Utils\Traits\Pdf\PageNumbering;
use Illuminate\Support\Facades\Response;
class StubBuilder
{
use PageNumbering;
public $entity;
public $entity_type;
public mixed $recipient;
public mixed $contact;
public mixed $invitation;
public string $recipient_string;
public string $html;
public function __construct(public Company $company, public User $user){}
public function setEntityType($entity_type)
{
$this->entity_type = $entity_type;
return $this;
}
public function build(): self
{
try{
DB::connection($this->company->db)->beginTransaction();
$this->createRecipient()
->createEntity()
->linkRelations()
->buildHtml();
DB::connection($this->company->db)->rollBack();
}
catch(\Exception $e)
{
return $e->getMessage();
DB::connection($this->company->db)->rollBack();
}
return $this;
}
public function getPdf(): mixed
{
if (config('ninja.phantomjs_pdf_generation') || config('ninja.pdf_generator') == 'phantom') {
return (new Phantom)->convertHtmlToPdf($this->html);
}
if (config('ninja.invoiceninja_hosted_pdf_generation') || config('ninja.pdf_generator') == 'hosted_ninja') {
$pdf = (new NinjaPdf())->build($this->html);
$numbered_pdf = $this->pageNumbering($pdf, $this->company);
if ($numbered_pdf) {
$pdf = $numbered_pdf;
}
return $pdf;
}
return (new PreviewPdf($this->html, $this->company))->handle();
}
private function buildHtml(): self
{
$html = new HtmlEngine($this->invitation);
$design = new Design(Design::CUSTOM, ['custom_partials' => request()->design['design']]);
$state = [
'template' => $design->elements([
'client' => $this->recipient,
'entity' => $this->entity,
'pdf_variables' => (array) $this->company->settings->pdf_variables,
'products' => request()->design['design']['product'],
]),
'variables' => $html->generateLabelsAndValues(),
'process_markdown' => $this->company->markdown_enabled,
];
$maker = new PdfMaker($state);
$this->html = $maker->design($design)
->build()
->getCompiledHTML();
return $this;
}
private function linkRelations(): self
{
$this->entity->setRelation('invitations', $this->invitation);
$this->entity->setRelation($this->recipient_string, $this->recipient);
$this->entity->setRelation('company', $this->company);
$this->entity->load("{$this->recipient_string}.company");
return $this;
}
private function createRecipient(): self
{
match($this->entity_type) {
'invoice' => $this->createClient(),
'quote' => $this->createClient(),
'credit' => $this->createClient(),
'purchase_order' => $this->createVendor(),
};
return $this;
}
private function createClient(): self
{
$this->recipient = Client::factory()->create([
'user_id' => $this->user->id,
'company_id' => $this->company->id,
]);
$this->contact = ClientContact::factory()->create([
'user_id' => $this->user->id,
'company_id' => $this->company->id,
'client_id' => $this->recipient->id,
]);
$this->recipient_string = 'client';
return $this;
}
private function createVendor(): self
{
$this->recipient = Vendor::factory()->create([
'user_id' => $this->user->id,
'company_id' => $this->user->company()->id,
]);
$this->contact = VendorContact::factory()->create([
'user_id' => $this->user->id,
'company_id' => $this->company->id,
'vendor_id' => $this->recipient->id,
]);
$this->recipient_string = 'vendor';
return $this;
}
private function createEntity(): self
{
match($this->entity_type) {
'invoice' => $this->createInvoice(),
'quote' => $this->createQuote(),
'credit' => $this->createCredit(),
'purchase_order' => $this->createPurchaseOrder(),
};
return $this;
}
private function createInvoice()
{
$this->entity = Invoice::factory()->create([
'user_id' => $this->user->id,
'company_id' => $this->company->id,
'client_id' => $this->recipient->id,
'terms' => $this->company->settings->invoice_terms,
'footer' => $this->company->settings->invoice_footer,
]);
$this->invitation = InvoiceInvitation::factory()->create([
'user_id' => $this->user->id,
'company_id' => $this->company->id,
'invoice_id' => $this->entity->id,
'client_contact_id' => $this->contact->id,
]);
}
private function createQuote()
{
$this->entity->save();
}
private function createCredit()
{
$this->entity->save();
}
private function createPurchaseOrder()
{
$this->entity->save();
}
}

View File

@ -30,11 +30,11 @@ class ClientFactory extends Factory
'balance' => 0,
'paid_to_date' => 0,
'vat_number' => $this->faker->numberBetween(123456789, 987654321),
'id_number' => '',
'custom_value1' => '',
'custom_value2' => '',
'custom_value3' => '',
'custom_value4' => '',
'id_number' => $this->faker->iban(),
'custom_value1' => $this->faker->dateTime(),
'custom_value2' => $this->faker->colorName(),
'custom_value3' => $this->faker->word(),
'custom_value4' => $this->faker->email(),
'address1' => $this->faker->buildingNumber(),
'address2' => $this->faker->streetAddress(),
'city' => $this->faker->city(),

View File

@ -35,10 +35,10 @@ class InvoiceFactory extends Factory
'tax_rate2' => 17.5,
//'tax_name3' => 'THIRDTAX',
//'tax_rate3' => 5,
// 'custom_value1' => $this->faker->date(),
//'custom_value2' => rand(0, 1) ? 'yes' : 'no',
// 'custom_value3' => $this->faker->numberBetween(1,4),
// 'custom_value4' => $this->faker->numberBetween(1,4),
'custom_value1' => $this->faker->date(),
'custom_value2' => rand(0, 1) ? 'yes' : 'no',
'custom_value3' => $this->faker->numberBetween(1,4),
'custom_value4' => $this->faker->numberBetween(1,4),
'is_deleted' => false,
'po_number' => $this->faker->text(10),
'date' => $this->faker->date(),