diff --git a/app/Http/Requests/EstimatesRequest.php b/app/Http/Requests/EstimatesRequest.php index f43b7e419..119a3c333 100644 --- a/app/Http/Requests/EstimatesRequest.php +++ b/app/Http/Requests/EstimatesRequest.php @@ -45,15 +45,21 @@ public function rules() 'nullable' ], 'discount' => [ + 'numeric', 'required', ], 'discount_val' => [ + 'integer', 'required', ], 'sub_total' => [ + 'integer', 'required', ], 'total' => [ + 'integer', + 'numeric', + 'max:99999999', 'required', ], 'tax' => [ @@ -77,9 +83,11 @@ public function rules() 'required', ], 'items.*.quantity' => [ + 'integer', 'required', ], 'items.*.price' => [ + 'integer', 'required', ], ]; diff --git a/app/Http/Requests/InvoicesRequest.php b/app/Http/Requests/InvoicesRequest.php index 84b417396..5bb702b0b 100644 --- a/app/Http/Requests/InvoicesRequest.php +++ b/app/Http/Requests/InvoicesRequest.php @@ -45,15 +45,21 @@ public function rules() 'nullable' ], 'discount' => [ + 'numeric', 'required', ], 'discount_val' => [ + 'integer', 'required', ], 'sub_total' => [ + 'integer', 'required', ], 'total' => [ + 'integer', + 'numeric', + 'max:99999999', 'required', ], 'tax' => [ @@ -77,9 +83,11 @@ public function rules() 'required', ], 'items.*.quantity' => [ + 'integer', 'required', ], 'items.*.price' => [ + 'integer', 'required', ], ]; diff --git a/app/Http/Requests/RecurringInvoiceRequest.php b/app/Http/Requests/RecurringInvoiceRequest.php index f624156e4..81e6355ab 100644 --- a/app/Http/Requests/RecurringInvoiceRequest.php +++ b/app/Http/Requests/RecurringInvoiceRequest.php @@ -43,15 +43,21 @@ public function rules() 'nullable' ], 'discount' => [ + 'numeric', 'required', ], 'discount_val' => [ + 'integer', 'required', ], 'sub_total' => [ + 'integer', 'required', ], 'total' => [ + 'integer', + 'numeric', + 'max:99999999', 'required', ], 'tax' => [ diff --git a/resources/scripts/admin/components/estimate-invoice-common/CreateItemRow.vue b/resources/scripts/admin/components/estimate-invoice-common/CreateItemRow.vue index 8af4293f4..705df7f45 100644 --- a/resources/scripts/admin/components/estimate-invoice-common/CreateItemRow.vue +++ b/resources/scripts/admin/components/estimate-invoice-common/CreateItemRow.vue @@ -271,23 +271,19 @@ const price = computed({ } else { updateItemAttribute('price', newValue) } + setDiscount() }, }) -const subtotal = computed(() => props.itemData.price * props.itemData.quantity) +const subtotal = computed(() => Math.round(props.itemData.price * props.itemData.quantity)) const discount = computed({ get: () => { return props.itemData.discount }, set: (newValue) => { - if (props.itemData.discount_type === 'percentage') { - updateItemAttribute('discount_val', (subtotal.value * newValue) / 100) - } else { - updateItemAttribute('discount_val', Math.round(newValue * 100)) - } - updateItemAttribute('discount', newValue) + setDiscount() }, }) @@ -313,7 +309,7 @@ const showRemoveButton = computed(() => { const totalSimpleTax = computed(() => { return Math.round( sumBy(props.itemData.taxes, function (tax) { - if (!tax.compound_tax) { + if (tax.amount) { return tax.amount } return 0 @@ -321,18 +317,7 @@ const totalSimpleTax = computed(() => { ) }) -const totalCompoundTax = computed(() => { - return Math.round( - sumBy(props.itemData.taxes, function (tax) { - if (tax.compound_tax) { - return tax.amount - } - return 0 - }) - ) -}) - -const totalTax = computed(() => totalSimpleTax.value + totalCompoundTax.value) +const totalTax = computed(() => totalSimpleTax.value) const rules = { name: { @@ -399,7 +384,7 @@ const v$ = useVuelidate( function updateTax(data) { props.store.$patch((state) => { - state[props.storeProp].items[props.index]['taxes'][data.index] = data.item + state[props.storeProp].items[props.index]['taxes'][data.index] = data.item }) let lastTax = props.itemData.taxes[props.itemData.taxes.length - 1] @@ -416,6 +401,16 @@ function updateTax(data) { syncItemToStore() } +function setDiscount() { + const newValue = props.store[props.storeProp].items[props.index].discount + + if (props.itemData.discount_type === 'percentage'){ + updateItemAttribute('discount_val', Math.round((subtotal.value * newValue) / 100)) + }else{ + updateItemAttribute('discount_val', Math.round(newValue * 100)) + } +} + function searchVal(val) { updateItemAttribute('name', val) } @@ -485,10 +480,12 @@ function syncItemToStore() { total: total.value, sub_total: subtotal.value, totalSimpleTax: totalSimpleTax.value, - totalCompoundTax: totalCompoundTax.value, totalTax: totalTax.value, tax: totalTax.value, taxes: [...itemTaxes], + tax_type_ids: itemTaxes.flatMap(_t => + _t.tax_type_id ? _t.tax_type_id : [], + ), } props.store.updateItem(data) diff --git a/resources/scripts/admin/components/estimate-invoice-common/CreateItemRowTax.vue b/resources/scripts/admin/components/estimate-invoice-common/CreateItemRowTax.vue index cf3b12946..eecd3e5fe 100644 --- a/resources/scripts/admin/components/estimate-invoice-common/CreateItemRowTax.vue +++ b/resources/scripts/admin/components/estimate-invoice-common/CreateItemRowTax.vue @@ -146,14 +146,14 @@ const filteredTypes = computed(() => { }) const taxAmount = computed(() => { - if (localTax.compound_tax && props.discountedTotal) { - return ((props.discountedTotal + props.totalTax) * localTax.percent) / 100 - } - if (props.discountedTotal && localTax.percent) { + const taxPerItemEnabled = props.store[props.storeProp].tax_per_item === 'YES' + const discountPerItemEnabled = props.store[props.storeProp].discount_per_item === 'YES' + if (taxPerItemEnabled && !discountPerItemEnabled){ + return getTaxAmount() + } return (props.discountedTotal * localTax.percent) / 100 } - return 0 }) @@ -171,6 +171,13 @@ watch( } ) +watch( + () => taxAmount.value, + () => { + updateRowTax() + }, +) + // Set SelectedTax if (props.taxData.tax_type_id > 0) { selectedTax.value = taxTypeStore.taxTypes.find( @@ -183,7 +190,6 @@ updateRowTax() function onSelectTax(val) { localTax.percent = val.percent localTax.tax_type_id = val.id - localTax.compound_tax = val.compound_tax localTax.name = val.name updateRowTax() @@ -220,6 +226,27 @@ function openTaxModal() { function removeTax(index) { props.store.$patch((state) => { state[props.storeProp].items[props.itemIndex].taxes.splice(index, 1) + state[props.storeProp].items[props.itemIndex].tax = 0 + state[props.storeProp].items[props.itemIndex].totalTax = 0 }) } + +function getTaxAmount() { + let total = 0 + let discount = 0 + const itemTotal = props.discountedTotal + const modelDiscount = props.store[props.storeProp].discount ? props.store[props.storeProp].discount : 0 + const type = props.store[props.storeProp].discount_type + if (modelDiscount > 0) { + props.store[props.storeProp].items.forEach((_i) => { + total += _i.total + }) + const proportion = (itemTotal / total).toFixed(2) + discount = type === 'fixed' ? modelDiscount * 100 : (total * modelDiscount) / 100 + const itemDiscount = Math.round(discount * proportion) + const discounted = itemTotal - itemDiscount + return Math.round((discounted * localTax.percent) / 100) + } + return Math.round((props.discountedTotal * localTax.percent) / 100) +} diff --git a/resources/scripts/admin/components/estimate-invoice-common/CreateTotal.vue b/resources/scripts/admin/components/estimate-invoice-common/CreateTotal.vue index a14c429ad..2a2935e9b 100644 --- a/resources/scripts/admin/components/estimate-invoice-common/CreateTotal.vue +++ b/resources/scripts/admin/components/estimate-invoice-common/CreateTotal.vue @@ -191,7 +191,7 @@