mirror of
https://github.com/crater-invoice/crater.git
synced 2025-10-27 11:41:09 -04:00
Refactor Customization Page
This commit is contained in:
@ -54,10 +54,13 @@ class Estimate extends Model
|
|||||||
'sub_total' => 'float'
|
'sub_total' => 'float'
|
||||||
];
|
];
|
||||||
|
|
||||||
public static function getNextEstimateNumber()
|
public static function getNextEstimateNumber($value)
|
||||||
{
|
{
|
||||||
// Get the last created order
|
// Get the last created order
|
||||||
$lastOrder = Estimate::orderBy('created_at', 'desc')->first();
|
$lastOrder = Estimate::where('estimate_number', 'LIKE', $value . '-%')
|
||||||
|
->orderBy('created_at', 'desc')
|
||||||
|
->first();
|
||||||
|
|
||||||
if (!$lastOrder) {
|
if (!$lastOrder) {
|
||||||
// We get here if there is no order at all
|
// We get here if there is no order at all
|
||||||
// If there is no number set it to 0, which will be 1 at the end.
|
// If there is no number set it to 0, which will be 1 at the end.
|
||||||
@ -99,10 +102,16 @@ class Estimate extends Model
|
|||||||
|
|
||||||
public function getEstimateNumAttribute()
|
public function getEstimateNumAttribute()
|
||||||
{
|
{
|
||||||
$position = $this->strposX($this->estimate_number, "-", 2) + 1;
|
$position = $this->strposX($this->estimate_number, "-", 1) + 1;
|
||||||
return substr($this->estimate_number, $position);
|
return substr($this->estimate_number, $position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getEstimatePrefixAttribute()
|
||||||
|
{
|
||||||
|
$prefix = explode("-",$this->estimate_number)[0];
|
||||||
|
return $prefix;
|
||||||
|
}
|
||||||
|
|
||||||
private function strposX($haystack, $needle, $number)
|
private function strposX($haystack, $needle, $number)
|
||||||
{
|
{
|
||||||
if ($number == '1') {
|
if ($number == '1') {
|
||||||
|
|||||||
@ -157,12 +157,8 @@ class CompanyController extends Controller
|
|||||||
{
|
{
|
||||||
$invoice_prefix = CompanySetting::getSetting('invoice_prefix', $request->header('company'));
|
$invoice_prefix = CompanySetting::getSetting('invoice_prefix', $request->header('company'));
|
||||||
$invoice_auto_generate = CompanySetting::getSetting('invoice_auto_generate', $request->header('company'));
|
$invoice_auto_generate = CompanySetting::getSetting('invoice_auto_generate', $request->header('company'));
|
||||||
$invoice_notes = CompanySetting::getSetting('invoice_notes', $request->header('company'), true);
|
|
||||||
$invoice_terms_and_conditions = CompanySetting::getSetting('invoice_terms_and_conditions', $request->header('company'), true);
|
|
||||||
|
|
||||||
$estimate_prefix = CompanySetting::getSetting('estimate_prefix', $request->header('company'));
|
$estimate_prefix = CompanySetting::getSetting('estimate_prefix', $request->header('company'));
|
||||||
$estimate_notes = CompanySetting::getSetting('estimate_notes', $request->header('company'), true);
|
|
||||||
$estimate_terms_and_conditions = CompanySetting::getSetting('estimate_terms_and_conditions', $request->header('company'), true);
|
|
||||||
$estimate_auto_generate = CompanySetting::getSetting('estimate_auto_generate', $request->header('company'));
|
$estimate_auto_generate = CompanySetting::getSetting('estimate_auto_generate', $request->header('company'));
|
||||||
|
|
||||||
$payment_prefix = CompanySetting::getSetting('payment_prefix', $request->header('company'));
|
$payment_prefix = CompanySetting::getSetting('payment_prefix', $request->header('company'));
|
||||||
@ -175,12 +171,8 @@ class CompanyController extends Controller
|
|||||||
return response()->json([
|
return response()->json([
|
||||||
'invoice_prefix' => $invoice_prefix,
|
'invoice_prefix' => $invoice_prefix,
|
||||||
'invoice_auto_generate' => $invoice_auto_generate,
|
'invoice_auto_generate' => $invoice_auto_generate,
|
||||||
'invoice_notes' => $invoice_notes,
|
|
||||||
'invoice_terms_and_conditions' => $invoice_terms_and_conditions,
|
|
||||||
'estimate_prefix' => $estimate_prefix,
|
'estimate_prefix' => $estimate_prefix,
|
||||||
'estimate_auto_generate' => $estimate_auto_generate,
|
'estimate_auto_generate' => $estimate_auto_generate,
|
||||||
'estimate_notes' => $estimate_notes,
|
|
||||||
'estimate_terms_and_conditions' => $estimate_terms_and_conditions,
|
|
||||||
'payment_prefix' => $payment_prefix,
|
'payment_prefix' => $payment_prefix,
|
||||||
'payment_auto_generate' => $payment_auto_generate,
|
'payment_auto_generate' => $payment_auto_generate,
|
||||||
'billing_address_format' => $billing_address_format,
|
'billing_address_format' => $billing_address_format,
|
||||||
@ -200,14 +192,10 @@ class CompanyController extends Controller
|
|||||||
} elseif ($request->type == "INVOICES") {
|
} elseif ($request->type == "INVOICES") {
|
||||||
$sets = [
|
$sets = [
|
||||||
'invoice_prefix',
|
'invoice_prefix',
|
||||||
'invoice_notes',
|
|
||||||
'invoice_terms_and_conditions'
|
|
||||||
];
|
];
|
||||||
} elseif ($request->type == "ESTIMATES") {
|
} elseif ($request->type == "ESTIMATES") {
|
||||||
$sets = [
|
$sets = [
|
||||||
'estimate_prefix',
|
'estimate_prefix',
|
||||||
'estimate_notes',
|
|
||||||
'estimate_terms_and_conditions'
|
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
$sets = [
|
$sets = [
|
||||||
|
|||||||
@ -56,25 +56,41 @@ class EstimatesController extends Controller
|
|||||||
|
|
||||||
public function create(Request $request)
|
public function create(Request $request)
|
||||||
{
|
{
|
||||||
$nextEstimateNumber = 'EST-'.Estimate::getNextEstimateNumber();
|
$estimate_prefix = CompanySetting::getSetting('estimate_prefix', $request->header('company'));
|
||||||
|
$estimate_num_auto_generate = CompanySetting::getSetting('estimate_auto_generate', $request->header('company'));
|
||||||
|
|
||||||
|
$nextEstimateNumberAttribute = null;
|
||||||
|
|
||||||
|
if ($estimate_num_auto_generate == "YES") {
|
||||||
|
$nextEstimateNumberAttribute = Estimate::getNextEstimateNumber($estimate_prefix);
|
||||||
|
}
|
||||||
|
|
||||||
$tax_per_item = CompanySetting::getSetting('tax_per_item', $request->header('company'));
|
$tax_per_item = CompanySetting::getSetting('tax_per_item', $request->header('company'));
|
||||||
$discount_per_item = CompanySetting::getSetting('discount_per_item', $request->header('company'));
|
$discount_per_item = CompanySetting::getSetting('discount_per_item', $request->header('company'));
|
||||||
$customers = User::where('role', 'customer')->get();
|
$customers = User::where('role', 'customer')->get();
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'customers' => $customers,
|
'customers' => $customers,
|
||||||
'nextEstimateNumber' => $nextEstimateNumber,
|
'nextEstimateNumber' => $nextEstimateNumberAttribute,
|
||||||
'taxes' => Tax::whereCompany($request->header('company'))->latest()->get(),
|
'taxes' => Tax::whereCompany($request->header('company'))->latest()->get(),
|
||||||
'items' => Item::whereCompany($request->header('company'))->get(),
|
'items' => Item::whereCompany($request->header('company'))->get(),
|
||||||
'tax_per_item' => $tax_per_item,
|
'tax_per_item' => $tax_per_item,
|
||||||
'discount_per_item' => $discount_per_item,
|
'discount_per_item' => $discount_per_item,
|
||||||
'estimateTemplates' => EstimateTemplate::all(),
|
'estimateTemplates' => EstimateTemplate::all(),
|
||||||
'shareable_link' => ''
|
'shareable_link' => '',
|
||||||
|
'estimate_prefix' => $estimate_prefix
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function store(EstimatesRequest $request)
|
public function store(EstimatesRequest $request)
|
||||||
{
|
{
|
||||||
|
$estimate_number = explode("-",$request->estimate_number);
|
||||||
|
$number_attributes['estimate_number'] = $estimate_number[0].'-'.sprintf('%06d', intval($estimate_number[1]));
|
||||||
|
|
||||||
|
Validator::make($number_attributes, [
|
||||||
|
'estimate_number' => 'required|unique:estimates,estimate_number'
|
||||||
|
])->validate();
|
||||||
|
|
||||||
$estimate_date = Carbon::createFromFormat('d/m/Y', $request->estimate_date);
|
$estimate_date = Carbon::createFromFormat('d/m/Y', $request->estimate_date);
|
||||||
$expiry_date = Carbon::createFromFormat('d/m/Y', $request->expiry_date);
|
$expiry_date = Carbon::createFromFormat('d/m/Y', $request->expiry_date);
|
||||||
$status = Estimate::STATUS_DRAFT;
|
$status = Estimate::STATUS_DRAFT;
|
||||||
@ -101,7 +117,7 @@ class EstimatesController extends Controller
|
|||||||
$estimate = Estimate::create([
|
$estimate = Estimate::create([
|
||||||
'estimate_date' => $estimate_date,
|
'estimate_date' => $estimate_date,
|
||||||
'expiry_date' => $expiry_date,
|
'expiry_date' => $expiry_date,
|
||||||
'estimate_number' => $request->estimate_number,
|
'estimate_number' => $number_attributes['estimate_number'],
|
||||||
'reference_number' => $request->reference_number,
|
'reference_number' => $request->reference_number,
|
||||||
'user_id' => $request->user_id,
|
'user_id' => $request->user_id,
|
||||||
'company_id' => $request->header('company'),
|
'company_id' => $request->header('company'),
|
||||||
@ -216,26 +232,33 @@ class EstimatesController extends Controller
|
|||||||
|
|
||||||
return response()->json( [
|
return response()->json( [
|
||||||
'customers' => $customers,
|
'customers' => $customers,
|
||||||
'nextEstimateNumber' => $estimate->estimate_number,
|
'nextEstimateNumber' => $estimate->getEstimateNumAttribute(),
|
||||||
'taxes' => Tax::latest()->whereCompany($request->header('company'))->get(),
|
'taxes' => Tax::latest()->whereCompany($request->header('company'))->get(),
|
||||||
'estimate' => $estimate,
|
'estimate' => $estimate,
|
||||||
'items' => Item::whereCompany($request->header('company'))->latest()->get(),
|
'items' => Item::whereCompany($request->header('company'))->latest()->get(),
|
||||||
'estimateTemplates' => EstimateTemplate::all(),
|
'estimateTemplates' => EstimateTemplate::all(),
|
||||||
'tax_per_item' => $estimate->tax_per_item,
|
'tax_per_item' => $estimate->tax_per_item,
|
||||||
'discount_per_item' => $estimate->discount_per_item,
|
'discount_per_item' => $estimate->discount_per_item,
|
||||||
'shareable_link' => url('/estimates/pdf/'.$estimate->unique_hash)
|
'shareable_link' => url('/estimates/pdf/'.$estimate->unique_hash),
|
||||||
|
'estimate_prefix' => $estimate->getEstimatePrefixAttribute()
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update(EstimatesRequest $request, $id)
|
public function update(EstimatesRequest $request, $id)
|
||||||
{
|
{
|
||||||
|
$estimate_number = explode("-",$request->estimate_number);
|
||||||
|
$number_attributes['estimate_number'] = $estimate_number[0].'-'.sprintf('%06d', intval($estimate_number[1]));
|
||||||
|
Validator::make($number_attributes, [
|
||||||
|
'estimate_number' => 'required|unique:estimates,estimate_number'.','.$id
|
||||||
|
])->validate();
|
||||||
|
|
||||||
$estimate_date = Carbon::createFromFormat('d/m/Y', $request->estimate_date);
|
$estimate_date = Carbon::createFromFormat('d/m/Y', $request->estimate_date);
|
||||||
$expiry_date = Carbon::createFromFormat('d/m/Y', $request->expiry_date);
|
$expiry_date = Carbon::createFromFormat('d/m/Y', $request->expiry_date);
|
||||||
|
|
||||||
$estimate = Estimate::find($id);
|
$estimate = Estimate::find($id);
|
||||||
$estimate->estimate_date = $estimate_date;
|
$estimate->estimate_date = $estimate_date;
|
||||||
$estimate->expiry_date = $expiry_date;
|
$estimate->expiry_date = $expiry_date;
|
||||||
$estimate->estimate_number = $request->estimate_number;
|
$estimate->estimate_number = $number_attributes['estimate_number'];
|
||||||
$estimate->reference_number = $request->reference_number;
|
$estimate->reference_number = $request->reference_number;
|
||||||
$estimate->user_id = $request->user_id;
|
$estimate->user_id = $request->user_id;
|
||||||
$estimate->estimate_template_id = $request->estimate_template_id;
|
$estimate->estimate_template_id = $request->estimate_template_id;
|
||||||
|
|||||||
@ -66,14 +66,22 @@ class InvoicesController extends Controller
|
|||||||
{
|
{
|
||||||
$tax_per_item = CompanySetting::getSetting('tax_per_item', $request->header('company'));
|
$tax_per_item = CompanySetting::getSetting('tax_per_item', $request->header('company'));
|
||||||
$discount_per_item = CompanySetting::getSetting('discount_per_item', $request->header('company'));
|
$discount_per_item = CompanySetting::getSetting('discount_per_item', $request->header('company'));
|
||||||
$nextInvoiceNumber = "INV-".Invoice::getNextInvoiceNumber();
|
$invoice_prefix = CompanySetting::getSetting('invoice_prefix', $request->header('company'));
|
||||||
|
$invoice_num_auto_generate = CompanySetting::getSetting('invoice_auto_generate', $request->header('company'));
|
||||||
|
|
||||||
|
$nextInvoiceNumberAttribute = null;
|
||||||
|
|
||||||
|
if ($invoice_num_auto_generate == "YES") {
|
||||||
|
$nextInvoiceNumberAttribute = Invoice::getNextInvoiceNumber($invoice_prefix);
|
||||||
|
}
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'nextInvoiceNumber' => $nextInvoiceNumber,
|
'nextInvoiceNumber' => $nextInvoiceNumberAttribute,
|
||||||
'items' => Item::with('taxes')->whereCompany($request->header('company'))->get(),
|
'items' => Item::with('taxes')->whereCompany($request->header('company'))->get(),
|
||||||
'invoiceTemplates' => InvoiceTemplate::all(),
|
'invoiceTemplates' => InvoiceTemplate::all(),
|
||||||
'tax_per_item' => $tax_per_item,
|
'tax_per_item' => $tax_per_item,
|
||||||
'discount_per_item' => $discount_per_item
|
'discount_per_item' => $discount_per_item,
|
||||||
|
'invoice_prefix' => $invoice_prefix
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,6 +93,13 @@ class InvoicesController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function store(Requests\InvoicesRequest $request)
|
public function store(Requests\InvoicesRequest $request)
|
||||||
{
|
{
|
||||||
|
$invoice_number = explode("-",$request->invoice_number);
|
||||||
|
$number_attributes['invoice_number'] = $invoice_number[0].'-'.sprintf('%06d', intval($invoice_number[1]));
|
||||||
|
|
||||||
|
Validator::make($number_attributes, [
|
||||||
|
'invoice_number' => 'required|unique:invoices,invoice_number'
|
||||||
|
])->validate();
|
||||||
|
|
||||||
$invoice_date = Carbon::createFromFormat('d/m/Y', $request->invoice_date);
|
$invoice_date = Carbon::createFromFormat('d/m/Y', $request->invoice_date);
|
||||||
$due_date = Carbon::createFromFormat('d/m/Y', $request->due_date);
|
$due_date = Carbon::createFromFormat('d/m/Y', $request->due_date);
|
||||||
$status = Invoice::STATUS_DRAFT;
|
$status = Invoice::STATUS_DRAFT;
|
||||||
@ -99,7 +114,7 @@ class InvoicesController extends Controller
|
|||||||
$invoice = Invoice::create([
|
$invoice = Invoice::create([
|
||||||
'invoice_date' => $invoice_date,
|
'invoice_date' => $invoice_date,
|
||||||
'due_date' => $due_date,
|
'due_date' => $due_date,
|
||||||
'invoice_number' => $request->invoice_number,
|
'invoice_number' => $number_attributes['invoice_number'],
|
||||||
'reference_number' => $request->reference_number,
|
'reference_number' => $request->reference_number,
|
||||||
'user_id' => $request->user_id,
|
'user_id' => $request->user_id,
|
||||||
'company_id' => $request->header('company'),
|
'company_id' => $request->header('company'),
|
||||||
@ -222,12 +237,13 @@ class InvoicesController extends Controller
|
|||||||
])->find($id);
|
])->find($id);
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'nextInvoiceNumber' => $invoice->invoice_number,
|
'nextInvoiceNumber' => $invoice->getInvoiceNumAttribute(),
|
||||||
'invoice' => $invoice,
|
'invoice' => $invoice,
|
||||||
'invoiceTemplates' => InvoiceTemplate::all(),
|
'invoiceTemplates' => InvoiceTemplate::all(),
|
||||||
'tax_per_item' => $invoice->tax_per_item,
|
'tax_per_item' => $invoice->tax_per_item,
|
||||||
'discount_per_item' => $invoice->discount_per_item,
|
'discount_per_item' => $invoice->discount_per_item,
|
||||||
'shareable_link' => url('/invoices/pdf/'.$invoice->unique_hash)
|
'shareable_link' => url('/invoices/pdf/'.$invoice->unique_hash),
|
||||||
|
'invoice_prefix' => $invoice->getInvoicePrefixAttribute()
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,6 +256,13 @@ class InvoicesController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function update(Requests\InvoicesRequest $request, $id)
|
public function update(Requests\InvoicesRequest $request, $id)
|
||||||
{
|
{
|
||||||
|
$invoice_number = explode("-",$request->invoice_number);
|
||||||
|
$number_attributes['invoice_number'] = $invoice_number[0].'-'.sprintf('%06d', intval($invoice_number[1]));
|
||||||
|
|
||||||
|
Validator::make($number_attributes, [
|
||||||
|
'invoice_number' => 'required|unique:invoices,invoice_number'.','.$id
|
||||||
|
])->validate();
|
||||||
|
|
||||||
$invoice_date = Carbon::createFromFormat('d/m/Y', $request->invoice_date);
|
$invoice_date = Carbon::createFromFormat('d/m/Y', $request->invoice_date);
|
||||||
$due_date = Carbon::createFromFormat('d/m/Y', $request->due_date);
|
$due_date = Carbon::createFromFormat('d/m/Y', $request->due_date);
|
||||||
|
|
||||||
@ -268,7 +291,7 @@ class InvoicesController extends Controller
|
|||||||
|
|
||||||
$invoice->invoice_date = $invoice_date;
|
$invoice->invoice_date = $invoice_date;
|
||||||
$invoice->due_date = $due_date;
|
$invoice->due_date = $due_date;
|
||||||
$invoice->invoice_number = $request->invoice_number;
|
$invoice->invoice_number = $number_attributes['invoice_number'];
|
||||||
$invoice->reference_number = $request->reference_number;
|
$invoice->reference_number = $request->reference_number;
|
||||||
$invoice->user_id = $request->user_id;
|
$invoice->user_id = $request->user_id;
|
||||||
$invoice->invoice_template_id = $request->invoice_template_id;
|
$invoice->invoice_template_id = $request->invoice_template_id;
|
||||||
|
|||||||
@ -10,6 +10,7 @@ use Carbon\Carbon;
|
|||||||
use function MongoDB\BSON\toJSON;
|
use function MongoDB\BSON\toJSON;
|
||||||
use Crater\User;
|
use Crater\User;
|
||||||
use Crater\Http\Requests\PaymentRequest;
|
use Crater\Http\Requests\PaymentRequest;
|
||||||
|
use Validator;
|
||||||
|
|
||||||
class PaymentController extends Controller
|
class PaymentController extends Controller
|
||||||
{
|
{
|
||||||
@ -50,13 +51,22 @@ class PaymentController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function create(Request $request)
|
public function create(Request $request)
|
||||||
{
|
{
|
||||||
$nextPaymentNumber = 'PAY-'.Payment::getNextPaymentNumber();
|
$payment_prefix = CompanySetting::getSetting('payment_prefix', $request->header('company'));
|
||||||
|
$payment_num_auto_generate = CompanySetting::getSetting('payment_auto_generate', $request->header('company'));
|
||||||
|
|
||||||
|
|
||||||
|
$nextPaymentNumberAttribute = null;
|
||||||
|
|
||||||
|
if ($payment_num_auto_generate == "YES") {
|
||||||
|
$nextPaymentNumberAttribute = Payment::getNextPaymentNumber($payment_prefix);
|
||||||
|
}
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'customers' => User::where('role', 'customer')
|
'customers' => User::where('role', 'customer')
|
||||||
->whereCompany($request->header('company'))
|
->whereCompany($request->header('company'))
|
||||||
->get(),
|
->get(),
|
||||||
'nextPaymentNumber' => $nextPaymentNumber
|
'nextPaymentNumber' => $nextPaymentNumberAttribute,
|
||||||
|
'payment_prefix' => $payment_prefix
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,6 +78,13 @@ class PaymentController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function store(PaymentRequest $request)
|
public function store(PaymentRequest $request)
|
||||||
{
|
{
|
||||||
|
$payment_number = explode("-",$request->payment_number);
|
||||||
|
$number_attributes['payment_number'] = $payment_number[0].'-'.sprintf('%06d', intval($payment_number[1]));
|
||||||
|
|
||||||
|
Validator::make($number_attributes, [
|
||||||
|
'payment_number' => 'required|unique:payments,payment_number'
|
||||||
|
])->validate();
|
||||||
|
|
||||||
$payment_date = Carbon::createFromFormat('d/m/Y', $request->payment_date);
|
$payment_date = Carbon::createFromFormat('d/m/Y', $request->payment_date);
|
||||||
|
|
||||||
if ($request->has('invoice_id') && $request->invoice_id != null) {
|
if ($request->has('invoice_id') && $request->invoice_id != null) {
|
||||||
@ -90,7 +107,7 @@ class PaymentController extends Controller
|
|||||||
|
|
||||||
$payment = Payment::create([
|
$payment = Payment::create([
|
||||||
'payment_date' => $payment_date,
|
'payment_date' => $payment_date,
|
||||||
'payment_number' => $request->payment_number,
|
'payment_number' => $number_attributes['payment_number'],
|
||||||
'user_id' => $request->user_id,
|
'user_id' => $request->user_id,
|
||||||
'company_id' => $request->header('company'),
|
'company_id' => $request->header('company'),
|
||||||
'invoice_id' => $request->invoice_id,
|
'invoice_id' => $request->invoice_id,
|
||||||
@ -135,7 +152,8 @@ class PaymentController extends Controller
|
|||||||
'customers' => User::where('role', 'customer')
|
'customers' => User::where('role', 'customer')
|
||||||
->whereCompany($request->header('company'))
|
->whereCompany($request->header('company'))
|
||||||
->get(),
|
->get(),
|
||||||
'nextPaymentNumber' => $payment->payment_number,
|
'nextPaymentNumber' => $payment->getPaymentNumAttribute(),
|
||||||
|
'payment_prefix' => $payment->getPaymentPrefixAttribute(),
|
||||||
'payment' => $payment,
|
'payment' => $payment,
|
||||||
'invoices' => $invoices
|
'invoices' => $invoices
|
||||||
]);
|
]);
|
||||||
@ -150,6 +168,13 @@ class PaymentController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function update(PaymentRequest $request, $id)
|
public function update(PaymentRequest $request, $id)
|
||||||
{
|
{
|
||||||
|
$payment_number = explode("-",$request->payment_number);
|
||||||
|
$number_attributes['payment_number'] = $payment_number[0].'-'.sprintf('%06d', intval($payment_number[1]));
|
||||||
|
|
||||||
|
Validator::make($number_attributes, [
|
||||||
|
'payment_number' => 'required|unique:payments,payment_number'.','.$id
|
||||||
|
])->validate();
|
||||||
|
|
||||||
$payment_date = Carbon::createFromFormat('d/m/Y', $request->payment_date);
|
$payment_date = Carbon::createFromFormat('d/m/Y', $request->payment_date);
|
||||||
|
|
||||||
$payment = Payment::find($id);
|
$payment = Payment::find($id);
|
||||||
@ -178,7 +203,7 @@ class PaymentController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
$payment->payment_date = $payment_date;
|
$payment->payment_date = $payment_date;
|
||||||
$payment->payment_number = $request->payment_number;
|
$payment->payment_number = $number_attributes['payment_number'];
|
||||||
$payment->user_id = $request->user_id;
|
$payment->user_id = $request->user_id;
|
||||||
$payment->invoice_id = $request->invoice_id;
|
$payment->invoice_id = $request->invoice_id;
|
||||||
$payment->payment_mode = $request->payment_mode;
|
$payment->payment_mode = $request->payment_mode;
|
||||||
|
|||||||
@ -66,10 +66,14 @@ class Invoice extends Model
|
|||||||
'formattedDueDate'
|
'formattedDueDate'
|
||||||
];
|
];
|
||||||
|
|
||||||
public static function getNextInvoiceNumber()
|
public static function getNextInvoiceNumber($value)
|
||||||
{
|
{
|
||||||
// Get the last created order
|
// Get the last created order
|
||||||
$lastOrder = Invoice::orderBy('created_at', 'desc')->first();
|
$lastOrder = Invoice::where('invoice_number', 'LIKE', $value . '-%')
|
||||||
|
->orderBy('created_at', 'desc')
|
||||||
|
->first();
|
||||||
|
|
||||||
|
|
||||||
if (!$lastOrder) {
|
if (!$lastOrder) {
|
||||||
// We get here if there is no order at all
|
// We get here if there is no order at all
|
||||||
// If there is no number set it to 0, which will be 1 at the end.
|
// If there is no number set it to 0, which will be 1 at the end.
|
||||||
@ -143,10 +147,15 @@ class Invoice extends Model
|
|||||||
|
|
||||||
public function getInvoiceNumAttribute()
|
public function getInvoiceNumAttribute()
|
||||||
{
|
{
|
||||||
$position = $this->strposX($this->invoice_number, "-", 2) + 1;
|
$position = $this->strposX($this->invoice_number, "-", 1) + 1;
|
||||||
return substr($this->invoice_number, $position);
|
return substr($this->invoice_number, $position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getInvoicePrefixAttribute () {
|
||||||
|
$prefix = explode("-", $this->invoice_number)[0];
|
||||||
|
return $prefix;
|
||||||
|
}
|
||||||
|
|
||||||
public function getFormattedCreatedAtAttribute($value)
|
public function getFormattedCreatedAtAttribute($value)
|
||||||
{
|
{
|
||||||
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
||||||
|
|||||||
@ -32,10 +32,34 @@ class Payment extends Model
|
|||||||
'formattedPaymentDate'
|
'formattedPaymentDate'
|
||||||
];
|
];
|
||||||
|
|
||||||
public static function getNextPaymentNumber()
|
|
||||||
|
private function strposX($haystack, $needle, $number)
|
||||||
|
{
|
||||||
|
if ($number == '1') {
|
||||||
|
return strpos($haystack, $needle);
|
||||||
|
} elseif ($number > '1') {
|
||||||
|
return strpos(
|
||||||
|
$haystack,
|
||||||
|
$needle,
|
||||||
|
$this->strposX($haystack, $needle, $number - 1) + strlen($needle)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return error_log('Error: Value for parameter $number is out of range');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPaymentNumAttribute()
|
||||||
|
{
|
||||||
|
$position = $this->strposX($this->payment_number, "-", 1) + 1;
|
||||||
|
return substr($this->payment_number, $position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getNextPaymentNumber($value)
|
||||||
{
|
{
|
||||||
// Get the last created order
|
// Get the last created order
|
||||||
$payment = Payment::orderBy('created_at', 'desc')->first();
|
$payment = Payment::where('payment_number', 'LIKE', $value . '-%')
|
||||||
|
->orderBy('created_at', 'desc')
|
||||||
|
->first();
|
||||||
if (!$payment) {
|
if (!$payment) {
|
||||||
// We get here if there is no order at all
|
// We get here if there is no order at all
|
||||||
// If there is no number set it to 0, which will be 1 at the end.
|
// If there is no number set it to 0, which will be 1 at the end.
|
||||||
@ -54,6 +78,13 @@ class Payment extends Model
|
|||||||
return sprintf('%06d', intval($number) + 1);
|
return sprintf('%06d', intval($number) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getPaymentPrefixAttribute ()
|
||||||
|
{
|
||||||
|
$prefix= explode("-",$this->payment_number)[0];
|
||||||
|
return $prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public function invoice()
|
public function invoice()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Invoice::class);
|
return $this->belongsTo(Invoice::class);
|
||||||
|
|||||||
71
resources/assets/js/components/base/BasePrefixInput.vue
Normal file
71
resources/assets/js/components/base/BasePrefixInput.vue
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<template>
|
||||||
|
<div class="base-prefix-input" @click="focusInput">
|
||||||
|
<font-awesome-icon v-if="icon" :icon="icon" class="icon" />
|
||||||
|
<p class="prefix-label"><span class="mr-1">{{ prefix }}</span>-</p>
|
||||||
|
<input
|
||||||
|
ref="basePrefixInput"
|
||||||
|
v-model="inputValue"
|
||||||
|
:type="type"
|
||||||
|
class="prefix-input-field"
|
||||||
|
@input="handleInput"
|
||||||
|
@change="handleChange"
|
||||||
|
@keyup="handleKeyupEnter"
|
||||||
|
@keydown="handleKeyDownEnter"
|
||||||
|
@blur="handleFocusOut"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
prefix: {
|
||||||
|
type: String,
|
||||||
|
default: null,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
type: String,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: [String, Number, File],
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: 'text'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
inputValue: this.value
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
'value' () {
|
||||||
|
this.inputValue = this.value
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
focusInput () {
|
||||||
|
this.$refs.basePrefixInput.focus()
|
||||||
|
},
|
||||||
|
handleInput (e) {
|
||||||
|
this.$emit('input', this.inputValue)
|
||||||
|
},
|
||||||
|
handleChange (e) {
|
||||||
|
this.$emit('change', this.inputValue)
|
||||||
|
},
|
||||||
|
handleKeyupEnter (e) {
|
||||||
|
this.$emit('keyup', this.inputValue)
|
||||||
|
},
|
||||||
|
handleKeyDownEnter (e) {
|
||||||
|
this.$emit('keydown', e, this.inputValue)
|
||||||
|
},
|
||||||
|
handleFocusOut (e) {
|
||||||
|
this.$emit('blur', this.inputValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@ -8,6 +8,7 @@ import BaseTextArea from './BaseTextArea.vue'
|
|||||||
import BaseSelect from './base-select/BaseSelect.vue'
|
import BaseSelect from './base-select/BaseSelect.vue'
|
||||||
import BaseLoader from './BaseLoader.vue'
|
import BaseLoader from './BaseLoader.vue'
|
||||||
import BaseCustomerSelect from './BaseCustomerSelect.vue'
|
import BaseCustomerSelect from './BaseCustomerSelect.vue'
|
||||||
|
import BasePrefixInput from './BasePrefixInput.vue'
|
||||||
|
|
||||||
import BasePopup from './popup/BasePopup.vue'
|
import BasePopup from './popup/BasePopup.vue'
|
||||||
import CustomerSelectPopup from './popup/CustomerSelectPopup.vue'
|
import CustomerSelectPopup from './popup/CustomerSelectPopup.vue'
|
||||||
@ -23,6 +24,7 @@ Vue.component('base-input', BaseInput)
|
|||||||
Vue.component('base-switch', BaseSwitch)
|
Vue.component('base-switch', BaseSwitch)
|
||||||
Vue.component('base-text-area', BaseTextArea)
|
Vue.component('base-text-area', BaseTextArea)
|
||||||
Vue.component('base-loader', BaseLoader)
|
Vue.component('base-loader', BaseLoader)
|
||||||
|
Vue.component('base-prefix-input', BasePrefixInput)
|
||||||
|
|
||||||
Vue.component('table-component', TableComponent)
|
Vue.component('table-component', TableComponent)
|
||||||
Vue.component('table-column', TableColumn)
|
Vue.component('table-column', TableColumn)
|
||||||
|
|||||||
@ -124,7 +124,7 @@ export default {
|
|||||||
},
|
},
|
||||||
percent: {
|
percent: {
|
||||||
required,
|
required,
|
||||||
between: between(0.10, 100)
|
between: between(-1, 100)
|
||||||
},
|
},
|
||||||
description: {
|
description: {
|
||||||
maxLength: maxLength(255)
|
maxLength: maxLength(255)
|
||||||
|
|||||||
@ -127,14 +127,15 @@
|
|||||||
<div class="row mt-4">
|
<div class="row mt-4">
|
||||||
<div class="col collapse-input">
|
<div class="col collapse-input">
|
||||||
<label>{{ $t('estimates.estimate_number') }}<span class="text-danger"> * </span></label>
|
<label>{{ $t('estimates.estimate_number') }}<span class="text-danger"> * </span></label>
|
||||||
<base-input
|
<base-prefix-input
|
||||||
:invalid="$v.newEstimate.estimate_number.$error"
|
v-model="estimateNumAttribute"
|
||||||
:read-only="true"
|
:invalid="$v.estimateNumAttribute.$error"
|
||||||
v-model="newEstimate.estimate_number"
|
:prefix="estimatePrefix"
|
||||||
icon="hashtag"
|
icon="hashtag"
|
||||||
@input="$v.newEstimate.estimate_number.$touch()"
|
@input="$v.estimateNumAttribute.$touch()"
|
||||||
/>
|
/>
|
||||||
<span v-show="$v.newEstimate.estimate_number.$error && !$v.newEstimate.estimate_number.required" class="text-danger mt-1"> {{ $tc('estimates.errors.required') }} </span>
|
<span v-show="$v.estimateNumAttribute.$error && !$v.estimateNumAttribute.required" class="text-danger mt-1"> {{ $tc('estimates.errors.required') }} </span>
|
||||||
|
<span v-show="!$v.estimateNumAttribute.numeric" class="text-danger mt-1"> {{ $tc('validation.numbers_only') }} </span>
|
||||||
</div>
|
</div>
|
||||||
<div class="col collapse-input">
|
<div class="col collapse-input">
|
||||||
<label>{{ $t('estimates.ref_number') }}</label>
|
<label>{{ $t('estimates.ref_number') }}</label>
|
||||||
@ -320,7 +321,7 @@ import { validationMixin } from 'vuelidate'
|
|||||||
import Guid from 'guid'
|
import Guid from 'guid'
|
||||||
import TaxStub from '../../stub/tax'
|
import TaxStub from '../../stub/tax'
|
||||||
import Tax from './EstimateTax'
|
import Tax from './EstimateTax'
|
||||||
const { required, between, maxLength } = require('vuelidate/lib/validators')
|
const { required, between, maxLength, numeric } = require('vuelidate/lib/validators')
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@ -361,7 +362,9 @@ export default {
|
|||||||
discountPerItem: null,
|
discountPerItem: null,
|
||||||
initLoading: false,
|
initLoading: false,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
maxDiscount: 0
|
maxDiscount: 0,
|
||||||
|
estimatePrefix: null,
|
||||||
|
estimateNumAttribute: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
validations () {
|
validations () {
|
||||||
@ -373,9 +376,6 @@ export default {
|
|||||||
expiry_date: {
|
expiry_date: {
|
||||||
required
|
required
|
||||||
},
|
},
|
||||||
estimate_number: {
|
|
||||||
required
|
|
||||||
},
|
|
||||||
discount_val: {
|
discount_val: {
|
||||||
between: between(0, this.subtotal)
|
between: between(0, this.subtotal)
|
||||||
},
|
},
|
||||||
@ -388,6 +388,10 @@ export default {
|
|||||||
},
|
},
|
||||||
selectedCustomer: {
|
selectedCustomer: {
|
||||||
required
|
required
|
||||||
|
},
|
||||||
|
estimateNumAttribute: {
|
||||||
|
required,
|
||||||
|
numeric
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -559,6 +563,8 @@ export default {
|
|||||||
this.taxPerItem = response.data.tax_per_item
|
this.taxPerItem = response.data.tax_per_item
|
||||||
this.selectedCurrency = this.defaultCurrency
|
this.selectedCurrency = this.defaultCurrency
|
||||||
this.estimateTemplates = response.data.estimateTemplates
|
this.estimateTemplates = response.data.estimateTemplates
|
||||||
|
this.estimatePrefix = response.data.estimate_prefix
|
||||||
|
this.estimateNumAttribute = response.data.nextEstimateNumber
|
||||||
}
|
}
|
||||||
this.initLoading = false
|
this.initLoading = false
|
||||||
return
|
return
|
||||||
@ -574,8 +580,9 @@ export default {
|
|||||||
let today = new Date()
|
let today = new Date()
|
||||||
this.newEstimate.estimate_date = moment(today).toString()
|
this.newEstimate.estimate_date = moment(today).toString()
|
||||||
this.newEstimate.expiry_date = moment(today).add(7, 'days').toString()
|
this.newEstimate.expiry_date = moment(today).add(7, 'days').toString()
|
||||||
this.newEstimate.estimate_number = response.data.nextEstimateNumber
|
|
||||||
this.itemList = response.data.items
|
this.itemList = response.data.items
|
||||||
|
this.estimatePrefix = response.data.estimate_prefix
|
||||||
|
this.estimateNumAttribute = response.data.nextEstimateNumber
|
||||||
}
|
}
|
||||||
this.initLoading = false
|
this.initLoading = false
|
||||||
},
|
},
|
||||||
@ -604,6 +611,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.isLoading = true
|
this.isLoading = true
|
||||||
|
this.newEstimate.estimate_number = this.estimatePrefix + '-' + this.estimateNumAttribute
|
||||||
|
|
||||||
let data = {
|
let data = {
|
||||||
...this.newEstimate,
|
...this.newEstimate,
|
||||||
@ -637,7 +645,11 @@ export default {
|
|||||||
this.isLoading = false
|
this.isLoading = false
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
this.isLoading = false
|
this.isLoading = false
|
||||||
console.log(err)
|
if (err.response.data.errors.estimate_number) {
|
||||||
|
window.toastr['error'](err.response.data.errors.estimate_number)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
window.toastr['error'](err.response.data.message)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
submitUpdate (data) {
|
submitUpdate (data) {
|
||||||
@ -650,7 +662,11 @@ export default {
|
|||||||
this.isLoading = false
|
this.isLoading = false
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
this.isLoading = false
|
this.isLoading = false
|
||||||
console.log(err)
|
if (err.response.data.errors.estimate_number) {
|
||||||
|
window.toastr['error'](err.response.data.errors.estimate_number)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
window.toastr['error'](err.response.data.message)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
checkItemsData (index, isValid) {
|
checkItemsData (index, isValid) {
|
||||||
|
|||||||
@ -127,14 +127,15 @@
|
|||||||
<div class="row mt-4">
|
<div class="row mt-4">
|
||||||
<div class="col collapse-input">
|
<div class="col collapse-input">
|
||||||
<label>{{ $t('invoices.invoice_number') }}<span class="text-danger"> * </span></label>
|
<label>{{ $t('invoices.invoice_number') }}<span class="text-danger"> * </span></label>
|
||||||
<base-input
|
<base-prefix-input
|
||||||
:invalid="$v.newInvoice.invoice_number.$error"
|
v-model="invoiceNumAttribute"
|
||||||
:read-only="true"
|
:invalid="$v.invoiceNumAttribute.$error"
|
||||||
v-model="newInvoice.invoice_number"
|
:prefix="invoicePrefix"
|
||||||
icon="hashtag"
|
icon="hashtag"
|
||||||
@input="$v.newInvoice.invoice_number.$touch()"
|
@input="$v.invoiceNumAttribute.$touch()"
|
||||||
/>
|
/>
|
||||||
<span v-show="$v.newInvoice.invoice_number.$error && !$v.newInvoice.invoice_number.required" class="text-danger mt-1"> {{ $tc('validation.required') }} </span>
|
<span v-show="$v.invoiceNumAttribute.$error && !$v.invoiceNumAttribute.required" class="text-danger mt-1"> {{ $tc('validation.required') }} </span>
|
||||||
|
<span v-show="!$v.invoiceNumAttribute.numeric" class="text-danger mt-1"> {{ $tc('validation.numbers_only') }} </span>
|
||||||
</div>
|
</div>
|
||||||
<div class="col collapse-input">
|
<div class="col collapse-input">
|
||||||
<label>{{ $t('invoices.ref_number') }}</label>
|
<label>{{ $t('invoices.ref_number') }}</label>
|
||||||
@ -320,7 +321,7 @@ import { validationMixin } from 'vuelidate'
|
|||||||
import Guid from 'guid'
|
import Guid from 'guid'
|
||||||
import TaxStub from '../../stub/tax'
|
import TaxStub from '../../stub/tax'
|
||||||
import Tax from './InvoiceTax'
|
import Tax from './InvoiceTax'
|
||||||
const { required, between, maxLength } = require('vuelidate/lib/validators')
|
const { required, between, maxLength, numeric } = require('vuelidate/lib/validators')
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@ -361,7 +362,9 @@ export default {
|
|||||||
discountPerItem: null,
|
discountPerItem: null,
|
||||||
initLoading: false,
|
initLoading: false,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
maxDiscount: 0
|
maxDiscount: 0,
|
||||||
|
invoicePrefix: null,
|
||||||
|
invoiceNumAttribute: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
validations () {
|
validations () {
|
||||||
@ -373,9 +376,6 @@ export default {
|
|||||||
due_date: {
|
due_date: {
|
||||||
required
|
required
|
||||||
},
|
},
|
||||||
invoice_number: {
|
|
||||||
required
|
|
||||||
},
|
|
||||||
discount_val: {
|
discount_val: {
|
||||||
between: between(0, this.subtotal)
|
between: between(0, this.subtotal)
|
||||||
},
|
},
|
||||||
@ -388,6 +388,10 @@ export default {
|
|||||||
},
|
},
|
||||||
selectedCustomer: {
|
selectedCustomer: {
|
||||||
required
|
required
|
||||||
|
},
|
||||||
|
invoiceNumAttribute: {
|
||||||
|
required,
|
||||||
|
numeric
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -559,6 +563,8 @@ export default {
|
|||||||
this.taxPerItem = response.data.tax_per_item
|
this.taxPerItem = response.data.tax_per_item
|
||||||
this.selectedCurrency = this.defaultCurrency
|
this.selectedCurrency = this.defaultCurrency
|
||||||
this.invoiceTemplates = response.data.invoiceTemplates
|
this.invoiceTemplates = response.data.invoiceTemplates
|
||||||
|
this.invoicePrefix = response.data.invoice_prefix
|
||||||
|
this.invoiceNumAttribute = response.data.nextInvoiceNumber
|
||||||
}
|
}
|
||||||
this.initLoading = false
|
this.initLoading = false
|
||||||
return
|
return
|
||||||
@ -574,8 +580,9 @@ export default {
|
|||||||
let today = new Date()
|
let today = new Date()
|
||||||
this.newInvoice.invoice_date = moment(today).toString()
|
this.newInvoice.invoice_date = moment(today).toString()
|
||||||
this.newInvoice.due_date = moment(today).add(7, 'days').toString()
|
this.newInvoice.due_date = moment(today).add(7, 'days').toString()
|
||||||
this.newInvoice.invoice_number = response.data.nextInvoiceNumber
|
|
||||||
this.itemList = response.data.items
|
this.itemList = response.data.items
|
||||||
|
this.invoicePrefix = response.data.invoice_prefix
|
||||||
|
this.invoiceNumAttribute = response.data.nextInvoiceNumber
|
||||||
}
|
}
|
||||||
this.initLoading = false
|
this.initLoading = false
|
||||||
},
|
},
|
||||||
@ -604,6 +611,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.isLoading = true
|
this.isLoading = true
|
||||||
|
this.newInvoice.invoice_number = this.invoicePrefix + '-' + this.invoiceNumAttribute
|
||||||
|
|
||||||
let data = {
|
let data = {
|
||||||
...this.newInvoice,
|
...this.newInvoice,
|
||||||
@ -637,6 +645,10 @@ export default {
|
|||||||
this.isLoading = false
|
this.isLoading = false
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
this.isLoading = false
|
this.isLoading = false
|
||||||
|
if (err.response.data.errors.invoice_number) {
|
||||||
|
window.toastr['error'](err.response.data.errors.invoice_number)
|
||||||
|
return true
|
||||||
|
}
|
||||||
console.log(err)
|
console.log(err)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@ -653,6 +665,10 @@ export default {
|
|||||||
}
|
}
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
this.isLoading = false
|
this.isLoading = false
|
||||||
|
if (err.response.data.errors.invoice_number) {
|
||||||
|
window.toastr['error'](err.response.data.errors.invoice_number)
|
||||||
|
return true
|
||||||
|
}
|
||||||
console.log(err)
|
console.log(err)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
@ -40,16 +40,15 @@
|
|||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label">{{ $t('payments.payment_number') }}</label><span class="text-danger"> *</span>
|
<label class="form-label">{{ $t('payments.payment_number') }}</label><span class="text-danger"> *</span>
|
||||||
<base-input
|
<base-prefix-input
|
||||||
:invalid="$v.formData.payment_number.$error"
|
:invalid="$v.paymentNumAttribute.$error"
|
||||||
v-model.trim="formData.payment_number"
|
v-model.trim="paymentNumAttribute"
|
||||||
read-only
|
:prefix="paymentPrefix"
|
||||||
type="text"
|
@input="$v.paymentNumAttribute.$touch()"
|
||||||
name="email"
|
|
||||||
@input="$v.formData.payment_number.$touch()"
|
|
||||||
/>
|
/>
|
||||||
<div v-if="$v.formData.payment_number.$error">
|
<div v-if="$v.paymentNumAttribute.$error">
|
||||||
<span v-if="!$v.formData.payment_number.required" class="text-danger">{{ $tc('validation.required') }}</span>
|
<span v-if="!$v.paymentNumAttribute.required" class="text-danger">{{ $tc('validation.required') }}</span>
|
||||||
|
<span v-if="!$v.paymentNumAttribute.numeric" class="text-danger">{{ $tc('validation.numbers_only') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -155,7 +154,7 @@ import { mapActions, mapGetters } from 'vuex'
|
|||||||
import MultiSelect from 'vue-multiselect'
|
import MultiSelect from 'vue-multiselect'
|
||||||
import { validationMixin } from 'vuelidate'
|
import { validationMixin } from 'vuelidate'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
const { required, between, maxLength } = require('vuelidate/lib/validators')
|
const { required, between, maxLength, numeric } = require('vuelidate/lib/validators')
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { MultiSelect },
|
components: { MultiSelect },
|
||||||
@ -184,7 +183,9 @@ export default {
|
|||||||
invoiceList: [],
|
invoiceList: [],
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
maxPayableAmount: Number.MAX_SAFE_INTEGER,
|
maxPayableAmount: Number.MAX_SAFE_INTEGER,
|
||||||
isSettingInitialData: true
|
isSettingInitialData: true,
|
||||||
|
paymentNumAttribute: null,
|
||||||
|
paymentPrefix: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
validations () {
|
validations () {
|
||||||
@ -193,9 +194,6 @@ export default {
|
|||||||
required
|
required
|
||||||
},
|
},
|
||||||
formData: {
|
formData: {
|
||||||
payment_number: {
|
|
||||||
required
|
|
||||||
},
|
|
||||||
payment_date: {
|
payment_date: {
|
||||||
required
|
required
|
||||||
},
|
},
|
||||||
@ -206,6 +204,10 @@ export default {
|
|||||||
notes: {
|
notes: {
|
||||||
maxLength: maxLength(255)
|
maxLength: maxLength(255)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
paymentNumAttribute: {
|
||||||
|
required,
|
||||||
|
numeric
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -297,6 +299,8 @@ export default {
|
|||||||
this.customer = response.data.payment.user
|
this.customer = response.data.payment.user
|
||||||
this.formData.payment_date = moment(response.data.payment.payment_date, 'YYYY-MM-DD').toString()
|
this.formData.payment_date = moment(response.data.payment.payment_date, 'YYYY-MM-DD').toString()
|
||||||
this.formData.amount = parseFloat(response.data.payment.amount)
|
this.formData.amount = parseFloat(response.data.payment.amount)
|
||||||
|
this.paymentPrefix = response.data.payment_prefix
|
||||||
|
this.paymentNumAttribute = response.data.nextPaymentNumber
|
||||||
if (response.data.payment.invoice !== null) {
|
if (response.data.payment.invoice !== null) {
|
||||||
this.maxPayableAmount = parseInt(response.data.payment.amount) + parseInt(response.data.payment.invoice.due_amount)
|
this.maxPayableAmount = parseInt(response.data.payment.amount) + parseInt(response.data.payment.invoice.due_amount)
|
||||||
this.invoice = response.data.payment.invoice
|
this.invoice = response.data.payment.invoice
|
||||||
@ -305,7 +309,8 @@ export default {
|
|||||||
} else {
|
} else {
|
||||||
let response = await this.fetchCreatePayment()
|
let response = await this.fetchCreatePayment()
|
||||||
this.customerList = response.data.customers
|
this.customerList = response.data.customers
|
||||||
this.formData.payment_number = response.data.nextPaymentNumber
|
this.paymentNumAttribute = response.data.nextPaymentNumber
|
||||||
|
this.paymentPrefix = response.data.payment_prefix
|
||||||
this.formData.payment_date = moment(new Date()).toString()
|
this.formData.payment_date = moment(new Date()).toString()
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -332,6 +337,9 @@ export default {
|
|||||||
if (this.$v.$invalid) {
|
if (this.$v.$invalid) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.formData.payment_number = this.paymentPrefix + '-' + this.paymentNumAttribute
|
||||||
|
|
||||||
if (this.isEdit) {
|
if (this.isEdit) {
|
||||||
let data = {
|
let data = {
|
||||||
editData: {
|
editData: {
|
||||||
@ -340,35 +348,53 @@ export default {
|
|||||||
},
|
},
|
||||||
id: this.$route.params.id
|
id: this.$route.params.id
|
||||||
}
|
}
|
||||||
let response = await this.updatePayment(data)
|
try {
|
||||||
if (response.data.success) {
|
let response = await this.updatePayment(data)
|
||||||
window.toastr['success'](this.$t('payments.updated_message'))
|
if (response.data.success) {
|
||||||
this.$router.push('/admin/payments')
|
window.toastr['success'](this.$t('payments.updated_message'))
|
||||||
return true
|
this.$router.push('/admin/payments')
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (response.data.error === 'invalid_amount') {
|
||||||
|
window.toastr['error'](this.$t('invalid_amount_message'))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
window.toastr['error'](response.data.error)
|
||||||
|
} catch (err) {
|
||||||
|
this.isLoading = false
|
||||||
|
if (err.response.data.errors.payment_number) {
|
||||||
|
window.toastr['error'](err.response.data.errors.payment_number)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
window.toastr['error'](err.response.data.message)
|
||||||
}
|
}
|
||||||
if (response.data.error === 'invalid_amount') {
|
|
||||||
window.toastr['error'](this.$t('invalid_amount_message'))
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
window.toastr['error'](response.data.error)
|
|
||||||
} else {
|
} else {
|
||||||
let data = {
|
let data = {
|
||||||
...this.formData,
|
...this.formData,
|
||||||
payment_date: moment(this.formData.payment_date).format('DD/MM/YYYY')
|
payment_date: moment(this.formData.payment_date).format('DD/MM/YYYY')
|
||||||
}
|
}
|
||||||
this.isLoading = true
|
this.isLoading = true
|
||||||
let response = await this.addPayment(data)
|
try {
|
||||||
if (response.data.success) {
|
let response = await this.addPayment(data)
|
||||||
window.toastr['success'](this.$t('payments.created_message'))
|
if (response.data.success) {
|
||||||
this.$router.push('/admin/payments')
|
window.toastr['success'](this.$t('payments.created_message'))
|
||||||
this.isLoading = true
|
this.$router.push('/admin/payments')
|
||||||
return true
|
this.isLoading = true
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (response.data.error === 'invalid_amount') {
|
||||||
|
window.toastr['error'](this.$t('invalid_amount_message'))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
window.toastr['error'](response.data.error)
|
||||||
|
} catch (err) {
|
||||||
|
this.isLoading = false
|
||||||
|
if (err.response.data.errors.payment_number) {
|
||||||
|
window.toastr['error'](err.response.data.errors.payment_number)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
window.toastr['error'](err.response.data.message)
|
||||||
}
|
}
|
||||||
if (response.data.error === 'invalid_amount') {
|
|
||||||
window.toastr['error'](this.$t('invalid_amount_message'))
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
window.toastr['error'](response.data.error)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<!-- Invoices Tab -->
|
<!-- Invoices Tab -->
|
||||||
<transition name="fade">
|
<transition name="fade-customize">
|
||||||
<div v-if="activeTab === 'INVOICES'" class="invoice-tab">
|
<div v-if="activeTab === 'INVOICES'" class="invoice-tab">
|
||||||
<form action="" class="form-section" @submit.prevent="updateInvoiceSetting">
|
<form action="" class="form-section" @submit.prevent="updateInvoiceSetting">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@ -69,7 +69,7 @@
|
|||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
<!-- Estimates Tab -->
|
<!-- Estimates Tab -->
|
||||||
<transition name="fade">
|
<transition name="fade-customize">
|
||||||
<div v-if="activeTab === 'ESTIMATES'" class="estimate-tab">
|
<div v-if="activeTab === 'ESTIMATES'" class="estimate-tab">
|
||||||
<form action="" class="form-section" @submit.prevent="updateEstimateSetting">
|
<form action="" class="form-section" @submit.prevent="updateEstimateSetting">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@ -124,7 +124,7 @@
|
|||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
<!-- Payments Tab -->
|
<!-- Payments Tab -->
|
||||||
<transition name="fade">
|
<transition name="fade-customize">
|
||||||
<div v-if="activeTab === 'PAYMENTS'" class="payment-tab">
|
<div v-if="activeTab === 'PAYMENTS'" class="payment-tab">
|
||||||
<form action="" class="form-section" @submit.prevent="updatePaymentSetting">
|
<form action="" class="form-section" @submit.prevent="updatePaymentSetting">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@ -208,6 +208,9 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
activeTab () {
|
||||||
|
this.loadData()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
validations: {
|
validations: {
|
||||||
invoices: {
|
invoices: {
|
||||||
@ -373,3 +376,16 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
<style>
|
||||||
|
.fade-customize-enter-active {
|
||||||
|
transition: opacity 0.9s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-customize-leave-active {
|
||||||
|
transition: opacity 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-customize-enter, .fade-customize-leave-to /* .fade-leave-active below version 2.1.8 */ {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
54
resources/assets/sass/components/base/base-prefix-input.scss
vendored
Normal file
54
resources/assets/sass/components/base/base-prefix-input.scss
vendored
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
.base-prefix-input {
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 40px;
|
||||||
|
padding: 2px 2px;
|
||||||
|
flex-direction: row;
|
||||||
|
background: #FFFFFF;
|
||||||
|
border: 1px solid $ls-color-gray--light;
|
||||||
|
border-radius: 5px;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
width: 13px;
|
||||||
|
height: 18px;
|
||||||
|
color: $ls-color-gray;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 900;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 16px;
|
||||||
|
margin-top: 17px;
|
||||||
|
margin-left: 20px;
|
||||||
|
z-index: 1;
|
||||||
|
transform: translate(-50%,-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
padding: 0 0 0 0;
|
||||||
|
margin: 0 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prefix-label {
|
||||||
|
display: flex;
|
||||||
|
height: 18px;
|
||||||
|
color: #55547A;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 16px;
|
||||||
|
padding: 9px 2px 9px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prefix-input-field {
|
||||||
|
width: 100%;
|
||||||
|
padding: 8px 13px;
|
||||||
|
padding-left: 1px;
|
||||||
|
text-align: left;
|
||||||
|
background: #FFFFFF;
|
||||||
|
border: none;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 21px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
1
resources/assets/sass/crater.scss
vendored
1
resources/assets/sass/crater.scss
vendored
@ -48,6 +48,7 @@
|
|||||||
@import 'components/base/base-text-area';
|
@import 'components/base/base-text-area';
|
||||||
@import "components/base/base-switch";
|
@import "components/base/base-switch";
|
||||||
@import 'components/base/base-loader/index';
|
@import 'components/base/base-loader/index';
|
||||||
|
@import 'components/base/base-prefix-input';
|
||||||
|
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
|
|||||||
Reference in New Issue
Block a user