diff --git a/app/Http/Controllers/Sales/Invoices.php b/app/Http/Controllers/Sales/Invoices.php index 38a2d66e2..fd72a8f61 100644 --- a/app/Http/Controllers/Sales/Invoices.php +++ b/app/Http/Controllers/Sales/Invoices.php @@ -77,6 +77,8 @@ class Invoices extends Controller $date_format = $this->getCompanyDateFormat(); + $discount_location = $invoice->totals->contains($invoice->totals->where('code', 'discount')->first()) ? 'in_totals' : 'per_item'; + // Get Invoice Totals foreach ($invoice->totals as $invoice_total) { $invoice->{$invoice_total->code} = $invoice_total->amount; @@ -90,7 +92,22 @@ class Invoices extends Controller $invoice->grand_total = round($invoice->total - $invoice->paid, $currency->precision); } - return view('sales.invoices.show', compact('invoice', 'accounts', 'currencies', 'currency', 'account_currency_code', 'customers', 'categories', 'payment_methods', 'signed_url', 'date_format')); + return view( + 'sales.invoices.show', + compact( + 'invoice', + 'accounts', + 'currencies', + 'currency', + 'account_currency_code', + 'customers', + 'categories', + 'payment_methods', + 'signed_url', + 'date_format', + 'discount_location' + ) + ); } /** diff --git a/app/Http/Controllers/Settings/Defaults.php b/app/Http/Controllers/Settings/Defaults.php index 476c8a155..c9bf56608 100644 --- a/app/Http/Controllers/Settings/Defaults.php +++ b/app/Http/Controllers/Settings/Defaults.php @@ -27,12 +27,18 @@ class Defaults extends Controller $payment_methods = Modules::getPaymentMethods(); + $discount_locations = [ + 'in_totals' => trans('settings.default.discount_in_totals'), + 'per_item' => trans('settings.default.discount_per_item'), + ]; + return view('settings.default.edit', compact( 'setting', 'accounts', 'currencies', 'taxes', - 'payment_methods' + 'payment_methods', + 'discount_locations' )); } } diff --git a/app/Jobs/Sale/CreateInvoiceItem.php b/app/Jobs/Sale/CreateInvoiceItem.php index 5e78a0fea..fc6994dd2 100644 --- a/app/Jobs/Sale/CreateInvoiceItem.php +++ b/app/Jobs/Sale/CreateInvoiceItem.php @@ -40,7 +40,7 @@ class CreateInvoiceItem extends Job // Apply discount to amount if (!empty($this->request['discount'])) { - $item_discounted_amount = $item_amount - ($item_amount * ($this->request['discount'] / 100)); + $item_discounted_amount = $item_amount -= ($item_amount * ($this->request['discount'] / 100)); } $tax_amount = 0; @@ -138,6 +138,7 @@ class CreateInvoiceItem extends Job 'quantity' => (double) $this->request['quantity'], 'price' => (double) $this->request['price'], 'tax' => $item_tax_total, + 'discount_rate' => $this->request['discount'], 'total' => $item_amount, ]); diff --git a/app/Models/Sale/InvoiceItem.php b/app/Models/Sale/InvoiceItem.php index 692269912..e55577291 100644 --- a/app/Models/Sale/InvoiceItem.php +++ b/app/Models/Sale/InvoiceItem.php @@ -17,7 +17,18 @@ class InvoiceItem extends Model * * @var array */ - protected $fillable = ['company_id', 'invoice_id', 'item_id', 'name', 'quantity', 'price', 'total', 'tax']; + protected $fillable = [ + 'company_id', + 'invoice_id', + 'item_id', + 'name', + 'quantity', + 'price', + 'total', + 'tax', + 'discount_rate', + 'discount_type', + ]; /** * Clonable relationships. @@ -83,6 +94,22 @@ class InvoiceItem extends Model $this->attributes['tax'] = (double) $value; } + /** + * Get the formatted discount. + * + * @return string + */ + public function getDiscountRateAttribute($value) + { + if (setting('localisation.percent_position', 'after') === 'after') { + $text = ($this->discount_type === 'normal') ? $value . '%' : $value; + } else { + $text = ($this->discount_type === 'normal') ? '%' . $value : $value; + } + + return $text; + } + /** * Convert tax to Array. * diff --git a/app/Models/Sale/InvoiceItemDiscount.php b/app/Models/Sale/InvoiceItemDiscount.php new file mode 100644 index 000000000..2e4ffffbc --- /dev/null +++ b/app/Models/Sale/InvoiceItemDiscount.php @@ -0,0 +1,42 @@ +belongsTo('App\Models\Sale\Invoice'); + } + + public function item() + { + return $this->belongsToThrough('App\Models\Common\Item', 'App\Models\Sale\InvoiceItem', 'invoice_item_id')->withDefault(['name' => trans('general.na')]); + } + + /** + * Convert rate to double. + * + * @param string $value + * @return void + */ + public function setRateAttribute($value) + { + $this->attributes['rate'] = (double) $value; + } +} diff --git a/database/migrations/2020_01_08_000000_core_v200.php b/database/migrations/2020_01_08_000000_core_v200.php index 0735f5a66..cb6acab5a 100644 --- a/database/migrations/2020_01_08_000000_core_v200.php +++ b/database/migrations/2020_01_08_000000_core_v200.php @@ -240,6 +240,11 @@ class CoreV200 extends Migration Schema::table('users', function (Blueprint $table) { $table->string('landing_page', 70)->nullable()->default('dashboard'); }); + + Schema::table('invoice_items', function (Blueprint $table) { + $table->double('discount_rate', 15, 4)->default('0.0000'); + $table->string('discount_type')->default('normal'); + }); } /** diff --git a/database/seeds/Settings.php b/database/seeds/Settings.php index d12ef1230..386472d27 100644 --- a/database/seeds/Settings.php +++ b/database/seeds/Settings.php @@ -63,6 +63,7 @@ class Settings extends Seeder 'invoice.color' => '#55588b', 'default.payment_method' => 'offline-payments.cash.1', 'default.list_limit' => '25', + 'default.discount_location' => 'in_totals', 'default.use_gravatar' => '0', 'email.protocol' => 'mail', 'email.sendmail_path' => '/usr/sbin/sendmail -bs', diff --git a/public/css/custom.css b/public/css/custom.css index de7a60b65..0ea69d22c 100644 --- a/public/css/custom.css +++ b/public/css/custom.css @@ -740,6 +740,14 @@ table .align-items-center td span.badge /*--Quantity Width Finish--*/ +/*--Discount Width--*/ +.w-12 +{ + width: 12%; +} +/*--Discount Width Finish--*/ + + /*--------Responsive--------*/ /*--Xs Breakpoint--*/ @media (max-width: 575.98px) diff --git a/resources/assets/js/views/sales/invoices.js b/resources/assets/js/views/sales/invoices.js index c5e485fbb..0983b53da 100644 --- a/resources/assets/js/views/sales/invoices.js +++ b/resources/assets/js/views/sales/invoices.js @@ -75,6 +75,7 @@ const app = new Vue({ price: (item.price).toFixed(2), quantity: item.quantity, tax_id: item.tax_id, + discount: item.discount_rate, total: (item.total).toFixed(2) }); }); @@ -109,7 +110,8 @@ const app = new Vue({ let tax_total = 0; let grand_total = 0; let items = this.form.items; - let discount = this.form.discount; + let discount_in_totals = this.form.discount; + let discount = ''; if (items.length) { let index = 0; @@ -125,8 +127,14 @@ const app = new Vue({ // item discount calculate. let item_discounted_total = item_sub_total; - if (discount) { - item_discounted_total = item_sub_total - (item_sub_total * (discount / 100)); + if (discount_in_totals) { + item_discounted_total = item_sub_total - (item_sub_total * (discount_in_totals / 100)); + discount = discount_in_totals; + } + + if (item.discount) { + item_discounted_total = item_sub_total = item_sub_total - (item_sub_total * (item.discount / 100)); + discount = item.discount; } // item tax calculate. @@ -202,12 +210,12 @@ const app = new Vue({ this.totals.tax = tax_total; // Apply discount to total - if (discount) { - discount_total = sub_total * (discount / 100); + if (discount_in_totals) { + discount_total = sub_total * (discount_in_totals / 100); this.totals.discount = discount_total; - sub_total = sub_total - (sub_total * (discount / 100)); + sub_total = sub_total - (sub_total * (discount_in_totals / 100)); } // set all item grand total. diff --git a/resources/lang/en-GB/settings.php b/resources/lang/en-GB/settings.php index 044061471..c6228526d 100644 --- a/resources/lang/en-GB/settings.php +++ b/resources/lang/en-GB/settings.php @@ -59,9 +59,12 @@ return [ ], 'default' => [ - 'description' => 'Default account, currency, language of your company', - 'list_limit' => 'Records Per Page', - 'use_gravatar' => 'Use Gravatar', + 'description' => 'Default account, currency, language of your company', + 'list_limit' => 'Records Per Page', + 'use_gravatar' => 'Use Gravatar', + 'discount_location' => 'Discount', + 'discount_per_item' => 'Per Item', + 'discount_in_totals' => 'In Totals', ], 'email' => [ diff --git a/resources/views/sales/invoices/create.blade.php b/resources/views/sales/invoices/create.blade.php index 74415c55c..2fd310441 100644 --- a/resources/views/sales/invoices/create.blade.php +++ b/resources/views/sales/invoices/create.blade.php @@ -51,6 +51,12 @@