Add File based templates
63
app/Console/Commands/CreateTemplateCommand.php
Normal file
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace Crater\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class CreateTemplateCommand extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'make:template {name} {--type=}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Create estimate or invoice pdf template. ';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$templateName = $this->argument('name');
|
||||
$type = $this->option('type');
|
||||
|
||||
if (!$type) {
|
||||
$type = $this->choice('Create a template for?', ['invoice', 'estimate']);
|
||||
}
|
||||
|
||||
if (Storage::disk('views')->exists("/app/pdf/{$type}/{$templateName}.blade.php")) {
|
||||
$this->info("Template with given name already exists.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Storage::disk('views')->copy("/app/pdf/{$type}/{$type}1.blade.php", "/app/pdf/{$type}/{$templateName}.blade.php");
|
||||
copy(public_path("/assets/img/PDF/{$type}1.png"), public_path("/assets/img/PDF/{$templateName}.png"));
|
||||
|
||||
$path = resource_path("app/pdf/{$type}/{$templateName}.blade.php");
|
||||
$type = ucfirst($type);
|
||||
$this->info("{$type} Template created successfully at ". $path);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -15,6 +15,7 @@ class Kernel extends ConsoleKernel
|
||||
protected $commands = [
|
||||
Commands\ResetApp::class,
|
||||
Commands\UpdateCommand::class,
|
||||
Commands\CreateTemplateCommand::class
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@ -21,7 +21,7 @@ class ConvertEstimateController extends Controller
|
||||
*/
|
||||
public function __invoke(Request $request, Estimate $estimate)
|
||||
{
|
||||
$estimate->load(['items', 'items.taxes', 'user', 'estimateTemplate', 'taxes']);
|
||||
$estimate->load(['items', 'items.taxes', 'user', 'taxes']);
|
||||
|
||||
$invoice_date = Carbon::now();
|
||||
$due_date = Carbon::now()->addDays(7);
|
||||
@ -39,7 +39,7 @@ class ConvertEstimateController extends Controller
|
||||
'reference_number' => $estimate->reference_number,
|
||||
'user_id' => $estimate->user_id,
|
||||
'company_id' => $request->header('company'),
|
||||
'invoice_template_id' => 1,
|
||||
'template_name' => 'invoice1',
|
||||
'status' => Invoice::STATUS_DRAFT,
|
||||
'paid_status' => Invoice::STATUS_UNPAID,
|
||||
'sub_total' => $estimate->sub_total,
|
||||
@ -84,8 +84,7 @@ class ConvertEstimateController extends Controller
|
||||
$invoice = Invoice::with([
|
||||
'items',
|
||||
'user',
|
||||
'invoiceTemplate',
|
||||
'taxes',
|
||||
'taxes'
|
||||
])->find($invoice->id);
|
||||
|
||||
return response()->json([
|
||||
|
||||
@ -5,6 +5,8 @@ namespace Crater\Http\Controllers\V1\Estimate;
|
||||
use Crater\Http\Controllers\Controller;
|
||||
use Crater\Models\EstimateTemplate;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class EstimateTemplatesController extends Controller
|
||||
{
|
||||
@ -16,8 +18,17 @@ class EstimateTemplatesController extends Controller
|
||||
*/
|
||||
public function __invoke(Request $request)
|
||||
{
|
||||
$templates = Storage::disk('views')->files('/app/pdf/estimate');
|
||||
$estimateTemplates = [];
|
||||
|
||||
foreach ($templates as $key => $template) {
|
||||
$templateName = Str::before(basename($template), '.blade.php');
|
||||
$estimateTemplates[$key]['name'] = $templateName;
|
||||
$estimateTemplates[$key]['path'] = asset('assets/img/PDF/'.$templateName.'.png');
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'templates' => EstimateTemplate::all(),
|
||||
'templates' => $estimateTemplates
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,7 +18,6 @@ class EstimatesController extends Controller
|
||||
$estimates = Estimate::with([
|
||||
'items',
|
||||
'user',
|
||||
'estimateTemplate',
|
||||
'taxes',
|
||||
'creator',
|
||||
])
|
||||
@ -68,7 +67,6 @@ class EstimatesController extends Controller
|
||||
'items',
|
||||
'items.taxes',
|
||||
'user',
|
||||
'estimateTemplate',
|
||||
'creator',
|
||||
'taxes',
|
||||
'taxes.taxType',
|
||||
|
||||
@ -21,7 +21,9 @@ class BootstrapController extends Controller
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
$default_language = $user->getSettings(['language'])['language'];
|
||||
$default_language = $user->getSettings(['language']);
|
||||
|
||||
$default_language = array_key_exists('language', $default_language) ? $default_language['language'] : 'en';
|
||||
|
||||
$settings = [
|
||||
'moment_date_format',
|
||||
|
||||
@ -32,7 +32,7 @@ class CloneInvoiceController extends Controller
|
||||
'reference_number' => $invoice->reference_number,
|
||||
'user_id' => $invoice->user_id,
|
||||
'company_id' => $request->header('company'),
|
||||
'invoice_template_id' => $invoice->invoice_template_id,
|
||||
'template_name' => 'invoice1',
|
||||
'status' => Invoice::STATUS_DRAFT,
|
||||
'paid_status' => Invoice::STATUS_UNPAID,
|
||||
'sub_total' => $invoice->sub_total,
|
||||
@ -78,8 +78,7 @@ class CloneInvoiceController extends Controller
|
||||
$newInvoice = Invoice::with([
|
||||
'items',
|
||||
'user',
|
||||
'invoiceTemplate',
|
||||
'taxes',
|
||||
'taxes'
|
||||
])
|
||||
->find($newInvoice->id);
|
||||
|
||||
|
||||
@ -3,7 +3,8 @@
|
||||
namespace Crater\Http\Controllers\V1\Invoice;
|
||||
|
||||
use Crater\Http\Controllers\Controller;
|
||||
use Crater\Models\InvoiceTemplate;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class InvoiceTemplatesController extends Controller
|
||||
@ -16,7 +17,14 @@ class InvoiceTemplatesController extends Controller
|
||||
*/
|
||||
public function __invoke(Request $request)
|
||||
{
|
||||
$invoiceTemplates = InvoiceTemplate::all();
|
||||
$templates = Storage::disk('views')->files('/app/pdf/invoice');
|
||||
$invoiceTemplates = [];
|
||||
|
||||
foreach ($templates as $key => $template) {
|
||||
$templateName = Str::before(basename($template), '.blade.php');
|
||||
$invoiceTemplates[$key]['name'] = $templateName;
|
||||
$invoiceTemplates[$key]['path'] = asset('assets/img/PDF/'.$templateName.'.png');
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'invoiceTemplates' => $invoiceTemplates,
|
||||
|
||||
@ -20,7 +20,7 @@ class InvoicesController extends Controller
|
||||
{
|
||||
$limit = $request->has('limit') ? $request->limit : 10;
|
||||
|
||||
$invoices = Invoice::with(['items', 'user', 'creator', 'invoiceTemplate', 'taxes'])
|
||||
$invoices = Invoice::with(['items', 'user', 'creator', 'taxes'])
|
||||
->join('users', 'users.id', '=', 'invoices.user_id')
|
||||
->applyFilters($request->only([
|
||||
'status',
|
||||
@ -78,7 +78,6 @@ class InvoicesController extends Controller
|
||||
'items',
|
||||
'items.taxes',
|
||||
'user',
|
||||
'invoiceTemplate',
|
||||
'taxes.taxType',
|
||||
'fields.customField',
|
||||
]);
|
||||
|
||||
@ -54,8 +54,8 @@ class EstimatesRequest extends FormRequest
|
||||
'tax' => [
|
||||
'required',
|
||||
],
|
||||
'estimate_template_id' => [
|
||||
'required',
|
||||
'template_name' => [
|
||||
'required'
|
||||
],
|
||||
'items' => [
|
||||
'required',
|
||||
|
||||
@ -54,8 +54,8 @@ class InvoicesRequest extends FormRequest
|
||||
'tax' => [
|
||||
'required',
|
||||
],
|
||||
'invoice_template_id' => [
|
||||
'required',
|
||||
'template_name' => [
|
||||
'required'
|
||||
],
|
||||
'items' => [
|
||||
'required',
|
||||
|
||||
@ -2,6 +2,10 @@
|
||||
|
||||
namespace Crater\Models;
|
||||
|
||||
use Crater\Models\Company;
|
||||
use Crater\Models\Tax;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Crater\Models\CompanySetting;
|
||||
use App;
|
||||
use Barryvdh\DomPDF\Facade as PDF;
|
||||
use Carbon\Carbon;
|
||||
@ -9,7 +13,6 @@ use Crater\Mail\SendEstimateMail;
|
||||
use Crater\Traits\GeneratesPdfTrait;
|
||||
use Crater\Traits\HasCustomFieldsTrait;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Spatie\MediaLibrary\HasMedia;
|
||||
use Spatie\MediaLibrary\InteractsWithMedia;
|
||||
@ -130,11 +133,6 @@ class Estimate extends Model implements HasMedia
|
||||
return $this->hasMany(Tax::class);
|
||||
}
|
||||
|
||||
public function estimateTemplate()
|
||||
{
|
||||
return $this->belongsTo('Crater\Models\EstimateTemplate');
|
||||
}
|
||||
|
||||
public function getEstimateNumAttribute()
|
||||
{
|
||||
$position = $this->strposX($this->estimate_number, "-", 1) + 1;
|
||||
@ -315,8 +313,7 @@ class Estimate extends Model implements HasMedia
|
||||
return Estimate::with([
|
||||
'items.taxes',
|
||||
'user',
|
||||
'estimateTemplate',
|
||||
'taxes',
|
||||
'taxes'
|
||||
])
|
||||
->find($estimate->id);
|
||||
}
|
||||
@ -341,11 +338,10 @@ class Estimate extends Model implements HasMedia
|
||||
}
|
||||
|
||||
return Estimate::with([
|
||||
'items.taxes',
|
||||
'user',
|
||||
'estimateTemplate',
|
||||
'taxes',
|
||||
])
|
||||
'items.taxes',
|
||||
'user',
|
||||
'taxes'
|
||||
])
|
||||
->find($this->id);
|
||||
}
|
||||
|
||||
@ -431,7 +427,7 @@ class Estimate extends Model implements HasMedia
|
||||
}
|
||||
}
|
||||
|
||||
$estimateTemplate = EstimateTemplate::find($this->estimate_template_id);
|
||||
$estimateTemplate = self::find($this->id)->template_name;
|
||||
|
||||
$company = Company::find($this->company_id);
|
||||
$locale = CompanySetting::getSetting('language', $company->id);
|
||||
@ -451,7 +447,7 @@ class Estimate extends Model implements HasMedia
|
||||
'taxes' => $taxes,
|
||||
]);
|
||||
|
||||
return PDF::loadView('app.pdf.estimate.'.$estimateTemplate->view);
|
||||
return PDF::loadView('app.pdf.estimate.'.$estimateTemplate);
|
||||
}
|
||||
|
||||
public function getCompanyAddress()
|
||||
|
||||
@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Crater\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class EstimateTemplate extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = ['path', 'view', 'name'];
|
||||
|
||||
public function estimates()
|
||||
{
|
||||
return $this->hasMany(Estimate::class);
|
||||
}
|
||||
|
||||
public function getPathAttribute($value)
|
||||
{
|
||||
return url($value);
|
||||
}
|
||||
}
|
||||
@ -2,6 +2,12 @@
|
||||
|
||||
namespace Crater\Models;
|
||||
|
||||
use Crater\Models\Company;
|
||||
use Crater\Models\CompanySetting;
|
||||
use Crater\Models\Currency;
|
||||
use Crater\Models\Tax;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Crater\Models\Payment;
|
||||
use App;
|
||||
use Barryvdh\DomPDF\Facade as PDF;
|
||||
use Carbon\Carbon;
|
||||
@ -9,7 +15,6 @@ use Crater\Mail\SendInvoiceMail;
|
||||
use Crater\Traits\GeneratesPdfTrait;
|
||||
use Crater\Traits\HasCustomFieldsTrait;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Spatie\MediaLibrary\HasMedia;
|
||||
use Spatie\MediaLibrary\InteractsWithMedia;
|
||||
@ -141,11 +146,6 @@ class Invoice extends Model implements HasMedia
|
||||
return $this->belongsTo('Crater\Models\User', 'creator_id');
|
||||
}
|
||||
|
||||
public function invoiceTemplate()
|
||||
{
|
||||
return $this->belongsTo(InvoiceTemplate::class);
|
||||
}
|
||||
|
||||
public function getInvoicePdfUrlAttribute()
|
||||
{
|
||||
return url('/invoices/pdf/'.$this->unique_hash);
|
||||
@ -366,11 +366,10 @@ class Invoice extends Model implements HasMedia
|
||||
}
|
||||
|
||||
$invoice = Invoice::with([
|
||||
'items',
|
||||
'user',
|
||||
'invoiceTemplate',
|
||||
'taxes',
|
||||
])
|
||||
'items',
|
||||
'user',
|
||||
'taxes'
|
||||
])
|
||||
->find($invoice->id);
|
||||
|
||||
return $invoice;
|
||||
@ -418,11 +417,10 @@ class Invoice extends Model implements HasMedia
|
||||
}
|
||||
|
||||
$invoice = Invoice::with([
|
||||
'items',
|
||||
'user',
|
||||
'invoiceTemplate',
|
||||
'taxes',
|
||||
])
|
||||
'items',
|
||||
'user',
|
||||
'taxes'
|
||||
])
|
||||
->find($this->id);
|
||||
|
||||
return $invoice;
|
||||
@ -512,7 +510,7 @@ class Invoice extends Model implements HasMedia
|
||||
}
|
||||
}
|
||||
|
||||
$invoiceTemplate = InvoiceTemplate::find($this->invoice_template_id);
|
||||
$invoiceTemplate = self::find($this->id)->template_name;
|
||||
|
||||
$company = Company::find($this->company_id);
|
||||
$locale = CompanySetting::getSetting('language', $company->id);
|
||||
@ -532,7 +530,7 @@ class Invoice extends Model implements HasMedia
|
||||
'taxes' => $taxes,
|
||||
]);
|
||||
|
||||
return PDF::loadView('app.pdf.invoice.'.$invoiceTemplate->view);
|
||||
return PDF::loadView('app.pdf.invoice.'.$invoiceTemplate);
|
||||
}
|
||||
|
||||
public function getEmailAttachmentSetting()
|
||||
|
||||
@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Crater\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class InvoiceTemplate extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = ['path', 'view', 'name'];
|
||||
|
||||
public function invoices()
|
||||
{
|
||||
return $this->hasMany(Invoice::class);
|
||||
}
|
||||
|
||||
public function getPathAttribute($value)
|
||||
{
|
||||
return url($value);
|
||||
}
|
||||
}
|
||||
@ -90,6 +90,12 @@ return [
|
||||
'app' => env('DROPBOX_APP'),
|
||||
'root' => env('DROPBOX_ROOT'),
|
||||
],
|
||||
|
||||
'views' => [
|
||||
'driver' => 'local',
|
||||
'root' => resource_path('views'),
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
/*
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
namespace Database\Factories;
|
||||
|
||||
use Crater\Models\Estimate;
|
||||
use Crater\Models\EstimateTemplate;
|
||||
use Crater\Models\User;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
@ -76,7 +75,7 @@ class EstimateFactory extends Factory
|
||||
'company_id' => User::where('role', 'super admin')->first()->company_id,
|
||||
'user_id' => User::factory()->create(['role' => 'customer'])->id,
|
||||
'status' => Estimate::STATUS_DRAFT,
|
||||
'estimate_template_id' => EstimateTemplate::find(1) ?? EstimateTemplate::factory(),
|
||||
'template_name' => 'estimate1',
|
||||
'sub_total' => $this->faker->randomDigitNotNull,
|
||||
'total' => $this->faker->randomDigitNotNull,
|
||||
'discount_type' => $this->faker->randomElement(['percentage', 'fixed']),
|
||||
|
||||
@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use Crater\Models\EstimateTemplate;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
class EstimateTemplateFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* The name of the factory's corresponding model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $model = EstimateTemplate::class;
|
||||
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function definition()
|
||||
{
|
||||
return [
|
||||
'path' => $this->faker->word,
|
||||
'view' => $this->faker->word,
|
||||
'name' => $this->faker->word,
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -3,7 +3,6 @@
|
||||
namespace Database\Factories;
|
||||
|
||||
use Crater\Models\Invoice;
|
||||
use Crater\Models\InvoiceTemplate;
|
||||
use Crater\Models\User;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
@ -101,7 +100,7 @@ class InvoiceFactory extends Factory
|
||||
'invoice_number' => 'INV-'.Invoice::getNextInvoiceNumber('INV'),
|
||||
'reference_number' => Invoice::getNextInvoiceNumber('INV'),
|
||||
'user_id' => User::factory()->create(['role' => 'customer'])->id,
|
||||
'invoice_template_id' => InvoiceTemplate::find(1) ?? InvoiceTemplate::factory(),
|
||||
'template_name' => 'invoice1',
|
||||
'status' => Invoice::STATUS_DRAFT,
|
||||
'tax_per_item' => 'NO',
|
||||
'discount_per_item' => 'NO',
|
||||
|
||||
@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use Crater\Models\InvoiceTemplate;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
class InvoiceTemplateFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* The name of the factory's corresponding model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $model = InvoiceTemplate::class;
|
||||
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function definition()
|
||||
{
|
||||
return [
|
||||
'path' => $this->faker->word,
|
||||
'view' => $this->faker->word,
|
||||
'name' => $this->faker->word,
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -34,8 +34,6 @@ class CreateInvoicesTable extends Migration
|
||||
$table->boolean('sent')->default(false);
|
||||
$table->boolean('viewed')->default(false);
|
||||
$table->string('unique_hash')->nullable();
|
||||
$table->integer('invoice_template_id')->unsigned()->nullable();
|
||||
$table->foreign('invoice_template_id')->references('id')->on('invoice_templates');
|
||||
$table->integer('user_id')->unsigned()->nullable();
|
||||
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||
$table->integer('company_id')->unsigned()->nullable();
|
||||
|
||||
@ -32,8 +32,6 @@ class CreateEstimatesTable extends Migration
|
||||
$table->string('unique_hash')->nullable();
|
||||
$table->integer('user_id')->unsigned()->nullable();
|
||||
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||
$table->integer('estimate_template_id')->unsigned()->nullable();
|
||||
$table->foreign('estimate_template_id')->references('id')->on('estimate_templates');
|
||||
$table->integer('company_id')->unsigned()->nullable();
|
||||
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
|
||||
$table->timestamps();
|
||||
|
||||
@ -4,7 +4,7 @@ use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateInvoiceTemplatesTable extends Migration
|
||||
class AddTemplateNameToInvoicesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
@ -13,12 +13,8 @@ class CreateInvoiceTemplatesTable extends Migration
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('invoice_templates', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('name')->nullable();
|
||||
$table->string('view');
|
||||
$table->string('path');
|
||||
$table->timestamps();
|
||||
Schema::table('invoices', function (Blueprint $table) {
|
||||
$table->string('template_name')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
@ -29,6 +25,8 @@ class CreateInvoiceTemplatesTable extends Migration
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('invoice_templates');
|
||||
Schema::table('invoices', function (Blueprint $table) {
|
||||
$table->dropColumn('template_name');
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -4,7 +4,7 @@ use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateEstimateTemplatesTable extends Migration
|
||||
class AddTemplateNameToEstimatesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
@ -13,12 +13,8 @@ class CreateEstimateTemplatesTable extends Migration
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('estimate_templates', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('name')->nullable();
|
||||
$table->string('view');
|
||||
$table->string('path');
|
||||
$table->timestamps();
|
||||
Schema::table('estimates', function (Blueprint $table) {
|
||||
$table->string('template_name')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
@ -29,6 +25,8 @@ class CreateEstimateTemplatesTable extends Migration
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('estimate_templates');
|
||||
Schema::table('estimates', function (Blueprint $table) {
|
||||
$table->dropColumn('template_name');
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
use Crater\Models\Estimate;
|
||||
use Crater\Models\Invoice;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class RemoveTemplateIdFromInvoicesAndEstimatesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
if (Schema::hasColumn('invoices', 'invoice_template_id'))
|
||||
{
|
||||
$invoices = Invoice::all();
|
||||
|
||||
$invoices->map(function ($invoice) {
|
||||
$invoice->template_name = 'invoice'.$invoice->invoice_template_id;
|
||||
$invoice->save();
|
||||
});
|
||||
|
||||
Schema::table('invoices', function (Blueprint $table) {
|
||||
$table->dropForeign(['invoice_template_id']);
|
||||
$table->dropColumn('invoice_template_id');
|
||||
});
|
||||
}
|
||||
|
||||
if (Schema::hasColumn('estimates', 'estimate_template_id'))
|
||||
{
|
||||
$estimates = Estimate::all();
|
||||
|
||||
$estimates->map(function ($estimate) {
|
||||
$estimate->template_name = 'estimate'.$estimate->estimate_template_id;
|
||||
$estimate->save();
|
||||
});
|
||||
|
||||
Schema::table('estimates', function (Blueprint $table) {
|
||||
$table->dropForeign(['estimate_template_id']);
|
||||
$table->dropColumn('estimate_template_id');
|
||||
});
|
||||
}
|
||||
|
||||
Schema::dropIfExists('invoice_templates');
|
||||
Schema::dropIfExists('estimate_templates');
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
@ -17,8 +17,6 @@ class DatabaseSeeder extends Seeder
|
||||
$this->call(CurrenciesTableSeeder::class);
|
||||
$this->call(DefaultSettingsSeeder::class);
|
||||
$this->call(CountriesTableSeeder::class);
|
||||
$this->call(EstimateTemplateSeeder::class);
|
||||
$this->call(InvoiceTemplateSeeder::class);
|
||||
$this->call(PaymentMethodSeeder::class);
|
||||
$this->call(UnitSeeder::class);
|
||||
}
|
||||
|
||||
@ -1,35 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Crater\Models\EstimateTemplate;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class EstimateTemplateSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
EstimateTemplate::create([
|
||||
'name' => 'Template 1',
|
||||
'view' => 'estimate1',
|
||||
'path' => '/assets/img/PDF/Template1.png',
|
||||
]);
|
||||
|
||||
EstimateTemplate::create([
|
||||
'name' => 'Template 2',
|
||||
'view' => 'estimate2',
|
||||
'path' => '/assets/img/PDF/Template2.png',
|
||||
]);
|
||||
|
||||
EstimateTemplate::create([
|
||||
'name' => 'Template 3',
|
||||
'view' => 'estimate3',
|
||||
'path' => '/assets/img/PDF/Template3.png',
|
||||
]);
|
||||
}
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Crater\Models\InvoiceTemplate;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class InvoiceTemplateSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
InvoiceTemplate::create([
|
||||
'name' => 'Template 1',
|
||||
'view' => 'invoice1',
|
||||
'path' => '/assets/img/PDF/Template1.png',
|
||||
]);
|
||||
|
||||
InvoiceTemplate::create([
|
||||
'name' => ' Template 2',
|
||||
'view' => 'invoice2',
|
||||
'path' => '/assets/img/PDF/Template2.png',
|
||||
]);
|
||||
|
||||
InvoiceTemplate::create([
|
||||
'name' => 'Template 3',
|
||||
'view' => 'invoice3',
|
||||
'path' => '/assets/img/PDF/Template3.png',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 104 KiB |
BIN
public/assets/img/PDF/invoice1.png
Normal file
|
After Width: | Height: | Size: 94 KiB |
BIN
public/assets/img/PDF/invoice2.png
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
public/assets/img/PDF/invoice3.png
Normal file
|
After Width: | Height: | Size: 104 KiB |
@ -7,14 +7,19 @@
|
||||
:key="index"
|
||||
:class="{
|
||||
'border border-solid border-primary-500':
|
||||
selectedTemplate === template.id,
|
||||
selectedTemplate === template.name,
|
||||
}"
|
||||
class="relative flex flex-col m-2 border border-gray-200 border-solid cursor-pointer hover:border-primary-300"
|
||||
@click="selectedTemplate = template.id"
|
||||
class="relative flex flex-col m-2 border border-gray-200 border-solid cursor-pointer hover:border-primary-300"
|
||||
>
|
||||
<img :src="template.path" alt="template-image" />
|
||||
<img
|
||||
v-if="selectedTemplate === template.id"
|
||||
:src="template.path"
|
||||
:alt="template.name"
|
||||
class="w-full"
|
||||
@click="selectedTemplate = template.name"
|
||||
/>
|
||||
<img
|
||||
v-if="selectedTemplate === template.name"
|
||||
:alt="template.name"
|
||||
class="absolute z-10 w-5 h-5 text-primary-500"
|
||||
style="top: -6px; right: -5px"
|
||||
src="/assets/img/tick.png"
|
||||
@ -24,8 +29,8 @@
|
||||
'w-full p-1 bg-gray-200 text-sm text-center absolute bottom-0 left-0',
|
||||
{
|
||||
'text-primary-500 bg-primary-100':
|
||||
selectedTemplate === template.id,
|
||||
'text-gray-600': selectedTemplate != template.id,
|
||||
selectedTemplate === template.name,
|
||||
'text-gray-600': selectedTemplate != template.name,
|
||||
},
|
||||
]"
|
||||
>
|
||||
@ -53,16 +58,16 @@ import { mapActions, mapGetters } from 'vuex'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
selectedTemplate: 1,
|
||||
selectedTemplate: null,
|
||||
isLoading: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('modal', ['modalData']),
|
||||
...mapGetters('estimate', ['getTemplateId']),
|
||||
...mapGetters('estimate', ['getTemplateName']),
|
||||
},
|
||||
mounted() {
|
||||
this.selectedTemplate = this.getTemplateId
|
||||
this.selectedTemplate = this.getTemplateName
|
||||
},
|
||||
methods: {
|
||||
...mapActions('estimate', ['setTemplate']),
|
||||
@ -77,7 +82,7 @@ export default {
|
||||
}
|
||||
},
|
||||
closeEstimateModal() {
|
||||
this.selectedTemplate = this.getTemplateId
|
||||
this.selectedTemplate = this.getTemplateName
|
||||
this.closeModal()
|
||||
this.resetModalData()
|
||||
},
|
||||
|
||||
@ -7,14 +7,19 @@
|
||||
:key="index"
|
||||
:class="{
|
||||
'border border-solid border-primary-500':
|
||||
selectedTemplate === template.id,
|
||||
selectedTemplate === template.name,
|
||||
}"
|
||||
class="relative flex flex-col m-2 border border-gray-200 border-solid cursor-pointer hover:border-primary-300"
|
||||
@click="selectedTemplate = template.id"
|
||||
class="relative flex flex-col m-2 border border-gray-200 border-solid cursor-pointer hover:border-primary-300"
|
||||
>
|
||||
<img :src="template.path" alt="template-image" />
|
||||
<img
|
||||
v-if="selectedTemplate === template.id"
|
||||
:src="template.path"
|
||||
:alt="template.name"
|
||||
class="w-full"
|
||||
@click="selectedTemplate = template.name"
|
||||
/>
|
||||
<img
|
||||
v-if="selectedTemplate === template.name"
|
||||
:alt="template.name"
|
||||
class="absolute z-10 w-5 h-5 text-primary-500"
|
||||
style="top: -6px; right: -5px"
|
||||
src="/assets/img/tick.png"
|
||||
@ -53,16 +58,16 @@ import { mapActions, mapGetters } from 'vuex'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
selectedTemplate: 1,
|
||||
selectedTemplate: null,
|
||||
isLoading: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('modal', ['modalData']),
|
||||
...mapGetters('invoice', ['getTemplateId']),
|
||||
...mapGetters('invoice', ['getTemplateName']),
|
||||
},
|
||||
mounted() {
|
||||
this.selectedTemplate = this.getTemplateId
|
||||
this.selectedTemplate = this.getTemplateName
|
||||
},
|
||||
methods: {
|
||||
...mapActions('invoice', ['setTemplate']),
|
||||
@ -77,7 +82,7 @@ export default {
|
||||
}
|
||||
},
|
||||
closeInvoiceModal() {
|
||||
this.selectedTemplate = this.getTemplateId
|
||||
this.selectedTemplate = this.getTemplateName
|
||||
this.closeModal()
|
||||
this.resetModalData()
|
||||
},
|
||||
|
||||
@ -60,10 +60,7 @@ export const fetchEstimate = ({ commit, dispatch, state }, id) => {
|
||||
window.axios
|
||||
.get(`/api/v1/estimates/${id}`)
|
||||
.then((response) => {
|
||||
commit(
|
||||
types.SET_TEMPLATE_ID,
|
||||
response.data.estimate.estimate_template_id
|
||||
)
|
||||
commit(types.SET_TEMPLATE_NAME, response.data.estimate.template_name)
|
||||
resolve(response)
|
||||
})
|
||||
.catch((err) => {
|
||||
@ -297,7 +294,7 @@ export const resetItem = ({ commit, dispatch, state }) => {
|
||||
|
||||
export const setTemplate = ({ commit, dispatch, state }, data) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
commit(types.SET_TEMPLATE_ID, data)
|
||||
commit(types.SET_TEMPLATE_NAME, data)
|
||||
resolve({})
|
||||
})
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
export const estimates = (state) => state.estimates
|
||||
export const selectAllField = (state) => state.selectAllField
|
||||
export const getTemplateId = (state) => state.estimateTemplateId
|
||||
export const getTemplateName = (state) => state.estimateTemplateName
|
||||
export const selectedEstimates = (state) => state.selectedEstimates
|
||||
export const totalEstimates = (state) => state.totalEstimates
|
||||
export const selectedCustomer = (state) => state.selectedCustomer
|
||||
|
||||
@ -4,7 +4,7 @@ import * as getters from './getters'
|
||||
|
||||
const initialState = {
|
||||
estimates: [],
|
||||
estimateTemplateId: 1,
|
||||
estimateTemplateName: null,
|
||||
selectAllField: false,
|
||||
selectedEstimates: [],
|
||||
totalEstimates: 0,
|
||||
|
||||
@ -9,7 +9,7 @@ export const RESET_CUSTOMER = 'RESET_CUSTOMER'
|
||||
export const RESET_ITEM = 'RESET_ITEM'
|
||||
export const SET_CUSTOMER = 'SET_CUSTOMER'
|
||||
export const SET_ITEM = 'SET_ITEM'
|
||||
export const SET_TEMPLATE_ID = 'SET_TEMPLATE_ID'
|
||||
export const SET_TEMPLATE_NAME = 'SET_TEMPLATE_NAME'
|
||||
export const SELECT_CUSTOMER = 'SELECT_CUSTOMER'
|
||||
export const RESET_SELECTED_CUSTOMER = 'RESET_SELECTED_CUSTOMER'
|
||||
export const SET_SELECT_ALL_STATE = 'SET_SELECT_ALL_STATE'
|
||||
|
||||
@ -52,8 +52,8 @@ export default {
|
||||
state.selectAllField = false
|
||||
},
|
||||
|
||||
[types.SET_TEMPLATE_ID](state, templateId) {
|
||||
state.estimateTemplateId = templateId
|
||||
[types.SET_TEMPLATE_NAME](state, templateName) {
|
||||
state.estimateTemplateName = templateName
|
||||
},
|
||||
|
||||
[types.SELECT_CUSTOMER](state, data) {
|
||||
|
||||
@ -21,7 +21,7 @@ export const fetchInvoice = ({ commit, dispatch, state }, id) => {
|
||||
window.axios
|
||||
.get(`/api/v1/invoices/${id}`)
|
||||
.then((response) => {
|
||||
commit(types.SET_TEMPLATE_ID, response.data.invoice.invoice_template_id)
|
||||
commit(types.SET_TEMPLATE_NAME, response.data.invoice.template_name)
|
||||
resolve(response)
|
||||
})
|
||||
.catch((err) => {
|
||||
@ -219,7 +219,7 @@ export const resetCustomer = ({ commit, dispatch, state }) => {
|
||||
|
||||
export const setTemplate = ({ commit, dispatch, state }, data) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
commit(types.SET_TEMPLATE_ID, data)
|
||||
commit(types.SET_TEMPLATE_NAME, data)
|
||||
resolve({})
|
||||
})
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
export const invoices = (state) => state.invoices
|
||||
export const selectAllField = (state) => state.selectAllField
|
||||
export const getTemplateId = (state) => state.invoiceTemplateId
|
||||
export const getTemplateName = (state) => state.invoiceTemplateName
|
||||
export const selectedInvoices = (state) => state.selectedInvoices
|
||||
export const totalInvoices = (state) => state.totalInvoices
|
||||
export const selectedCustomer = (state) => state.selectedCustomer
|
||||
|
||||
@ -4,7 +4,7 @@ import * as getters from './getters'
|
||||
|
||||
const initialState = {
|
||||
invoices: [],
|
||||
invoiceTemplateId: 1,
|
||||
invoiceTemplateName: null,
|
||||
selectedInvoices: [],
|
||||
selectAllField: false,
|
||||
totalInvoices: 0,
|
||||
|
||||
@ -12,7 +12,7 @@ export const SET_CUSTOMER = 'SET_CUSTOMER'
|
||||
export const RESET_ITEM = 'RESET_ITEM'
|
||||
export const SET_ITEM = 'SET_ITEM'
|
||||
|
||||
export const SET_TEMPLATE_ID = 'SET_TEMPLATE_ID'
|
||||
export const SET_TEMPLATE_NAME = 'SET_TEMPLATE_NAME'
|
||||
|
||||
export const SELECT_CUSTOMER = 'SELECT_CUSTOMER'
|
||||
export const RESET_SELECTED_CUSTOMER = 'RESET_SELECTED_CUSTOMER'
|
||||
|
||||
@ -51,8 +51,8 @@ export default {
|
||||
state.selectedInvoices = []
|
||||
},
|
||||
|
||||
[types.SET_TEMPLATE_ID](state, templateId) {
|
||||
state.invoiceTemplateId = templateId
|
||||
[types.SET_TEMPLATE_NAME](state, templateName) {
|
||||
state.invoiceTemplateName = templateName
|
||||
},
|
||||
|
||||
[types.SELECT_CUSTOMER](state, data) {
|
||||
|
||||
@ -266,8 +266,8 @@
|
||||
variant="gray"
|
||||
@click="openTemplateModal"
|
||||
>
|
||||
<span class="flex text-black">
|
||||
{{ $t('estimates.estimate_template') }} {{ getTemplateId }}
|
||||
<span class="flex text-black capitalize">
|
||||
{{ getTemplateName }}
|
||||
<pencil-icon class="h-5 ml-2 -mr-1" />
|
||||
</span>
|
||||
</sw-button>
|
||||
@ -514,9 +514,9 @@ export default {
|
||||
...mapGetters('company', ['defaultCurrency']),
|
||||
|
||||
...mapGetters('estimate', [
|
||||
'getTemplateId',
|
||||
'selectedCustomer',
|
||||
'selectedNote',
|
||||
'getTemplateName',
|
||||
]),
|
||||
|
||||
...mapGetters('estimateTemplate', ['getEstimateTemplates']),
|
||||
@ -708,6 +708,7 @@ export default {
|
||||
'selectCustomer',
|
||||
'updateEstimate',
|
||||
'resetSelectedNote',
|
||||
'setTemplate',
|
||||
]),
|
||||
|
||||
...mapActions('item', ['fetchItems']),
|
||||
@ -789,6 +790,7 @@ export default {
|
||||
this.estimateNumAttribute = res4.data.nextNumber
|
||||
this.estimatePrefix = res4.data.prefix
|
||||
}
|
||||
this.setTemplate(this.getEstimateTemplates[0].name)
|
||||
} else {
|
||||
this.estimatePrefix = res4.data.prefix
|
||||
}
|
||||
@ -903,7 +905,7 @@ export default {
|
||||
total: this.total,
|
||||
tax: this.totalTax,
|
||||
user_id: null,
|
||||
estimate_template_id: this.getTemplateId,
|
||||
template_name: this.getTemplateName,
|
||||
}
|
||||
|
||||
if (this.selectedCustomer != null) {
|
||||
|
||||
@ -183,7 +183,7 @@ export default {
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters('estimate', ['getTemplateId', 'selectedCustomer']),
|
||||
...mapGetters('estimate', ['getTemplateName', 'selectedCustomer']),
|
||||
},
|
||||
|
||||
created() {
|
||||
|
||||
@ -259,7 +259,7 @@
|
||||
@click="openTemplateModal"
|
||||
>
|
||||
<span class="flex text-black">
|
||||
{{ $t('invoices.template') }} {{ getTemplateId }}
|
||||
{{ getTemplateName }}
|
||||
<pencil-icon class="h-5 ml-2 -mr-1" />
|
||||
</span>
|
||||
</sw-button>
|
||||
@ -510,7 +510,7 @@ export default {
|
||||
...mapGetters('notes', ['notes']),
|
||||
|
||||
...mapGetters('invoice', [
|
||||
'getTemplateId',
|
||||
'getTemplateName',
|
||||
'selectedCustomer',
|
||||
'selectedNote',
|
||||
]),
|
||||
@ -710,6 +710,7 @@ export default {
|
||||
'selectCustomer',
|
||||
'updateInvoice',
|
||||
'resetSelectedNote',
|
||||
'setTemplate',
|
||||
]),
|
||||
|
||||
...mapActions('invoiceTemplate', ['fetchInvoiceTemplates']),
|
||||
@ -784,6 +785,7 @@ export default {
|
||||
this.invoiceNumAttribute = res4.data.nextNumber
|
||||
this.invoicePrefix = res4.data.prefix
|
||||
}
|
||||
this.setTemplate(this.getInvoiceTemplates[0].name)
|
||||
} else {
|
||||
this.invoicePrefix = res4.data.prefix
|
||||
}
|
||||
@ -899,7 +901,7 @@ export default {
|
||||
total: this.total,
|
||||
tax: this.totalTax,
|
||||
user_id: null,
|
||||
invoice_template_id: this.getTemplateId,
|
||||
template_name: this.getTemplateName,
|
||||
}
|
||||
|
||||
if (this.selectedCustomer != null) {
|
||||
|
||||
@ -185,7 +185,7 @@ export default {
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters('invoice', ['getTemplateId', 'selectedCustomer']),
|
||||
...mapGetters('invoice', ['getTemplateName', 'selectedCustomer']),
|
||||
},
|
||||
|
||||
created() {
|
||||
|
||||
@ -51,7 +51,7 @@ test('create estimate', function () {
|
||||
->assertStatus(200);
|
||||
|
||||
$this->assertDatabaseHas('estimates', [
|
||||
'estimate_template_id' => $estimate['estimate_template_id'],
|
||||
'template_name' => $estimate['template_name'],
|
||||
'estimate_number' => $estimate['estimate_number'],
|
||||
'discount_type' => $estimate['discount_type'],
|
||||
'discount_val' => $estimate['discount_val'],
|
||||
@ -97,7 +97,7 @@ test('update estimate', function () {
|
||||
$newEstimate = $response->decodeResponseJson()['estimate'];
|
||||
|
||||
$this->assertDatabaseHas('estimates', [
|
||||
'estimate_template_id' => $estimate2['estimate_template_id'],
|
||||
'template_name' => $estimate2['template_name'],
|
||||
'estimate_number' => $estimate2['estimate_number'],
|
||||
'discount_type' => $estimate2['discount_type'],
|
||||
'discount_val' => $estimate2['discount_val'],
|
||||
|
||||
@ -46,7 +46,7 @@ test('create invoice', function () {
|
||||
$response->assertOk();
|
||||
|
||||
$this->assertDatabaseHas('invoices', [
|
||||
'invoice_template_id' => $invoice['invoice_template_id'],
|
||||
'template_name' => $invoice['template_name'],
|
||||
'invoice_number' => $invoice['invoice_number'],
|
||||
'sub_total' => $invoice['sub_total'],
|
||||
'discount' => $invoice['discount'],
|
||||
@ -78,7 +78,7 @@ test('create invoice as sent', function () {
|
||||
'tax' => $invoice['tax'],
|
||||
'discount' => $invoice['discount'],
|
||||
'user_id' => $invoice['user_id'],
|
||||
'invoice_template_id' => $invoice['invoice_template_id'],
|
||||
'template_name' => $invoice['template_name'],
|
||||
]);
|
||||
|
||||
$this->assertDatabaseHas('invoice_items', $invoice['items'][0]);
|
||||
@ -115,7 +115,7 @@ test('update invoice', function () {
|
||||
'tax' => $invoice2['tax'],
|
||||
'discount' => $invoice2['discount'],
|
||||
'user_id' => $invoice2['user_id'],
|
||||
'invoice_template_id' => $invoice2['invoice_template_id'],
|
||||
'template_name' => $invoice2['template_name'],
|
||||
]);
|
||||
|
||||
$this->assertDatabaseHas('invoice_items', $invoice2['items'][0]);
|
||||
|
||||
@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Crater\Models\EstimateTemplate;
|
||||
use Crater\Models\User;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Laravel\Sanctum\Sanctum;
|
||||
|
||||
beforeEach(function () {
|
||||
Artisan::call('db:seed', ['--class' => 'DatabaseSeeder', '--force' => true]);
|
||||
Artisan::call('db:seed', ['--class' => 'DemoSeeder', '--force' => true]);
|
||||
|
||||
$user = User::where('role', 'super admin')->first();
|
||||
$this->withHeaders([
|
||||
'company' => $user->company_id,
|
||||
]);
|
||||
Sanctum::actingAs(
|
||||
$user,
|
||||
['*']
|
||||
);
|
||||
});
|
||||
|
||||
test('estimate template has many estimates', function () {
|
||||
$estimateTemplate = EstimateTemplate::factory()->hasEstimates(5)->create();
|
||||
|
||||
$this->assertCount(5, $estimateTemplate->estimates);
|
||||
|
||||
$this->assertTrue($estimateTemplate->estimates()->exists());
|
||||
});
|
||||
@ -46,13 +46,6 @@ test('estimate has many taxes', function () {
|
||||
$this->assertTrue($estimate->taxes()->exists());
|
||||
});
|
||||
|
||||
test('estimate belongs to estimate template', function () {
|
||||
$estimate = Estimate::factory()->forEstimateTemplate()->create();
|
||||
|
||||
$this->assertTrue($estimate->estimateTemplate()->exists());
|
||||
});
|
||||
|
||||
|
||||
test('get next estimate number', function () {
|
||||
$estimate = Estimate::factory()->create();
|
||||
|
||||
@ -114,7 +107,7 @@ test('create estimate', function () {
|
||||
$this->assertDatabaseHas('estimates', [
|
||||
'estimate_number' => $estimate['estimate_number'],
|
||||
'user_id' => $estimate['user_id'],
|
||||
'estimate_template_id' => $estimate['estimate_template_id'],
|
||||
'template_name' => $estimate['template_name'],
|
||||
'sub_total' => $estimate['sub_total'],
|
||||
'total' => $estimate['total'],
|
||||
'discount' => $estimate['discount'],
|
||||
@ -162,7 +155,7 @@ test('update estimate', function () {
|
||||
$this->assertDatabaseHas('estimates', [
|
||||
'estimate_number' => $newEstimate['estimate_number'],
|
||||
'user_id' => $newEstimate['user_id'],
|
||||
'estimate_template_id' => $newEstimate['estimate_template_id'],
|
||||
'template_name' => $newEstimate['template_name'],
|
||||
'sub_total' => $newEstimate['sub_total'],
|
||||
'total' => $newEstimate['total'],
|
||||
'discount' => $newEstimate['discount'],
|
||||
|
||||
@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Crater\Models\InvoiceTemplate;
|
||||
use Crater\Models\User;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Laravel\Sanctum\Sanctum;
|
||||
|
||||
beforeEach(function () {
|
||||
Artisan::call('db:seed', ['--class' => 'DatabaseSeeder', '--force' => true]);
|
||||
Artisan::call('db:seed', ['--class' => 'DemoSeeder', '--force' => true]);
|
||||
|
||||
$user = User::where('role', 'super admin')->first();
|
||||
$this->withHeaders([
|
||||
'company' => $user->company_id,
|
||||
]);
|
||||
Sanctum::actingAs(
|
||||
$user,
|
||||
['*']
|
||||
);
|
||||
});
|
||||
|
||||
test('invoice template has many invoices', function () {
|
||||
$invoiceTemplate = InvoiceTemplate::factory()->hasInvoices(5)->create();
|
||||
|
||||
$this->assertCount(5, $invoiceTemplate->invoices);
|
||||
|
||||
$this->assertTrue($invoiceTemplate->invoices()->exists());
|
||||
});
|
||||
@ -54,12 +54,6 @@ test('invoice belongs to user', function () {
|
||||
$this->assertTrue($invoice->user()->exists());
|
||||
});
|
||||
|
||||
test('invoice belongs to invoice template', function () {
|
||||
$invoice = Invoice::factory()->forInvoiceTemplate()->create();
|
||||
|
||||
$this->assertTrue($invoice->invoiceTemplate()->exists());
|
||||
});
|
||||
|
||||
test('get next invoice number', function () {
|
||||
$invoice = Invoice::factory()->create();
|
||||
|
||||
@ -140,7 +134,7 @@ test('create invoice', function () {
|
||||
'discount' => $invoice['discount'],
|
||||
'notes' => $invoice['notes'],
|
||||
'user_id' => $invoice['user_id'],
|
||||
'invoice_template_id' => $invoice['invoice_template_id'],
|
||||
'template_name' => $invoice['template_name'],
|
||||
]);
|
||||
});
|
||||
|
||||
@ -191,7 +185,7 @@ test('update invoice', function () {
|
||||
'discount' => $newInvoice['discount'],
|
||||
'notes' => $newInvoice['notes'],
|
||||
'user_id' => $newInvoice['user_id'],
|
||||
'invoice_template_id' => $newInvoice['invoice_template_id'],
|
||||
'template_name' => $newInvoice['template_name'],
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
@ -33,8 +33,8 @@ test('estimate request validation rules', function () {
|
||||
'tax' => [
|
||||
'required',
|
||||
],
|
||||
'estimate_template_id' => [
|
||||
'required',
|
||||
'template_name' => [
|
||||
'required'
|
||||
],
|
||||
'items' => [
|
||||
'required',
|
||||
|
||||
@ -33,8 +33,8 @@ test('invoice request validation rules', function () {
|
||||
'tax' => [
|
||||
'required',
|
||||
],
|
||||
'invoice_template_id' => [
|
||||
'required',
|
||||
'template_name' => [
|
||||
'required'
|
||||
],
|
||||
'items' => [
|
||||
'required',
|
||||
|
||||