mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-06-04 23:04:36 -04:00
Proposals
This commit is contained in:
parent
11a3e9ab1e
commit
8f4cba1ed8
@ -52,14 +52,16 @@ class ProposalController extends BaseController
|
|||||||
|
|
||||||
public function create(ProposalRequest $request)
|
public function create(ProposalRequest $request)
|
||||||
{
|
{
|
||||||
|
$account = auth()->user()->account;
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'account' => auth()->user()->account,
|
'account' => $account,
|
||||||
'proposal' => null,
|
'proposal' => null,
|
||||||
'method' => 'POST',
|
'method' => 'POST',
|
||||||
'url' => 'proposals',
|
'url' => 'proposals',
|
||||||
'title' => trans('texts.new_proposal'),
|
'title' => trans('texts.new_proposal'),
|
||||||
'quotes' => Invoice::scope()->with('client.contacts')->quotes()->orderBy('id')->get(),
|
'quotes' => Invoice::scope()->with('client.contacts')->quotes()->orderBy('id')->get(),
|
||||||
'templates' => ProposalTemplate::scope()->orderBy('name')->get(),
|
'templates' => ProposalTemplate::whereAccountId($account->id)->orWhereNull('account_id')->orderBy('name')->get(),
|
||||||
'quotePublicId' => $request->quote_id,
|
'quotePublicId' => $request->quote_id,
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -75,16 +77,17 @@ class ProposalController extends BaseController
|
|||||||
|
|
||||||
public function edit(ProposalRequest $request)
|
public function edit(ProposalRequest $request)
|
||||||
{
|
{
|
||||||
|
$account = auth()->user()->account;
|
||||||
$proposal = $request->entity();
|
$proposal = $request->entity();
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'account' => auth()->user()->account,
|
'account' => $account,
|
||||||
'proposal' => $proposal,
|
'proposal' => $proposal,
|
||||||
'method' => 'PUT',
|
'method' => 'PUT',
|
||||||
'url' => 'proposals/' . $proposal->public_id,
|
'url' => 'proposals/' . $proposal->public_id,
|
||||||
'title' => trans('texts.edit_proposal'),
|
'title' => trans('texts.edit_proposal'),
|
||||||
'clients' => Client::scope()->with('contacts')->orderBy('name')->get(),
|
'quotes' => Invoice::scope()->with('client.contacts')->quotes()->orderBy('id')->get(),
|
||||||
'clientPublicId' => $proposal->client ? $proposal->client->public_id : null,
|
'templates' => ProposalTemplate::whereAccountId($account->id)->orWhereNull('account_id')->orderBy('name')->get(),
|
||||||
];
|
];
|
||||||
|
|
||||||
return View::make('proposals.edit', $data);
|
return View::make('proposals.edit', $data);
|
||||||
|
@ -22,6 +22,7 @@ class Proposal extends EntityModel
|
|||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
|
'template_id',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
namespace App\Ninja\Repositories;
|
namespace App\Ninja\Repositories;
|
||||||
|
|
||||||
use App\Models\Proposal;
|
use App\Models\Proposal;
|
||||||
|
use App\Models\Invoice;
|
||||||
use Auth;
|
use Auth;
|
||||||
use DB;
|
use DB;
|
||||||
use Utils;
|
use Utils;
|
||||||
@ -62,13 +63,16 @@ class ProposalRepository extends BaseRepository
|
|||||||
|
|
||||||
public function save($input, $proposal = false)
|
public function save($input, $proposal = false)
|
||||||
{
|
{
|
||||||
$publicId = isset($data['public_id']) ? $data['public_id'] : false;
|
|
||||||
|
|
||||||
if (! $proposal) {
|
if (! $proposal) {
|
||||||
$proposal = Proposal::createNew();
|
$proposal = Proposal::createNew();
|
||||||
}
|
}
|
||||||
|
|
||||||
$proposal->fill($input);
|
$proposal->fill($input);
|
||||||
|
|
||||||
|
if (isset($input['quote_id'])) {
|
||||||
|
$proposal->quote_id = $input['quote_id'] ? Invoice::getPrivateId($input['quote_id']) : null;
|
||||||
|
}
|
||||||
|
|
||||||
$proposal->save();
|
$proposal->save();
|
||||||
|
|
||||||
return $proposal;
|
return $proposal;
|
||||||
|
@ -49,7 +49,7 @@ class AddSubscriptionFormat extends Migration
|
|||||||
$table->unsignedInteger('proposal_category_id');
|
$table->unsignedInteger('proposal_category_id');
|
||||||
$table->string('name');
|
$table->string('name');
|
||||||
$table->text('private_notes');
|
$table->text('private_notes');
|
||||||
|
|
||||||
$table->mediumText('html');
|
$table->mediumText('html');
|
||||||
$table->mediumText('css');
|
$table->mediumText('css');
|
||||||
|
|
||||||
@ -62,15 +62,14 @@ class AddSubscriptionFormat extends Migration
|
|||||||
|
|
||||||
Schema::create('proposal_templates', function ($table) {
|
Schema::create('proposal_templates', function ($table) {
|
||||||
$table->increments('id');
|
$table->increments('id');
|
||||||
$table->unsignedInteger('account_id');
|
$table->unsignedInteger('account_id')->nullable();
|
||||||
$table->unsignedInteger('user_id');
|
$table->unsignedInteger('user_id')->nullable();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
$table->softDeletes();
|
$table->softDeletes();
|
||||||
$table->boolean('is_deleted')->default(false);
|
$table->boolean('is_deleted')->default(false);
|
||||||
$table->text('private_notes');
|
$table->text('private_notes');
|
||||||
|
|
||||||
$table->string('name');
|
$table->string('name');
|
||||||
$table->text('tags');
|
|
||||||
$table->mediumText('html');
|
$table->mediumText('html');
|
||||||
$table->mediumText('css');
|
$table->mediumText('css');
|
||||||
|
|
||||||
@ -90,7 +89,7 @@ class AddSubscriptionFormat extends Migration
|
|||||||
$table->boolean('is_deleted')->default(false);
|
$table->boolean('is_deleted')->default(false);
|
||||||
|
|
||||||
$table->unsignedInteger('quote_id')->index();
|
$table->unsignedInteger('quote_id')->index();
|
||||||
$table->unsignedInteger('temlate_id')->index();
|
$table->unsignedInteger('template_id')->index();
|
||||||
$table->text('private_notes');
|
$table->text('private_notes');
|
||||||
$table->mediumText('html');
|
$table->mediumText('html');
|
||||||
$table->mediumText('css');
|
$table->mediumText('css');
|
||||||
@ -98,7 +97,7 @@ class AddSubscriptionFormat extends Migration
|
|||||||
$table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
|
$table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
|
||||||
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||||
$table->foreign('quote_id')->references('id')->on('invoices')->onDelete('cascade');
|
$table->foreign('quote_id')->references('id')->on('invoices')->onDelete('cascade');
|
||||||
$table->foreign('temlate_id')->references('id')->on('proposal_templates')->onDelete('cascade');
|
$table->foreign('template_id')->references('id')->on('proposal_templates')->onDelete('cascade');
|
||||||
|
|
||||||
$table->unsignedInteger('public_id')->index();
|
$table->unsignedInteger('public_id')->index();
|
||||||
$table->unique(['account_id', 'public_id']);
|
$table->unique(['account_id', 'public_id']);
|
||||||
|
56
database/seeds/ProposalTemplatesSeeder.php
Normal file
56
database/seeds/ProposalTemplatesSeeder.php
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\ProposalTemplate;
|
||||||
|
|
||||||
|
class ProposalTemplatesSeeder extends Seeder
|
||||||
|
{
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
Eloquent::unguard();
|
||||||
|
|
||||||
|
$designs = [
|
||||||
|
'Clean',
|
||||||
|
'Bold',
|
||||||
|
'Modern',
|
||||||
|
'Plain',
|
||||||
|
'Business',
|
||||||
|
'Creative',
|
||||||
|
'Elegant',
|
||||||
|
'Hipster',
|
||||||
|
'Playful',
|
||||||
|
'Photo',
|
||||||
|
];
|
||||||
|
|
||||||
|
for ($i = 0; $i < count($designs); $i++) {
|
||||||
|
$design = $designs[$i];
|
||||||
|
$fileName = storage_path() . '/templates/' . strtolower($design) . '.js';
|
||||||
|
if (file_exists($fileName)) {
|
||||||
|
$pdfmake = file_get_contents($fileName);
|
||||||
|
if ($pdfmake) {
|
||||||
|
$record = InvoiceDesign::whereName($design)->first();
|
||||||
|
if (! $record) {
|
||||||
|
$record = new InvoiceDesign();
|
||||||
|
$record->id = $i + 1;
|
||||||
|
$record->name = $design;
|
||||||
|
}
|
||||||
|
$record->pdfmake = json_encode(json_decode($pdfmake)); // remove the white space
|
||||||
|
$record->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ($i = 1; $i <= 3; $i++) {
|
||||||
|
$name = 'Custom' . $i;
|
||||||
|
$id = $i + 10;
|
||||||
|
|
||||||
|
if (InvoiceDesign::whereName($name)->orWhere('id', '=', $id)->first()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
InvoiceDesign::create([
|
||||||
|
'id' => $id,
|
||||||
|
'name' => $name,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2700,13 +2700,13 @@ $LANG = array(
|
|||||||
'archive_proposal_template' => 'Archive Template',
|
'archive_proposal_template' => 'Archive Template',
|
||||||
'delete_proposal_template' => 'Delete Template',
|
'delete_proposal_template' => 'Delete Template',
|
||||||
'restored_proposal_template' => 'Restore Template',
|
'restored_proposal_template' => 'Restore Template',
|
||||||
'created_proposal_template' => 'Successfully created temlate',
|
'created_proposal_template' => 'Successfully created template',
|
||||||
'updated_proposal_template' => 'Successfully updated temlate',
|
'updated_proposal_template' => 'Successfully updated template',
|
||||||
'archived_proposal_template' => 'Successfully archived temlate',
|
'archived_proposal_template' => 'Successfully archived template',
|
||||||
'deleted_proposal_template' => 'Successfully archived temlate',
|
'deleted_proposal_template' => 'Successfully archived template',
|
||||||
'archived_proposal_templates' => 'Successfully archived :count temlates',
|
'archived_proposal_templates' => 'Successfully archived :count templates',
|
||||||
'deleted_proposal_templates' => 'Successfully archived :count temlates',
|
'deleted_proposal_templates' => 'Successfully archived :count templates',
|
||||||
'restored_proposal_template' => 'Successfully restored temlate',
|
'restored_proposal_template' => 'Successfully restored template',
|
||||||
'proposal_category' => 'Category',
|
'proposal_category' => 'Category',
|
||||||
'proposal_categories' => 'Categories',
|
'proposal_categories' => 'Categories',
|
||||||
'new_proposal_category' => 'New Category',
|
'new_proposal_category' => 'New Category',
|
||||||
|
@ -19,7 +19,13 @@
|
|||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
|
|
||||||
{!! Former::open() !!}
|
{!! Former::open($url)
|
||||||
|
->method($method)
|
||||||
|
->id('mainForm')
|
||||||
|
->rules([
|
||||||
|
'quote_id' => 'required',
|
||||||
|
'template_id' => 'required',
|
||||||
|
]) !!}
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-12">
|
<div class="col-lg-12">
|
||||||
@ -30,13 +36,13 @@
|
|||||||
{!! Former::select('quote_id')->addOption('', '')
|
{!! Former::select('quote_id')->addOption('', '')
|
||||||
->label(trans('texts.quote'))
|
->label(trans('texts.quote'))
|
||||||
->addGroupClass('quote-select') !!}
|
->addGroupClass('quote-select') !!}
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6">
|
|
||||||
{!! Former::select('template_id')->addOption('', '')
|
{!! Former::select('template_id')->addOption('', '')
|
||||||
->label(trans('texts.template'))
|
->label(trans('texts.template'))
|
||||||
->addGroupClass('template-select') !!}
|
->addGroupClass('template-select') !!}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -65,8 +71,12 @@
|
|||||||
var templates = {!! $templates !!};
|
var templates = {!! $templates !!};
|
||||||
var templateMap = {};
|
var templateMap = {};
|
||||||
|
|
||||||
|
function onSaveClick() {
|
||||||
|
$('#mainForm').submit();
|
||||||
|
}
|
||||||
|
|
||||||
$(function() {
|
$(function() {
|
||||||
var quoteId = {{ $quotePublicId ?: 0 }};
|
var quoteId = {{ ! empty($quotePublicId) ? $quotePublicId : 0 }};
|
||||||
var $quoteSelect = $('select#quote_id');
|
var $quoteSelect = $('select#quote_id');
|
||||||
for (var i = 0; i < quotes.length; i++) {
|
for (var i = 0; i < quotes.length; i++) {
|
||||||
var quote = quotes[i];
|
var quote = quotes[i];
|
||||||
@ -79,7 +89,7 @@
|
|||||||
for (var i = 0; i < templates.length; i++) {
|
for (var i = 0; i < templates.length; i++) {
|
||||||
var template = templates[i];
|
var template = templates[i];
|
||||||
templateMap[template.public_id] = template;
|
templateMap[template.public_id] = template;
|
||||||
$templateSelect.append(new Option(template.name, template.public_id));
|
$proposal_templateSelect.append(new Option(template.name, template.public_id));
|
||||||
}
|
}
|
||||||
@include('partials/entity_combobox', ['entityType' => ENTITY_PROPOSAL_TEMPLATE])
|
@include('partials/entity_combobox', ['entityType' => ENTITY_PROPOSAL_TEMPLATE])
|
||||||
|
|
||||||
|
@ -19,7 +19,13 @@
|
|||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
|
|
||||||
{!! Former::open() !!}
|
{!! Former::open($url)
|
||||||
|
->method($method)
|
||||||
|
->id('mainForm')
|
||||||
|
->rules([
|
||||||
|
'quote_id' => 'required',
|
||||||
|
'template_id' => 'required',
|
||||||
|
]) !!}
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-12">
|
<div class="col-lg-12">
|
||||||
|
@ -19,7 +19,13 @@
|
|||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
|
|
||||||
{!! Former::open() !!}
|
{!! Former::open($url)
|
||||||
|
->method($method)
|
||||||
|
->id('mainForm')
|
||||||
|
->rules([
|
||||||
|
'quote_id' => 'required',
|
||||||
|
'template_id' => 'required',
|
||||||
|
]) !!}
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-12">
|
<div class="col-lg-12">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user