mirror of
				https://github.com/crater-invoice/crater.git
				synced 2025-10-31 05:31:10 -04:00 
			
		
		
		
	Merge branch 'master' of https://gitlab.com/mohit.panjvani/crater-web into fix-view-status
This commit is contained in:
		
							
								
								
									
										31
									
								
								app/Events/UpdateFinished.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								app/Events/UpdateFinished.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Laraspace\Events; | ||||
|  | ||||
| use Illuminate\Broadcasting\Channel; | ||||
| use Illuminate\Broadcasting\InteractsWithSockets; | ||||
| use Illuminate\Broadcasting\PresenceChannel; | ||||
| use Illuminate\Broadcasting\PrivateChannel; | ||||
| use Illuminate\Contracts\Broadcasting\ShouldBroadcast; | ||||
| use Illuminate\Foundation\Events\Dispatchable; | ||||
| use Illuminate\Queue\SerializesModels; | ||||
|  | ||||
| class UpdateFinished | ||||
| { | ||||
|     use Dispatchable; | ||||
|  | ||||
|     public $new; | ||||
|  | ||||
|     public $old; | ||||
|  | ||||
|     /** | ||||
|      * Create a new event instance. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function __construct($old, $new) | ||||
|     { | ||||
|         $this->old   = $old; | ||||
|         $this->new   = $new; | ||||
|     } | ||||
| } | ||||
| @ -54,7 +54,7 @@ class AccessTokensController extends Controller | ||||
| 	{ | ||||
| 		$request->validate([ | ||||
| 			'username' => 'required|email', | ||||
| 			'password' => 'required|string', | ||||
| 			'password' => 'required|string|min:8', | ||||
| 		]); | ||||
|  | ||||
| 		if ($this->hasTooManyLoginAttempts($request)) { | ||||
|  | ||||
| @ -37,6 +37,7 @@ class EnvironmentController extends Controller | ||||
|  | ||||
|         if(array_key_exists("success", $results)) { | ||||
|             Artisan::call('config:clear'); | ||||
|             Artisan::call('key:generate --force'); | ||||
|             Artisan::call('migrate --seed'); | ||||
|             Artisan::call('migrate', ['--path' => 'vendor/laravel/passport/database/migrations']); | ||||
|  | ||||
|  | ||||
| @ -260,6 +260,7 @@ class InvoicesController extends Controller | ||||
|                 'error' => 'invalid_due_amount' | ||||
|             ]); | ||||
|         } elseif ($invoice->due_amount != 0 && $invoice->paid_status == Invoice::STATUS_PAID) { | ||||
|             $invoice->status = $invoice->getPreviousStatus(); | ||||
|             $invoice->paid_status = Invoice::STATUS_PARTIALLY_PAID; | ||||
|         } | ||||
|  | ||||
|  | ||||
| @ -170,6 +170,7 @@ class PaymentController extends Controller | ||||
|                 $invoice->status = Invoice::STATUS_COMPLETED; | ||||
|                 $invoice->paid_status = Invoice::STATUS_PAID; | ||||
|             } else { | ||||
|                 $invoice->status = $invoice->getPreviousStatus(); | ||||
|                 $invoice->paid_status = Invoice::STATUS_PARTIALLY_PAID; | ||||
|             } | ||||
|  | ||||
| @ -211,16 +212,7 @@ class PaymentController extends Controller | ||||
|                 $invoice->paid_status = Invoice::STATUS_PARTIALLY_PAID; | ||||
|             } | ||||
|  | ||||
|             if ($invoice->due_date < Carbon::now()) { | ||||
|                 $invoice->status = Invoice::STATUS_OVERDUE; | ||||
|             } elseif ($invoice->viewed) { | ||||
|                 $invoice->status = Invoice::STATUS_VIEWED; | ||||
|             } elseif ($invoice->sent) { | ||||
|                 $invoice->status = Invoice::STATUS_SENT; | ||||
|             } else { | ||||
|                 $invoice->status = Invoice::STATUS_DRAFT; | ||||
|             } | ||||
|  | ||||
|             $invoice->status = $invoice->getPreviousStatus(); | ||||
|             $invoice->save(); | ||||
|         } | ||||
|  | ||||
| @ -246,16 +238,7 @@ class PaymentController extends Controller | ||||
|                     $invoice->paid_status = Invoice::STATUS_PARTIALLY_PAID; | ||||
|                 } | ||||
|  | ||||
|                 if ($invoice->due_date < Carbon::now()) { | ||||
|                     $invoice->status = Invoice::STATUS_OVERDUE; | ||||
|                 } elseif ($invoice->sent) { | ||||
|                     $invoice->status = Invoice::STATUS_SENT; | ||||
|                 } elseif ($invoice->viewed) { | ||||
|                     $invoice->status = Invoice::STATUS_VIEWED; | ||||
|                 } else { | ||||
|                     $invoice->status = Invoice::STATUS_DRAFT; | ||||
|                 } | ||||
|  | ||||
|                 $invoice->status = $invoice->getPreviousStatus(); | ||||
|                 $invoice->save(); | ||||
|             } | ||||
|  | ||||
|  | ||||
| @ -26,8 +26,7 @@ class ReportController extends Controller | ||||
|                 $query->whereBetween( | ||||
|                     'invoice_date', | ||||
|                     [$start->format('Y-m-d'), $end->format('Y-m-d')] | ||||
|                 ) | ||||
|                 ->where('paid_status', Invoice::STATUS_PAID); | ||||
|                 ); | ||||
|             }]) | ||||
|             ->customer() | ||||
|             ->whereCompany($company->id) | ||||
|  | ||||
							
								
								
									
										28
									
								
								app/Http/Controllers/UpdateController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								app/Http/Controllers/UpdateController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Laraspace\Http\Controllers; | ||||
|  | ||||
| use Illuminate\Http\Request; | ||||
| use Laraspace\Space\Updater; | ||||
| use Laraspace\Space\SiteApi; | ||||
|  | ||||
| class UpdateController extends Controller | ||||
| { | ||||
|     public function update(Request $request) | ||||
|     { | ||||
|         set_time_limit(600); // 10 minutes | ||||
|  | ||||
|         $json = Updater::update($request->installed, $request->version); | ||||
|  | ||||
|         return response()->json($json); | ||||
|     } | ||||
|  | ||||
|     public function checkLatestVersion(Request $request) | ||||
|     { | ||||
|         set_time_limit(600); // 10 minutes | ||||
|  | ||||
|         $json = Updater::checkForUpdate(); | ||||
|  | ||||
|         return response()->json($json); | ||||
|     } | ||||
| } | ||||
| @ -26,12 +26,16 @@ class CustomerRequest extends FormRequest | ||||
|             case 'POST': | ||||
|                 return [ | ||||
|                     'name' => 'required', | ||||
|                     'addresses.*.address_street_1' => 'max:255', | ||||
|                     'addresses.*.address_street_2' => 'max:255', | ||||
|                     'email' => 'email|nullable|unique:users,email', | ||||
|                 ]; | ||||
|                 break; | ||||
|             case 'PUT': | ||||
|                 return [ | ||||
|                     'name' => 'required', | ||||
|                     'addresses.*.address_street_1' => 'max:255', | ||||
|                     'addresses.*.address_street_2' => 'max:255', | ||||
|                 ]; | ||||
|                 break; | ||||
|             default: | ||||
|  | ||||
| @ -27,13 +27,22 @@ class EstimatesRequest extends FormRequest | ||||
|             'expiry_date' => 'required', | ||||
|             'estimate_number' => 'required|unique:estimates,estimate_number', | ||||
|             'user_id' => 'required', | ||||
|             'discount' => 'required', | ||||
|             'discount' => 'required|digits_between:1,20', | ||||
|             'discount_val' => 'required|digits_between:1,20', | ||||
|             'sub_total' => 'required|digits_between:1,20', | ||||
|             'total' => 'required|digits_between:1,20', | ||||
|             'tax' => 'required|digits_between:1,20', | ||||
|             'estimate_template_id' => 'required', | ||||
|             'items' => 'required|array', | ||||
|             'items.*.description' => 'max:255', | ||||
|             'items.*' => 'required|max:255', | ||||
|             'items.*.name' => 'required', | ||||
|             'items.*.quantity' => 'required|numeric', | ||||
|             'items.*.price' => 'required|numeric', | ||||
|             'items.*.quantity' => 'required|digits_between:1,20', | ||||
|             'items.*.price' => 'required|digits_between:1,20', | ||||
|             'items.*.discount' => 'digits_between:1,20', | ||||
|             'items.*.discount_val' => 'digits_between:1,20', | ||||
|             'items.*.tax' => 'digits_between:1,20', | ||||
|             'items.*.total' => 'digits_between:1,20', | ||||
|         ]; | ||||
|  | ||||
|         if ($this->getMethod() == 'PUT') { | ||||
|  | ||||
| @ -25,7 +25,7 @@ class ExpenseRequest extends FormRequest | ||||
|         return [ | ||||
|             'expense_date' => 'required', | ||||
|             'expense_category_id' => 'required', | ||||
|             'amount' => 'required' | ||||
|             'amount' => 'required|digits_between:1,20' | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -27,13 +27,22 @@ class InvoicesRequest extends FormRequest | ||||
|             'due_date' => 'required', | ||||
|             'invoice_number' => 'required|unique:invoices,invoice_number', | ||||
|             'user_id' => 'required', | ||||
|             'discount' => 'required', | ||||
|             'discount' => 'required|digits_between:1,20', | ||||
|             'discount_val' => 'required|digits_between:1,20', | ||||
|             'sub_total' => 'required|digits_between:1,20', | ||||
|             'total' => 'required|digits_between:1,20', | ||||
|             'tax' => 'required|digits_between:1,20', | ||||
|             'invoice_template_id' => 'required', | ||||
|             'items' => 'required|array', | ||||
|             'items.*' => 'required|max:255', | ||||
|             'items.*.description' => 'max:255', | ||||
|             'items.*.name' => 'required', | ||||
|             'items.*.quantity' => 'required|numeric', | ||||
|             'items.*.price' => 'required|numeric', | ||||
|             'items.*.quantity' => 'required|digits_between:1,20', | ||||
|             'items.*.price' => 'required|digits_between:1,20', | ||||
|             'items.*.discount' => 'digits_between:1,20', | ||||
|             'items.*.discount_val' => 'digits_between:1,20', | ||||
|             'items.*.tax' => 'digits_between:1,20', | ||||
|             'items.*.total' => 'digits_between:1,20', | ||||
|         ]; | ||||
|  | ||||
|         if ($this->getMethod() == 'PUT') { | ||||
|  | ||||
| @ -24,7 +24,7 @@ class ItemsRequest extends FormRequest | ||||
|     { | ||||
|         return [ | ||||
|             'name' => 'required', | ||||
|             'price' => 'required', | ||||
|             'price' => 'required|digits_between:1,20', | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -26,7 +26,7 @@ class PaymentRequest extends FormRequest | ||||
|             'payment_date' => 'required', | ||||
|             'payment_number' => 'required|unique:payments,payment_number', | ||||
|             'user_id' => 'required', | ||||
|             'amount' => 'required', | ||||
|             'amount' => 'required|digits_between:1,20', | ||||
|         ]; | ||||
|  | ||||
|         if ($this->getMethod() == 'PUT') { | ||||
|  | ||||
| @ -31,6 +31,8 @@ class ProfileRequest extends FormRequest | ||||
|                 return [ | ||||
|                     'name' => 'required', | ||||
|                     'password' => 'required', | ||||
|                     'address_street_1' => 'max:255', | ||||
|                     'address_street_2' => 'max:255', | ||||
|                     'email' => [ | ||||
|                         'required', | ||||
|                         'email', | ||||
| @ -41,6 +43,8 @@ class ProfileRequest extends FormRequest | ||||
|             case 'PUT': | ||||
|                 return [ | ||||
|                     'name' => 'required', | ||||
|                     'address_street_1' => 'max:255', | ||||
|                     'address_street_2' => 'max:255', | ||||
|                     'email' => 'required|email' | ||||
|                 ]; | ||||
|                 break; | ||||
|  | ||||
| @ -113,6 +113,19 @@ class Invoice extends Model | ||||
|         return $this->belongsTo(InvoiceTemplate::class); | ||||
|     } | ||||
|  | ||||
|     public function getPreviousStatus() | ||||
|     { | ||||
|         if ($this->due_date < Carbon::now()) { | ||||
|             return self::STATUS_OVERDUE; | ||||
|         } elseif ($this->viewed) { | ||||
|             return self::STATUS_VIEWED; | ||||
|         } elseif ($this->sent) { | ||||
|             return self::STATUS_SENT; | ||||
|         } else { | ||||
|             return self::STATUS_DRAFT; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private function strposX($haystack, $needle, $number) | ||||
|     { | ||||
|         if ($number == '1') { | ||||
|  | ||||
| @ -60,7 +60,7 @@ class InvoiceItem extends Model | ||||
|             $query->whereBetween( | ||||
|                 'invoice_date', | ||||
|                 [$start->format('Y-m-d'), $end->format('Y-m-d')] | ||||
|             )->where('paid_status', Invoice::STATUS_PAID); | ||||
|             ); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|  | ||||
							
								
								
									
										24
									
								
								app/Listeners/Updates/Listener.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								app/Listeners/Updates/Listener.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Laraspace\Listeners\Updates; | ||||
|  | ||||
| class Listener | ||||
| { | ||||
|     const VERSION = ''; | ||||
|  | ||||
|     /** | ||||
|      * Check if should listen. | ||||
|      * | ||||
|      * @param  $event | ||||
|      * @return boolean | ||||
|      */ | ||||
|     protected function check($event) | ||||
|     { | ||||
|         // Do not apply to the same or newer versions | ||||
|         // if (version_compare($event->old, static::VERSION, '>=')) { | ||||
|         //     return false; | ||||
|         // } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										32
									
								
								app/Listeners/Updates/V10/Version101.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								app/Listeners/Updates/V10/Version101.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Laraspace\Listeners\Updates\V10; | ||||
|  | ||||
| use Illuminate\Contracts\Queue\ShouldQueue; | ||||
| use Illuminate\Queue\InteractsWithQueue; | ||||
| use Laraspace\Listeners\Updates\Listener; | ||||
| use Laraspace\Events\UpdateFinished; | ||||
| use Illuminate\Support\Facades\Artisan; | ||||
| use Laraspace\Setting; | ||||
|  | ||||
| class Version101 extends Listener | ||||
| { | ||||
|     const VERSION = '1.0.1'; | ||||
|  | ||||
|     /** | ||||
|      * Handle the event. | ||||
|      * | ||||
|      * @param  object  $event | ||||
|      * @return void | ||||
|      */ | ||||
|     public function handle(UpdateFinished $event) | ||||
|     { | ||||
|         // if (!$this->check($event)) { | ||||
|         //     return; | ||||
|         // } | ||||
|  | ||||
|         Artisan::call('db:seed', ['--class' => 'DemoSeeder', '--force' => true]); | ||||
|  | ||||
|         Setting::getSetting('version', self::VERSION); | ||||
|     } | ||||
| } | ||||
| @ -4,6 +4,8 @@ namespace Laraspace\Providers; | ||||
| use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; | ||||
| use Illuminate\Auth\Events\Registered; | ||||
| use Illuminate\Auth\Listeners\SendEmailVerificationNotification; | ||||
| use Laraspace\Events\UpdateFinished; | ||||
| use Laraspace\Listeners\Updates\V10\Version101; | ||||
|  | ||||
| class EventServiceProvider extends ServiceProvider | ||||
| { | ||||
| @ -13,8 +15,8 @@ class EventServiceProvider extends ServiceProvider | ||||
|      * @var array | ||||
|      */ | ||||
|     protected $listen = [ | ||||
|         'Laraspace\Events\SomeEvent' => [ | ||||
|             'Laraspace\Listeners\EventListener', | ||||
|         UpdateFinished::class=> [ | ||||
|             Version101::class, | ||||
|         ], | ||||
|         Registered::class => [ | ||||
|             SendEmailVerificationNotification::class, | ||||
|  | ||||
							
								
								
									
										36
									
								
								app/Space/SiteApi.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								app/Space/SiteApi.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Laraspace\Space; | ||||
|  | ||||
| use GuzzleHttp\Client; | ||||
| use GuzzleHttp\Exception\RequestException; | ||||
| use Laraspace\Setting; | ||||
|  | ||||
| trait SiteApi | ||||
| { | ||||
|  | ||||
|     protected static function getRemote($url, $data = array()) | ||||
|     { | ||||
|         $base = 'http://crater-main.test/'; | ||||
|  | ||||
|         $client = new Client(['verify' => false, 'base_uri' => $base]); | ||||
|  | ||||
|         $headers['headers'] = array( | ||||
|             'Accept'        => 'application/json', | ||||
|             'Referer'       => url('/'), | ||||
|             'crater'        => Setting::getSetting('version') | ||||
|         ); | ||||
|  | ||||
|         $data['http_errors'] = false; | ||||
|  | ||||
|         $data = array_merge($data, $headers); | ||||
|  | ||||
|         try { | ||||
|             $result = $client->get($url, $data); | ||||
|         } catch (RequestException $e) { | ||||
|             $result = $e; | ||||
|         } | ||||
|  | ||||
|         return $result; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										110
									
								
								app/Space/Updater.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								app/Space/Updater.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,110 @@ | ||||
| <?php | ||||
| namespace Laraspace\Space; | ||||
|  | ||||
| use File; | ||||
| use ZipArchive; | ||||
| use Artisan; | ||||
| use GuzzleHttp\Exception\RequestException; | ||||
| use Laraspace\Space\SiteApi; | ||||
| use Laraspace\Events\UpdateFinished; | ||||
| use Laraspace\Setting; | ||||
|  | ||||
| class Updater | ||||
| { | ||||
|     use SiteApi; | ||||
|  | ||||
|     public static function update($installed, $version) | ||||
|     { | ||||
|         $data = null; | ||||
|         $path = null; | ||||
|  | ||||
|         $url = '/download/'.$version; | ||||
|  | ||||
|         $response = static::getRemote($url, ['timeout' => 100, 'track_redirects' => true]); | ||||
|  | ||||
|         // Exception | ||||
|         if ($response instanceof RequestException) { | ||||
|             return [ | ||||
|                 'success' => false, | ||||
|                 'errors' => 'Download Exception', | ||||
|                 'data' => [ | ||||
|                     'path' => $path | ||||
|                 ] | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         if ($response && ($response->getStatusCode() == 200)) { | ||||
|             $data = $response->getBody()->getContents(); | ||||
|         } | ||||
|  | ||||
|         // Create temp directory | ||||
|         $path = 'temp-' . md5(mt_rand()); | ||||
|         $path2 = 'temp2-' . md5(mt_rand()); | ||||
|         $temp_path = storage_path('app/temp') . '/' . $path; | ||||
|         $temp_path2 = storage_path('app/temp') . '/' . $path2; | ||||
|  | ||||
|         if (!File::isDirectory($temp_path)) { | ||||
|             File::makeDirectory($temp_path); | ||||
|             File::makeDirectory($temp_path2); | ||||
|         } | ||||
|  | ||||
|         $file = $temp_path . '/upload.zip'; | ||||
|  | ||||
|         // Add content to the Zip file | ||||
|         $uploaded = is_int(file_put_contents($file, $data)) ? true : false; | ||||
|  | ||||
|         if (!$uploaded) { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         // Unzip the file | ||||
|         $zip = new ZipArchive(); | ||||
|  | ||||
|         if ($zip->open($file)) { | ||||
|             $zip->extractTo($temp_path2); | ||||
|         } | ||||
|  | ||||
|         $zip->close(); | ||||
|  | ||||
|         // Delete zip file | ||||
|         File::delete($file); | ||||
|  | ||||
|         if (!File::copyDirectory($temp_path2.'/crater', base_path())) { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         // Delete temp directory | ||||
|         File::deleteDirectory($temp_path); | ||||
|         File::deleteDirectory($temp_path2); | ||||
|  | ||||
|         try { | ||||
|             event(new UpdateFinished($installed, $version)); | ||||
|  | ||||
|             return [ | ||||
|                 'success' => true, | ||||
|                 'errors' => false, | ||||
|                 'data' => [] | ||||
|             ]; | ||||
|         } catch (\Exception $e) { | ||||
|             return [ | ||||
|                 'success' => false, | ||||
|                 'errors' => 'Update error', | ||||
|                 'data' => [] | ||||
|             ]; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static function checkForUpdate() | ||||
|     { | ||||
|         $data = null; | ||||
|         $url = '/check/latest/download/'.Setting::getSetting('version'); | ||||
|  | ||||
|         $response = static::getRemote($url, ['timeout' => 100, 'track_redirects' => true]); | ||||
|  | ||||
|         if ($response && ($response->getStatusCode() == 200)) { | ||||
|             $data = $response->getBody()->getContents(); | ||||
|         } | ||||
|  | ||||
|         return json_decode($data); | ||||
|     } | ||||
| } | ||||
| @ -216,7 +216,7 @@ class User extends Authenticatable implements HasMedia | ||||
|             $query->whereBetween( | ||||
|                 'invoice_date', | ||||
|                 [$start->format('Y-m-d'), $end->format('Y-m-d')] | ||||
|             )->where('paid_status', Invoice::STATUS_PAID); | ||||
|             ); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|  | ||||
| @ -18,7 +18,7 @@ class CreateItemsTable extends Migration | ||||
|             $table->string('name'); | ||||
|             $table->string('description')->nullable(); | ||||
|             $table->string('unit')->nullable(); | ||||
|             $table->integer('price'); | ||||
|             $table->unsignedBigInteger('price'); | ||||
|             $table->integer('company_id')->unsigned()->nullable(); | ||||
|             $table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade'); | ||||
|             $table->timestamps(); | ||||
|  | ||||
| @ -24,13 +24,13 @@ class CreateInvoicesTable extends Migration | ||||
|             $table->string('tax_per_item'); | ||||
|             $table->string('discount_per_item'); | ||||
|             $table->text('notes')->nullable(); | ||||
|             $table->decimal('discount', 15, 0)->nullable(); | ||||
|             $table->string('discount_type')->nullable(); | ||||
|             $table->integer('discount_val')->nullable(); | ||||
|             $table->integer('sub_total'); | ||||
|             $table->integer('total'); | ||||
|             $table->integer('tax'); | ||||
|             $table->integer('due_amount'); | ||||
|             $table->unsignedBigInteger('discount')->nullable(); | ||||
|             $table->unsignedBigInteger('discount_val')->nullable(); | ||||
|             $table->unsignedBigInteger('sub_total'); | ||||
|             $table->unsignedBigInteger('total'); | ||||
|             $table->unsignedBigInteger('tax'); | ||||
|             $table->unsignedBigInteger('due_amount'); | ||||
|             $table->boolean('sent')->default(false); | ||||
|             $table->boolean('viewed')->default(false); | ||||
|             $table->string('unique_hash')->nullable(); | ||||
|  | ||||
| @ -17,13 +17,13 @@ class CreateInvoiceItemsTable extends Migration | ||||
|             $table->increments('id'); | ||||
|             $table->string('name'); | ||||
|             $table->string('description')->nullable(); | ||||
|             $table->integer('quantity'); | ||||
|             $table->integer('price'); | ||||
|             $table->string('discount_type'); | ||||
|             $table->integer('discount_val'); | ||||
|             $table->decimal('discount', 15, 0); | ||||
|             $table->integer('tax'); | ||||
|             $table->integer('total'); | ||||
|             $table->unsignedBigInteger('quantity'); | ||||
|             $table->unsignedBigInteger('price'); | ||||
|             $table->unsignedBigInteger('discount_val'); | ||||
|             $table->unsignedBigInteger('discount'); | ||||
|             $table->unsignedBigInteger('tax'); | ||||
|             $table->unsignedBigInteger('total'); | ||||
|             $table->integer('invoice_id')->unsigned(); | ||||
|             $table->foreign('invoice_id')->references('id')->on('invoices')->onDelete('cascade'); | ||||
|             $table->integer('item_id')->unsigned()->nullable(); | ||||
|  | ||||
| @ -23,12 +23,12 @@ class CreateEstimatesTable extends Migration | ||||
|             $table->string('tax_per_item'); | ||||
|             $table->string('discount_per_item'); | ||||
|             $table->string('notes')->nullable(); | ||||
|             $table->decimal('discount', 15, 0)->nullable(); | ||||
|             $table->string('discount_type')->nullable(); | ||||
|             $table->integer('discount_val')->nullable(); | ||||
|             $table->integer('sub_total'); | ||||
|             $table->integer('total'); | ||||
|             $table->integer('tax'); | ||||
|             $table->unsignedBigInteger('discount')->nullable(); | ||||
|             $table->unsignedBigInteger('discount_val')->nullable(); | ||||
|             $table->unsignedBigInteger('sub_total'); | ||||
|             $table->unsignedBigInteger('total'); | ||||
|             $table->unsignedBigInteger('tax'); | ||||
|             $table->string('unique_hash')->nullable(); | ||||
|             $table->integer('user_id')->unsigned()->nullable(); | ||||
|             $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); | ||||
|  | ||||
| @ -17,13 +17,13 @@ class CreateEstimateItemsTable extends Migration | ||||
|             $table->increments('id'); | ||||
|             $table->string('name'); | ||||
|             $table->string('description')->nullable(); | ||||
|             $table->integer('quantity'); | ||||
|             $table->string('discount_type'); | ||||
|             $table->decimal('discount', 15, 0); | ||||
|             $table->integer('discount_val'); | ||||
|             $table->integer('price'); | ||||
|             $table->integer('tax'); | ||||
|             $table->integer('total'); | ||||
|             $table->unsignedBigInteger('quantity'); | ||||
|             $table->unsignedBigInteger('discount'); | ||||
|             $table->unsignedBigInteger('discount_val'); | ||||
|             $table->unsignedBigInteger('price'); | ||||
|             $table->unsignedBigInteger('tax'); | ||||
|             $table->unsignedBigInteger('total'); | ||||
|             $table->integer('item_id')->unsigned()->nullable(); | ||||
|             $table->foreign('item_id')->references('id')->on('items')->onDelete('cascade'); | ||||
|             $table->integer('estimate_id')->unsigned(); | ||||
|  | ||||
| @ -17,7 +17,7 @@ class CreateExpensesTable extends Migration | ||||
|             $table->increments('id'); | ||||
|             $table->date('expense_date'); | ||||
|             $table->string('attachment_receipt')->nullable(); | ||||
|             $table->integer('amount'); | ||||
|             $table->unsignedBigInteger('amount'); | ||||
|             $table->string('notes')->nullable(); | ||||
|             $table->integer('expense_category_id')->unsigned(); | ||||
|             $table->foreign('expense_category_id')->references('id')->on('expense_categories')->onDelete('cascade'); | ||||
|  | ||||
| @ -19,7 +19,7 @@ class CreatePaymentsTable extends Migration | ||||
|             $table->string('payment_mode')->nullable(); | ||||
|             $table->date('payment_date'); | ||||
|             $table->text('notes')->nullable(); | ||||
|             $table->decimal('amount', 15, 0); | ||||
|             $table->unsignedBigInteger('amount'); | ||||
|             $table->integer('user_id')->unsigned(); | ||||
|             $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); | ||||
|             $table->integer('invoice_id')->unsigned()->nullable(); | ||||
|  | ||||
| @ -30,7 +30,7 @@ class CreateTaxesTable extends Migration | ||||
|             $table->integer('company_id')->unsigned()->nullable(); | ||||
|             $table->foreign('company_id')->references('id')->on('companies'); | ||||
|             $table->string('name'); | ||||
|             $table->decimal('amount', 15, 0); | ||||
|             $table->unsignedBigInteger('amount'); | ||||
|             $table->decimal('percent', 5, 2); | ||||
|             $table->tinyInteger('compound_tax')->default(0); | ||||
|             $table->timestamps(); | ||||
|  | ||||
| @ -13,19 +13,19 @@ class EstimateTemplateSeeder extends Seeder | ||||
|     public function run() | ||||
|     { | ||||
|         EstimateTemplate::create([ | ||||
|             'name' => 'Estimate Template1', | ||||
|             'name' => 'Template 1', | ||||
|             'view' => 'estimate1', | ||||
|             'path' => '/assets/img/PDF/Template1.png' | ||||
|         ]); | ||||
|  | ||||
|         EstimateTemplate::create([ | ||||
|             'name' => 'Estimate Template2', | ||||
|             'name' => 'Template 2', | ||||
|             'view' => 'estimate2', | ||||
|             'path' => '/assets/img/PDF/Template2.png' | ||||
|         ]); | ||||
|  | ||||
|         EstimateTemplate::create([ | ||||
|             'name' => 'Estimate Template3', | ||||
|             'name' => 'Template 3', | ||||
|             'view' => 'estimate3', | ||||
|             'path' => '/assets/img/PDF/Template3.png' | ||||
|         ]); | ||||
|  | ||||
| @ -13,19 +13,19 @@ class InvoiceTemplateSeeder extends Seeder | ||||
|     public function run() | ||||
|     { | ||||
|         InvoiceTemplate::create([ | ||||
|             'name' => 'Invoice Template1', | ||||
|             'name' => 'Template 1', | ||||
|             'view' => 'invoice1', | ||||
|             'path' => '/assets/img/PDF/Template1.png' | ||||
|         ]); | ||||
|  | ||||
|         InvoiceTemplate::create([ | ||||
|             'name' => 'Invoice Template2', | ||||
|             'name' => ' Template 2', | ||||
|             'view' => 'invoice2', | ||||
|             'path' => '/assets/img/PDF/Template2.png' | ||||
|         ]); | ||||
|  | ||||
|         InvoiceTemplate::create([ | ||||
|             'name' => 'Invoice Template3', | ||||
|             'name' => 'Template 3', | ||||
|             'view' => 'invoice3', | ||||
|             'path' => '/assets/img/PDF/Template3.png' | ||||
|         ]); | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| <template> | ||||
|   <transition name="fade"> | ||||
|     <div v-if="modalActive" class="base-modal" :class="'size-' + modalSize"> | ||||
|     <div v-if="modalActive" :class="'size-' + modalSize" class="base-modal"> | ||||
|       <div class="modal-body"> | ||||
|         <div class="close-icon"> | ||||
|           <font-awesome-icon class="mr-2" icon="times" @click="closeModal"/> | ||||
|  | ||||
| @ -233,6 +233,8 @@ export default { | ||||
|     confirm_mark_as_accepted: 'This estimate will be marked as Accepted', | ||||
|     confirm_mark_as_rejected: 'This estimate will be marked as Rejected', | ||||
|     no_matching_estimates: 'There are no matching estimates!', | ||||
|     mark_as_sent_successfully: 'Estimate marked as sent successfully', | ||||
|     send_estimate_successfully: 'Estimate sent successfully', | ||||
|     errors: { | ||||
|       required: 'Field is required' | ||||
|     }, | ||||
| @ -324,6 +326,8 @@ export default { | ||||
|     list_of_invoices: 'This section will contain the list of invoices.', | ||||
|     select_invoice: 'Select Invoice', | ||||
|     no_matching_invoices: 'There are no matching invoices!', | ||||
|     mark_as_sent_successfully: 'Invoice marked as sent successfully', | ||||
|     send_invoice_successfully: 'Invoice sent successfully', | ||||
|     item: { | ||||
|       title: 'Item Title', | ||||
|       description: 'Description', | ||||
|  | ||||
| @ -237,6 +237,8 @@ export default { | ||||
|     confirm_mark_as_sent: 'Esta estimación se marcará como enviada', | ||||
|     confirm_mark_as_accepted: 'Esta estimación se marcará como Aceptada', | ||||
|     confirm_mark_as_rejected: 'Esta estimación se marcará como Rechazada', | ||||
|     mark_as_sent_successfully: 'Estimación marcada como enviada correctamente', | ||||
|     send_estimate_successfully: 'Estimación enviada con éxito', | ||||
|     errors: { | ||||
|       required: 'Se requiere campo' | ||||
|     }, | ||||
| @ -326,6 +328,8 @@ export default { | ||||
|     no_invoices: '¡Aún no hay facturas!', | ||||
|     list_of_invoices: 'Esta sección contendrá la lista de facturas.', | ||||
|     select_invoice: 'Seleccionar factura', | ||||
|     mark_as_sent_successfully: 'Factura marcada como enviada con éxito', | ||||
|     send_invoice_successfully: 'Factura enviada exitosamente', | ||||
|     item: { | ||||
|       title: 'Título del artículo', | ||||
|       description: 'Descripción', | ||||
|  | ||||
| @ -237,6 +237,8 @@ export default { | ||||
|     confirm_mark_as_sent: 'Cette estimation sera marquée comme envoyé', | ||||
|     confirm_mark_as_accepted: 'Cette estimation sera marquée comme acceptée', | ||||
|     confirm_mark_as_rejected: 'Cette estimation sera marquée comme Rejetée', | ||||
|     mark_as_sent_successfully: 'Estimation marquée comme envoyée avec succès', | ||||
|     send_estimate_successfully: 'Estimation envoyée avec succès', | ||||
|     errors: { | ||||
|       required: 'Champ requis' | ||||
|     }, | ||||
| @ -326,6 +328,8 @@ export default { | ||||
|     no_invoices: 'Aucune facture pour le moment!', | ||||
|     list_of_invoices: 'Cette section contiendra la liste des factures.', | ||||
|     select_invoice: 'Sélectionnez facture', | ||||
|     mark_as_sent_successfully: 'Facture marquée comme envoyée avec succès', | ||||
|     send_invoice_successfully: 'Facture envoyée avec succès', | ||||
|     item: { | ||||
|       title: 'Titre de larticle', | ||||
|       description: 'La description', | ||||
|  | ||||
| @ -396,7 +396,7 @@ export default { | ||||
|       swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$tc('estimates.confirm_delete', 1), | ||||
|         icon: 'error', | ||||
|         icon: '/assets/icon/trash-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true | ||||
|       }).then(async (willDelete) => { | ||||
| @ -416,7 +416,7 @@ export default { | ||||
|       swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$t('estimates.confirm_conversion'), | ||||
|         icon: 'error', | ||||
|         icon: '/assets/icon/envelope-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true | ||||
|       }).then(async (willDelete) => { | ||||
| @ -433,14 +433,24 @@ export default { | ||||
|       }) | ||||
|     }, | ||||
|     async onMarkAsSent (id) { | ||||
|       swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$t('estimates.confirm_mark_as_sent'), | ||||
|         icon: '/assets/icon/check-circle-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true | ||||
|       }).then(async (willMarkAsSent) => { | ||||
|         if (willMarkAsSent) { | ||||
|           const data = { | ||||
|             id: id | ||||
|           } | ||||
|           let response = await this.markAsSent(data) | ||||
|           this.$refs.table.refresh() | ||||
|           if (response.data) { | ||||
|         window.toastr['success'](this.$tc('estimates.mark_as_sent')) | ||||
|             window.toastr['success'](this.$tc('estimates.mark_as_sent_successfully')) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     async removeInvoice (id) { | ||||
| @ -448,7 +458,7 @@ export default { | ||||
|       swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$tc('invoices.confirm_delete'), | ||||
|         icon: 'error', | ||||
|         icon: '/assets/icon/trash-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true | ||||
|       }).then(async (willDelete) => { | ||||
| @ -465,25 +475,45 @@ export default { | ||||
|     }, | ||||
|  | ||||
|     async sendInvoice (id) { | ||||
|       swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$t('invoices.confirm_send'), | ||||
|         icon: '/assets/icon/paper-plane-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true | ||||
|       }).then(async (willSendInvoice) => { | ||||
|         if (willSendInvoice) { | ||||
|           const data = { | ||||
|             id: id | ||||
|           } | ||||
|           let response = await this.sendEmail(data) | ||||
|           this.$refs.table.refresh() | ||||
|           if (response.data) { | ||||
|         window.toastr['success'](this.$tc('invoices.send_invoice')) | ||||
|             window.toastr['success'](this.$tc('invoices.send_invoice_successfully')) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     async sentInvoice (id) { | ||||
|       swal({ | ||||
|         title: this.$t('general.are_you_sure'), | ||||
|         text: this.$t('invoices.invoice_mark_as_sent'), | ||||
|         icon: '/assets/icon/check-circle-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true | ||||
|       }).then(async (willMarkAsSend) => { | ||||
|         if (willMarkAsSend) { | ||||
|           const data = { | ||||
|             id: id | ||||
|           } | ||||
|           let response = await this.markAsSent(data) | ||||
|           this.$refs.table.refresh() | ||||
|           if (response.data) { | ||||
|         window.toastr['success'](this.$tc('invoices.mark_as_sent')) | ||||
|             window.toastr['success'](this.$tc('invoices.mark_as_sent_successfully')) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|     } | ||||
|  | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -425,7 +425,7 @@ export default { | ||||
|           if (response.data) { | ||||
|             this.filters.status = 'ACCEPTED' | ||||
|             this.$refs.table.refresh() | ||||
|             window.toastr['success'](this.$tc('estimates.marked_as_rejected_message')) | ||||
|             window.toastr['success'](this.$tc('estimates.confirm_mark_as_accepted')) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
| @ -570,7 +570,7 @@ export default { | ||||
|           let response = await this.markAsSent(data) | ||||
|           this.refreshTable() | ||||
|           if (response.data) { | ||||
|             window.toastr['success'](this.$tc('estimates.mark_as_sent')) | ||||
|             window.toastr['success'](this.$tc('estimates.mark_as_sent_successfully')) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
| @ -590,7 +590,7 @@ export default { | ||||
|           let response = await this.sendEmail(data) | ||||
|           this.refreshTable() | ||||
|           if (response.data) { | ||||
|             window.toastr['success'](this.$tc('estimates.mark_as_sent')) | ||||
|             window.toastr['success'](this.$tc('estimates.send_estimate_successfully')) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|  | ||||
| @ -5,6 +5,7 @@ | ||||
|       <div class="page-actions row"> | ||||
|         <div class="col-xs-2"> | ||||
|           <base-button | ||||
|             v-if="estimate.status !== 'SENT'" | ||||
|             :loading="isRequestOnGoing" | ||||
|             :disabled="isRequestOnGoing" | ||||
|             :outline="true" | ||||
| @ -144,6 +145,8 @@ export default { | ||||
|         orderByField: null, | ||||
|         searchText: null | ||||
|       }, | ||||
|       status: ['DRAFT', 'SENT', 'VIEWED', 'EXPIRED', 'ACCEPTED', 'REJECTED'], | ||||
|       isMarkAsSent: false, | ||||
|       isRequestOnGoing: false, | ||||
|       isSearching: false | ||||
|     } | ||||
| @ -230,11 +233,11 @@ export default { | ||||
|         dangerMode: true | ||||
|       }).then(async (willMarkAsSent) => { | ||||
|         if (willMarkAsSent) { | ||||
|           this.isRequestOnGoing = true | ||||
|           this.isMarkAsSent = true | ||||
|           let response = await this.markAsSent({id: this.estimate.id}) | ||||
|           this.isRequestOnGoing = false | ||||
|           this.isMarkAsSent = false | ||||
|           if (response.data) { | ||||
|             window.toastr['success'](this.$tc('estimates.mark_as_sent')) | ||||
|             window.toastr['success'](this.$tc('estimates.mark_as_sent_successfully')) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|  | ||||
| @ -390,15 +390,15 @@ export default { | ||||
|         icon: '/assets/icon/paper-plane-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true | ||||
|       }).then(async (Send_Invoice) => { | ||||
|         if (Send_Invoice) { | ||||
|       }).then(async (willSendInvoice) => { | ||||
|         if (willSendInvoice) { | ||||
|           const data = { | ||||
|             id: id | ||||
|           } | ||||
|           let response = await this.sendEmail(data) | ||||
|           this.refreshTable() | ||||
|           if (response.data) { | ||||
|             window.toastr['success'](this.$tc('invoices.send_invoice')) | ||||
|             window.toastr['success'](this.$tc('invoices.send_invoice_successfully')) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
| @ -410,15 +410,15 @@ export default { | ||||
|         icon: '/assets/icon/check-circle-solid.svg', | ||||
|         buttons: true, | ||||
|         dangerMode: true | ||||
|       }).then(async (MarkAsSend_Invoice) => { | ||||
|         if (MarkAsSend_Invoice) { | ||||
|       }).then(async (willMarkAsSend) => { | ||||
|         if (willMarkAsSend) { | ||||
|           const data = { | ||||
|             id: id | ||||
|           } | ||||
|           let response = await this.markAsSent(data) | ||||
|           this.refreshTable() | ||||
|           if (response.data) { | ||||
|             window.toastr['success'](this.$tc('invoices.mark_as_sent')) | ||||
|             window.toastr['success'](this.$tc('invoices.mark_as_sent_successfully')) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|  | ||||
| @ -263,7 +263,7 @@ | ||||
|         } | ||||
|  | ||||
|         tr.main-table-header th { | ||||
|             border-bottom: 1px solid #EAF1FB; | ||||
|             border-bottom: 0.620315px solid #E8E8E8; | ||||
|             font-style: normal; | ||||
|             font-weight: normal; | ||||
|             font-size: 12px; | ||||
|  | ||||
| @ -264,7 +264,7 @@ | ||||
|         } | ||||
|  | ||||
|         tr.main-table-header th { | ||||
|             border-bottom: 1px solid #EAF1FB; | ||||
|             border-bottom: 0.620315px solid #E8E8E8; | ||||
|             font-style: normal; | ||||
|             font-weight: normal; | ||||
|             font-size: 12px; | ||||
|  | ||||
| @ -1,6 +1,8 @@ | ||||
| @if ($estimate->notes != '' && $estimate->notes != null) | ||||
|     <div class="notes"> | ||||
|         <div class="notes-label"> | ||||
|             Notes | ||||
|         </div> | ||||
|         {{$estimate->notes}} | ||||
|     </div> | ||||
| @endif | ||||
|  | ||||
| @ -1,27 +1,32 @@ | ||||
| <table width="100%" class="table2" cellspacing="0" border="0"> | ||||
|     <tr class="main-table-header"> | ||||
|         <th class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 20px">#</th> | ||||
|         @if($estimate->discount_per_item === 'NO') | ||||
|             <th width="80%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 0px">Items</th> | ||||
|         @else | ||||
|             <th width="40%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 0px">Items</th> | ||||
|         @endif | ||||
|         <th width="17%" class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 20px">Quantity</th> | ||||
|         <th width="18%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 40px">Price</th> | ||||
|         <th width="18%" class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 40px">Price</th> | ||||
|         @if($estimate->discount_per_item === 'YES') | ||||
|             <th width="10%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 10px">Discount</th> | ||||
|             <th width="10%" class="ItemTableHeader" style="text-align: right; color: #55547A; padding-left: 10px">Discount</th> | ||||
|         @endif | ||||
|         <th width="15%" class="ItemTableHeader" style="text-align: right; color: #55547A;">Amount</th> | ||||
|     </tr> | ||||
|     @php | ||||
|         $index = 1 | ||||
|     @endphp | ||||
|     @foreach ($estimate->items as $item) | ||||
|         <tr class="item-details"> | ||||
|             <td class="inv-item items" style="text-align: right; color: #040405; padding-right: 20px; vertical-align: top;">{{$index}}</td> | ||||
|             <td class="inv-item items" style="text-align: left; color: #040405;padding-left: 0px"> | ||||
|                 <span>{{ $item->name }}</span><br> | ||||
|                 <span style="text-align: left; color: #595959; font-size: 9px; font-weight:300; line-height: 12px;">{{ $item->description }}</span> | ||||
|             </td> | ||||
|             <td class="inv-item items" style="text-align: right; color: #040405; padding-right: 20px">{{$item->quantity}}</td> | ||||
|             <td class="inv-item items" style="text-align: left; color: #040405; padding-left: 40px">{{$item->price/100}}</td> | ||||
|             <td class="inv-item items" style="text-align: right; color: #040405; padding-right: 40px">{{$item->price/100}}</td> | ||||
|             @if($estimate->discount_per_item === 'YES') | ||||
|                 <td class="inv-item items" style="text-align: left; color: #040405; padding-left: 10px"> | ||||
|                 <td class="inv-item items" style="text-align: right; color: #040405; padding-left: 10px"> | ||||
|                     @if($item->discount_type === 'fixed') | ||||
|                         {{$item->discount_val/100}} | ||||
|                     @endif | ||||
| @ -30,12 +35,15 @@ | ||||
|                     @endif | ||||
|                 </td> | ||||
|             @endif | ||||
|             <td class="inv-item items" style="text-align: right; color: #040405">{{$item->total/100}}</td> | ||||
|             <td class="inv-item items" style="text-align: right; color: #040405;">{{$item->total/100}}</td> | ||||
|         </tr> | ||||
|         @php | ||||
|             $index += 1 | ||||
|         @endphp | ||||
|     @endforeach | ||||
| </table> | ||||
|  | ||||
| <table width="100%" style="margin-left:420px" cellspacing="0px" border="0" class="table3"> | ||||
| <table width="100%" cellspacing="0px" style="margin-left:420px" border="0" class="table3 @if(count($estimate->items) > 12) page-break @endif"> | ||||
|     <tr> | ||||
|         <td class="no-borde" style="color: #55547A; padding-left:10px;  font-size:12px;">Subtotal</td> | ||||
|         <td class="no-border items" | ||||
|  | ||||
| @ -11,6 +11,7 @@ | ||||
|         html { | ||||
|             margin: 0px; | ||||
|             padding: 0px; | ||||
|             margin-top: 50px; | ||||
|         } | ||||
|  | ||||
|         table { | ||||
| @ -35,7 +36,7 @@ | ||||
|             width: 100%; | ||||
|             height: 90px; | ||||
|             left: 0px; | ||||
|             top: 0px; | ||||
|             top: -50px; | ||||
|         } | ||||
|  | ||||
|         .header-logo { | ||||
| @ -71,7 +72,7 @@ | ||||
|  | ||||
|         .wrapper { | ||||
|            display: block; | ||||
|            padding-top: 60px; | ||||
|            padding-top: 16px; | ||||
|            padding-bottom: 60px; | ||||
|         } | ||||
|  | ||||
| @ -251,6 +252,7 @@ | ||||
|             page-break-after: auto; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         .table2 hr { | ||||
|             height:0.1px; | ||||
|         } | ||||
| @ -263,7 +265,7 @@ | ||||
|         } | ||||
|  | ||||
|         tr.main-table-header th { | ||||
|             border-bottom: 1px solid #EAF1FB; | ||||
|             border-bottom: 0.620315px solid #E8E8E8; | ||||
|             font-style: normal; | ||||
|             font-weight: normal; | ||||
|             font-size: 12px; | ||||
| @ -380,8 +382,8 @@ | ||||
|                 </td> | ||||
|             </tr> | ||||
|         </table> | ||||
|         <hr class="header-line" style="border: 0.620315px solid #E8E8E8;"/> | ||||
|     </div> | ||||
|     <hr class="header-line" /> | ||||
|     <div class="wrapper"> | ||||
|         <div class="address"> | ||||
|             <div class="company"> | ||||
|  | ||||
| @ -264,7 +264,7 @@ | ||||
|         } | ||||
|  | ||||
|         tr.main-table-header th { | ||||
|             border-bottom: 1px solid #EAF1FB; | ||||
|             border-bottom: 0.620315px solid #E8E8E8; | ||||
|             font-style: normal; | ||||
|             font-weight: normal; | ||||
|             font-size: 12px; | ||||
|  | ||||
| @ -1,6 +1,8 @@ | ||||
| @if ($invoice->notes != '' && $invoice->notes != null) | ||||
|     <div class="notes"> | ||||
|         <div class="notes-label"> | ||||
|             Notes | ||||
|         </div> | ||||
|         {{$invoice->notes}} | ||||
|     </div> | ||||
| @endif | ||||
|  | ||||
| @ -1,27 +1,32 @@ | ||||
| <table width="100%" class="table2" cellspacing="0" border="0"> | ||||
|     <tr class="main-table-header"> | ||||
|         <th class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 20px">#</th> | ||||
|         @if($invoice->discount_per_item === 'NO') | ||||
|             <th width="80%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 0px">Items</th> | ||||
|         @else | ||||
|             <th width="40%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 0px">Items</th> | ||||
|         @endif | ||||
|         <th width="17%" class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 20px">Quantity</th> | ||||
|         <th width="18%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 40px">Price</th> | ||||
|         <th width="18%" class="ItemTableHeader" style="text-align: right; color: #55547A; padding-right: 40px">Price</th> | ||||
|         @if($invoice->discount_per_item === 'YES') | ||||
|             <th width="10%" class="ItemTableHeader" style="text-align: left; color: #55547A; padding-left: 10px">Discount</th> | ||||
|             <th width="10%" class="ItemTableHeader" style="text-align: right; color: #55547A; padding-left: 10px">Discount</th> | ||||
|         @endif | ||||
|         <th width="15%" class="ItemTableHeader" style="text-align: right; color: #55547A;">Amount</th> | ||||
|     </tr> | ||||
|     @php | ||||
|         $index = 1 | ||||
|     @endphp | ||||
|     @foreach ($invoice->items as $item) | ||||
|         <tr class="item-details"> | ||||
|             <td class="inv-item items" style="text-align: right; color: #040405; padding-right: 20px; vertical-align: top;">{{$index}}</td> | ||||
|             <td class="inv-item items" style="text-align: left; color: #040405;padding-left: 0px"> | ||||
|                 <span>{{ $item->name }}</span><br> | ||||
|                 <span style="text-align: left; color: #595959; font-size: 9px; font-weight:300; line-height: 12px;">{{ $item->description }}</span> | ||||
|             </td> | ||||
|             <td class="inv-item items" style="text-align: right; color: #040405; padding-right: 20px">{{$item->quantity}}</td> | ||||
|             <td class="inv-item items" style="text-align: left; color: #040405; padding-left: 40px">{{$item->price/100}}</td> | ||||
|             <td class="inv-item items" style="text-align: right; color: #040405; padding-right: 40px">{{$item->price/100}}</td> | ||||
|             @if($invoice->discount_per_item === 'YES') | ||||
|                 <td class="inv-item items" style="text-align: left; color: #040405; padding-left: 10px"> | ||||
|                 <td class="inv-item items" style="text-align: right; color: #040405; padding-left: 10px"> | ||||
|                     @if($item->discount_type === 'fixed') | ||||
|                         {{$item->discount_val/100}} | ||||
|                     @endif | ||||
| @ -30,8 +35,11 @@ | ||||
|                     @endif | ||||
|                 </td> | ||||
|             @endif | ||||
|             <td class="inv-item items" style="text-align: right; color: #040405">{{$item->total/100}}</td> | ||||
|             <td class="inv-item items" style="text-align: right; color: #040405;">{{$item->total/100}}</td> | ||||
|         </tr> | ||||
|         @php | ||||
|             $index += 1 | ||||
|         @endphp | ||||
|     @endforeach | ||||
| </table> | ||||
|  | ||||
|  | ||||
| @ -106,6 +106,8 @@ Route::group(['middleware' => 'redirect-if-installed'], function () { | ||||
|         'uses' => 'OnboardingController@companySettings' | ||||
|     ]); | ||||
| }); | ||||
|  | ||||
|  | ||||
| // App version | ||||
| // ---------------------------------- | ||||
|  | ||||
| @ -120,6 +122,18 @@ Route::group(['middleware' => 'api'], function () { | ||||
|       'middleware' => 'admin' | ||||
|     ], function () { | ||||
|  | ||||
|         // Auto update routes | ||||
|         //---------------------------------- | ||||
|         Route::post('/update', [ | ||||
|             'as' => 'auto.update', | ||||
|             'uses' => 'UpdateController@update' | ||||
|         ]); | ||||
|  | ||||
|         Route::get('/check/update', [ | ||||
|             'as' => 'check.update', | ||||
|             'uses' => 'UpdateController@checkLatestVersion' | ||||
|         ]); | ||||
|  | ||||
|         Route::get('/bootstrap', [ | ||||
|             'as' => 'bootstrap', | ||||
|             'uses' => 'UsersController@getBootstrap' | ||||
|  | ||||
		Reference in New Issue
	
	Block a user