diff --git a/app/Http/Controllers/Settings/Defaults.php b/app/Http/Controllers/Settings/Defaults.php index c9bf56608..476c8a155 100644 --- a/app/Http/Controllers/Settings/Defaults.php +++ b/app/Http/Controllers/Settings/Defaults.php @@ -27,18 +27,12 @@ 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', - 'discount_locations' + 'payment_methods' )); } } diff --git a/app/Jobs/Purchase/CreateBill.php b/app/Jobs/Purchase/CreateBill.php index 531091095..c87539e10 100644 --- a/app/Jobs/Purchase/CreateBill.php +++ b/app/Jobs/Purchase/CreateBill.php @@ -64,7 +64,7 @@ class CreateBill extends Job protected function createItemsAndTotals() { // Create items - list($sub_total, $taxes) = $this->createItems(); + list($sub_total, $discount_amount_total, $taxes) = $this->createItems(); $sort_order = 1; @@ -83,8 +83,23 @@ class CreateBill extends Job $sort_order++; // Add discount + if ($discount_amount_total > 0) { + BillTotal::create([ + 'company_id' => $this->bill->company_id, + 'bill_id' => $this->bill->id, + 'code' => 'item_discount', + 'name' => 'bills.item_discount', + 'amount' => $discount_amount_total, + 'sort_order' => $sort_order, + ]); + + $this->request['amount'] -= $discount_amount_total; + + $sort_order++; + } + if (!empty($this->request['discount'])) { - $discount_total = $sub_total * ($this->request['discount'] / 100); + $discount_total = ($sub_total - $discount_amount_total) * ($this->request['discount'] / 100); BillTotal::create([ 'company_id' => $this->bill->company_id, @@ -155,7 +170,7 @@ class CreateBill extends Job protected function createItems() { - $sub_total = 0; + $sub_total = $discount_amount = $discount_amount_total = 0; $taxes = []; @@ -170,8 +185,14 @@ class CreateBill extends Job $bill_item = $this->dispatch(new CreateBillItem($item, $this->bill)); + $item_amount = (double) $item['price'] * (double) $item['quantity']; + + $discount_amount = ($item_amount * ($item['discount'] / 100)); + // Calculate totals - $sub_total += $bill_item->total; + $sub_total += $bill_item->total + $discount_amount; + + $discount_amount_total += $discount_amount; if (!$bill_item->item_taxes) { continue; @@ -190,6 +211,6 @@ class CreateBill extends Job } } - return [$sub_total, $taxes]; + return [$sub_total, $discount_amount_total, $taxes]; } } diff --git a/app/Jobs/Purchase/UpdateBill.php b/app/Jobs/Purchase/UpdateBill.php index 6b673d723..4e8420eff 100644 --- a/app/Jobs/Purchase/UpdateBill.php +++ b/app/Jobs/Purchase/UpdateBill.php @@ -72,7 +72,7 @@ class UpdateBill extends Job protected function createItemsAndTotals() { // Create items - list($sub_total, $taxes) = $this->createItems(); + list($sub_total, $discount_amount_total, $taxes) = $this->createItems(); // Delete current totals $this->deleteRelationships($this->bill, 'totals'); @@ -94,8 +94,23 @@ class UpdateBill extends Job $sort_order++; // Add discount + if ($discount_amount_total > 0) { + BillTotal::create([ + 'company_id' => $this->bill->company_id, + 'bill_id' => $this->bill->id, + 'code' => 'item_discount', + 'name' => 'bills.item_discount', + 'amount' => $discount_amount_total, + 'sort_order' => $sort_order, + ]); + + $this->request['amount'] -= $discount_amount_total; + + $sort_order++; + } + if (!empty($this->request['discount'])) { - $discount_total = $sub_total * ($this->request['discount'] / 100); + $discount_total = ($sub_total - $discount_amount_total) * ($this->request['discount'] / 100); BillTotal::create([ 'company_id' => $this->bill->company_id, @@ -166,7 +181,7 @@ class UpdateBill extends Job protected function createItems() { - $sub_total = 0; + $sub_total = $discount_amount = $discount_amount_total = 0; $taxes = []; @@ -184,8 +199,14 @@ class UpdateBill extends Job $bill_item = $this->dispatch(new CreateBillItem($item, $this->bill)); + $item_amount = (double) $item['price'] * (double) $item['quantity']; + + $discount_amount = ($item_amount * ($item['discount'] / 100)); + // Calculate totals - $sub_total += $bill_item->total; + $sub_total += $bill_item->total + $discount_amount; + + $discount_amount_total += $discount_amount; if (!$bill_item->item_taxes) { continue; @@ -204,6 +225,6 @@ class UpdateBill extends Job } } - return [$sub_total, $taxes]; + return [$sub_total, $discount_amount_total, $taxes]; } } diff --git a/app/Jobs/Sale/CreateInvoice.php b/app/Jobs/Sale/CreateInvoice.php index 6ac4c4df1..7ade6315f 100644 --- a/app/Jobs/Sale/CreateInvoice.php +++ b/app/Jobs/Sale/CreateInvoice.php @@ -64,7 +64,7 @@ class CreateInvoice extends Job protected function createItemsAndTotals() { // Create items - list($sub_total, $taxes) = $this->createItems(); + list($sub_total, $discount_amount_total, $taxes) = $this->createItems(); $sort_order = 1; @@ -83,8 +83,23 @@ class CreateInvoice extends Job $sort_order++; // Add discount + if ($discount_amount_total > 0) { + InvoiceTotal::create([ + 'company_id' => $this->invoice->company_id, + 'invoice_id' => $this->invoice->id, + 'code' => 'item_discount', + 'name' => 'invoices.item_discount', + 'amount' => $discount_amount_total, + 'sort_order' => $sort_order, + ]); + + $this->request['amount'] -= $discount_amount_total; + + $sort_order++; + } + if (!empty($this->request['discount'])) { - $discount_total = $sub_total * ($this->request['discount'] / 100); + $discount_total = ($sub_total - $discount_amount_total) * ($this->request['discount'] / 100); InvoiceTotal::create([ 'company_id' => $this->invoice->company_id, @@ -155,7 +170,7 @@ class CreateInvoice extends Job protected function createItems() { - $sub_total = 0; + $sub_total = $discount_amount = $discount_amount_total = 0; $taxes = []; @@ -170,8 +185,14 @@ class CreateInvoice extends Job $invoice_item = $this->dispatch(new CreateInvoiceItem($item, $this->invoice)); + $item_amount = (double) $item['price'] * (double) $item['quantity']; + + $discount_amount = ($item_amount * ($item['discount'] / 100)); + // Calculate totals - $sub_total += $invoice_item->total; + $sub_total += $invoice_item->total + $discount_amount; + + $discount_amount_total += $discount_amount; if (!$invoice_item->item_taxes) { continue; @@ -190,6 +211,6 @@ class CreateInvoice extends Job } } - return [$sub_total, $taxes]; + return [$sub_total, $discount_amount_total, $taxes]; } } diff --git a/app/Jobs/Sale/UpdateInvoice.php b/app/Jobs/Sale/UpdateInvoice.php index 344534d2c..85c15c1c4 100644 --- a/app/Jobs/Sale/UpdateInvoice.php +++ b/app/Jobs/Sale/UpdateInvoice.php @@ -72,7 +72,7 @@ class UpdateInvoice extends Job protected function createItemsAndTotals() { // Create items - list($sub_total, $taxes) = $this->createItems(); + list($sub_total, $discount_amount_total, $taxes) = $this->createItems(); // Delete current totals $this->deleteRelationships($this->invoice, 'totals'); @@ -94,8 +94,23 @@ class UpdateInvoice extends Job $sort_order++; // Add discount + if ($discount_amount_total > 0) { + InvoiceTotal::create([ + 'company_id' => $this->invoice->company_id, + 'invoice_id' => $this->invoice->id, + 'code' => 'item_discount', + 'name' => 'invoices.item_discount', + 'amount' => $discount_amount_total, + 'sort_order' => $sort_order, + ]); + + $this->request['amount'] -= $discount_amount_total; + + $sort_order++; + } + if (!empty($this->request['discount'])) { - $discount_total = $sub_total * ($this->request['discount'] / 100); + $discount_total = ($sub_total - $discount_amount_total) * ($this->request['discount'] / 100); InvoiceTotal::create([ 'company_id' => $this->invoice->company_id, @@ -166,7 +181,7 @@ class UpdateInvoice extends Job protected function createItems() { - $sub_total = 0; + $sub_total = $discount_amount = $discount_amount_total = 0; $taxes = []; @@ -184,8 +199,14 @@ class UpdateInvoice extends Job $invoice_item = $this->dispatch(new CreateInvoiceItem($item, $this->invoice)); + $item_amount = (double) $item['price'] * (double) $item['quantity']; + + $discount_amount = ($item_amount * ($item['discount'] / 100)); + // Calculate totals - $sub_total += $invoice_item->total; + $sub_total += $invoice_item->total + $discount_amount; + + $discount_amount_total += $discount_amount; if (!$invoice_item->item_taxes) { continue; @@ -204,6 +225,6 @@ class UpdateInvoice extends Job } } - return [$sub_total, $taxes]; + return [$sub_total, $discount_amount_total, $taxes]; } } diff --git a/database/migrations/2020_03_20_183732_core_v208.php b/database/migrations/2020_03_20_183732_core_v208.php index 481ad86ed..896df429d 100644 --- a/database/migrations/2020_03_20_183732_core_v208.php +++ b/database/migrations/2020_03_20_183732_core_v208.php @@ -20,6 +20,14 @@ class CoreV208 extends Migration $table->string('discount_type')->default('normal')->after('discount_rate'); } ); + + Schema::table( + 'bill_items', + function (Blueprint $table) { + $table->double('discount_rate', 15, 4)->default('0.0000')->after('tax'); + $table->string('discount_type')->default('normal')->after('discount_rate'); + } + ); } /** @@ -35,5 +43,12 @@ class CoreV208 extends Migration $table->dropColumn(['discount_rate', 'discount_type']); } ); + + Schema::table( + 'bill_items', + function (Blueprint $table) { + $table->dropColumn(['discount_rate', 'discount_type']); + } + ); } } diff --git a/resources/assets/js/views/purchases/bills.js b/resources/assets/js/views/purchases/bills.js index ef333548d..67bf7e086 100644 --- a/resources/assets/js/views/purchases/bills.js +++ b/resources/assets/js/views/purchases/bills.js @@ -32,6 +32,7 @@ const app = new Vue({ bulk_action: new BulkAction('bills'), totals: { sub: 0, + item_discount: '', discount: '', discount_text: false, tax: 0, @@ -107,6 +108,7 @@ const app = new Vue({ onCalculateTotal() { let sub_total = 0; let discount_total = 0; + let item_discount_total = 0; let tax_total = 0; let grand_total = 0; let items = this.form.items; @@ -122,18 +124,21 @@ const app = new Vue({ let item = items[index]; // item sub total calcute. - let item_sub_total = item.price * item.quantity; + let item_total = item.price * item.quantity; // item discount calculate. - let item_discounted_total = item_sub_total; + let item_discounted_total = item_total; if (discount_in_totals) { - item_discounted_total = item_sub_total - (item_sub_total * (discount_in_totals / 100)); + item_discounted_total = item_total - (item_total * (discount_in_totals / 100)); discount = discount_in_totals; } + let discount_amount = 0; + if (item.discount) { - item_discounted_total = item_sub_total = item_sub_total - (item_sub_total * (item.discount / 100)); + discount_amount = item_total * (item.discount / 100); + item_discounted_total = item_total - discount_amount; discount = item.discount; } @@ -186,7 +191,7 @@ const app = new Vue({ item_tax_total = item_sub_and_tax_total - item_base_rate; - item_sub_total = item_base_rate + discount; + item_total = item_base_rate + discount; } if (compounds.length) { @@ -197,10 +202,15 @@ const app = new Vue({ } // set item total - items[index].total = item_sub_total; + if (item.discount) { + items[index].total = item_discounted_total; + } else { + items[index].total = item_total; + } // calculate sub, tax, discount all items. - sub_total += item_sub_total; + item_discount_total += discount_amount; + sub_total += item_total; tax_total += item_tax_total; } } @@ -208,6 +218,9 @@ const app = new Vue({ // set global total variable. this.totals.sub = sub_total; this.totals.tax = tax_total; + this.totals.item_discount = item_discount_total; + + sub_total -= item_discount_total; // Apply discount to total if (discount_in_totals) { diff --git a/resources/assets/js/views/sales/invoices.js b/resources/assets/js/views/sales/invoices.js index be3875acb..961f59d40 100644 --- a/resources/assets/js/views/sales/invoices.js +++ b/resources/assets/js/views/sales/invoices.js @@ -32,6 +32,7 @@ const app = new Vue({ bulk_action: new BulkAction('invoices'), totals: { sub: 0, + item_discount: '', discount: '', discount_text: false, tax: 0, @@ -107,6 +108,7 @@ const app = new Vue({ onCalculateTotal() { let sub_total = 0; let discount_total = 0; + let item_discount_total = 0; let tax_total = 0; let grand_total = 0; let items = this.form.items; @@ -122,18 +124,21 @@ const app = new Vue({ let item = items[index]; // item sub total calcute. - let item_sub_total = item.price * item.quantity; + let item_total = item.price * item.quantity; // item discount calculate. - let item_discounted_total = item_sub_total; + let item_discounted_total = item_total; if (discount_in_totals) { - item_discounted_total = item_sub_total - (item_sub_total * (discount_in_totals / 100)); + item_discounted_total = item_total - (item_total * (discount_in_totals / 100)); discount = discount_in_totals; } + let discount_amount = 0; + if (item.discount) { - item_discounted_total = item_sub_total = item_sub_total - (item_sub_total * (item.discount / 100)); + discount_amount = item_total * (item.discount / 100); + item_discounted_total = item_total - discount_amount; discount = item.discount; } @@ -186,7 +191,7 @@ const app = new Vue({ item_tax_total = item_sub_and_tax_total - item_base_rate; - item_sub_total = item_base_rate + discount; + item_total = item_base_rate + discount; } if (compounds.length) { @@ -197,10 +202,15 @@ const app = new Vue({ } // set item total - items[index].total = item_sub_total; + if (item.discount) { + items[index].total = item_discounted_total; + } else { + items[index].total = item_total; + } // calculate sub, tax, discount all items. - sub_total += item_sub_total; + item_discount_total += discount_amount; + sub_total += item_total; tax_total += item_tax_total; } } @@ -208,6 +218,9 @@ const app = new Vue({ // set global total variable. this.totals.sub = sub_total; this.totals.tax = tax_total; + this.totals.item_discount = item_discount_total; + + sub_total -= item_discount_total; // Apply discount to total if (discount_in_totals) { diff --git a/resources/lang/en-GB/bills.php b/resources/lang/en-GB/bills.php index 834694d52..5914cf59b 100644 --- a/resources/lang/en-GB/bills.php +++ b/resources/lang/en-GB/bills.php @@ -13,6 +13,7 @@ return [ 'price' => 'Price', 'sub_total' => 'Subtotal', 'discount' => 'Discount', + 'item_discount' => 'Item Discount', 'tax_total' => 'Tax Total', 'total' => 'Total', diff --git a/resources/lang/en-GB/invoices.php b/resources/lang/en-GB/invoices.php index 10e56bca3..e06ce9a68 100644 --- a/resources/lang/en-GB/invoices.php +++ b/resources/lang/en-GB/invoices.php @@ -13,6 +13,7 @@ return [ 'price' => 'Price', 'sub_total' => 'Subtotal', 'discount' => 'Discount', + 'item_discount' => 'Item Discount', 'tax_total' => 'Tax Total', 'total' => 'Total', diff --git a/resources/views/purchases/bills/create.blade.php b/resources/views/purchases/bills/create.blade.php index 86bcd85d3..f344556cb 100644 --- a/resources/views/purchases/bills/create.blade.php +++ b/resources/views/purchases/bills/create.blade.php @@ -90,6 +90,19 @@ @stack('sub_total_td_end') + @stack('item_discount_td_start') +