File: //home/slfopp7cb1df/www/inventorypacket.com/resources/src/views/app/pages/sales/edit_sale.vue
<template>
<div class="main-content">
<breadcumb :page="$t('EditSale')" :folder="$t('ListSales')"/>
<div v-if="isLoading" class="loading_page spinner spinner-primary mr-3"></div>
<validation-observer ref="edit_sale" v-if="!isLoading">
<b-form @submit.prevent="Submit_Sale">
<b-row>
<b-col lg="12" md="12" sm="12">
<b-card>
<b-row>
<b-modal hide-footer id="open_scan" size="md" title="Barcode Scanner">
<qrcode-scanner
:qrbox="250"
:fps="10"
style="width: 100%; height: calc(100vh - 56px);"
@result="onScan"
/>
</b-modal>
<!-- date -->
<b-col lg="4" md="4" sm="12" class="mb-3">
<validation-provider
name="date"
:rules="{ required: true}"
v-slot="validationContext"
>
<b-form-group :label="$t('date') + ' ' + '*'">
<b-form-input
:state="getValidationState(validationContext)"
aria-describedby="date-feedback"
type="date"
v-model="sale.date"
></b-form-input>
<b-form-invalid-feedback
id="OrderTax-feedback"
>{{ validationContext.errors[0] }}</b-form-invalid-feedback>
</b-form-group>
</validation-provider>
</b-col>
<!-- Customer -->
<b-col lg="4" md="4" sm="12" class="mb-3">
<validation-provider name="Customer" :rules="{ required: true}">
<b-form-group slot-scope="{ valid, errors }" :label="$t('Customer') + ' ' + '*'">
<v-select
:class="{'is-invalid': !!errors.length}"
:state="errors[0] ? false : (valid ? true : null)"
v-model="sale.client_id"
:reduce="label => label.value"
:placeholder="$t('Choose_Customer')"
:options="clients.map(clients => ({label: clients.name, value: clients.id}))"
/>
<b-form-invalid-feedback>{{ errors[0] }}</b-form-invalid-feedback>
</b-form-group>
</validation-provider>
</b-col>
<!-- warehouse -->
<b-col lg="4" md="4" sm="12" class="mb-3">
<validation-provider name="warehouse" :rules="{ required: true}">
<b-form-group slot-scope="{ valid, errors }" :label="$t('warehouse') + ' ' + '*'">
<v-select
:class="{'is-invalid': !!errors.length}"
:state="errors[0] ? false : (valid ? true : null)"
:disabled="details.length > 0"
@input="Selected_Warehouse"
v-model="sale.warehouse_id"
:reduce="label => label.value"
:placeholder="$t('Choose_Warehouse')"
:options="warehouses.map(warehouses => ({label: warehouses.name, value: warehouses.id}))"
/>
<b-form-invalid-feedback>{{ errors[0] }}</b-form-invalid-feedback>
</b-form-group>
</validation-provider>
</b-col>
<!-- Product -->
<b-col md="12" class="mb-5">
<h6>{{$t('ProductName')}}</h6>
<div id="autocomplete" class="autocomplete">
<div class="input-with-icon">
<img src="/assets_setup/scan.png" alt="Scan" class="scan-icon" @click="showModal">
<input
:placeholder="$t('Scan_Search_Product_by_Code_Name')"
@input='e => search_input = e.target.value'
@keyup="search(search_input)"
@focus="handleFocus"
@blur="handleBlur"
ref="product_autocomplete"
class="autocomplete-input" />
</div>
<ul class="autocomplete-result-list" v-show="focused">
<li class="autocomplete-result" v-for="product_fil in product_filter" @mousedown="SearchProduct(product_fil)">{{getResultValue(product_fil)}}</li>
</ul>
</div>
</b-col>
<!-- Order products -->
<b-col md="12">
<h5>{{$t('order_products')}} *</h5>
<div class="table-responsive">
<table class="table table-hover">
<thead class="bg-gray-300">
<tr>
<th scope="col">#</th>
<th scope="col">{{$t('ProductName')}}</th>
<th scope="col">{{$t('Net_Unit_Price')}}</th>
<th scope="col">{{$t('CurrentStock')}}</th>
<th scope="col">{{$t('Qty')}}</th>
<th scope="col">{{$t('Discount')}}</th>
<th scope="col">{{$t('Tax')}}</th>
<th scope="col">{{$t('SubTotal')}}</th>
<th scope="col" class="text-center">
<i class="fa fa-trash"></i>
</th>
</tr>
</thead>
<tbody>
<tr v-if="details.length <=0">
<td colspan="9">{{$t('NodataAvailable')}}</td>
</tr>
<tr
v-for="detail in details"
:class="{'row_deleted': detail.del === 1 || (detail.no_unit === 0 && detail.product_type != 'is_service')}"
:key="detail.detail_id"
>
<td>{{detail.detail_id}}</td>
<td>
<span>{{detail.code}}</span>
<br>
<span class="badge badge-success">{{detail.name}}</span>
</td>
<td>{{currentUser.currency}} {{formatNumber(detail.Net_price, 3)}}</td>
<td>
<span class="badge badge-warning" v-if="detail.product_type == 'is_service'">----</span>
<span class="badge badge-warning" v-else>{{detail.stock}} {{detail.unitSale}}</span>
</td>
<td>
<div class="quantity">
<b-input-group>
<b-input-group-prepend>
<span v-show="detail.no_unit !== 0 || detail.product_type == 'is_service'"
class="btn btn-primary btn-sm"
@click="decrement(detail ,detail.detail_id)"
>-</span>
</b-input-group-prepend>
<input
class="form-control"
@keyup="Verified_Qty(detail,detail.detail_id)"
:min="0.00"
:max="detail.stock"
v-model.number="detail.quantity"
:disabled="detail.del === 1 || (detail.no_unit === 0 && detail.product_type != 'is_service')"
>
<b-input-group-append>
<span v-show="detail.no_unit !== 0 || detail.product_type == 'is_service'"
class="btn btn-primary btn-sm"
@click="increment(detail ,detail.detail_id)"
>+</span>
</b-input-group-append>
</b-input-group>
</div>
</td>
<td>{{currentUser.currency}} {{formatNumber(detail.DiscountNet * detail.quantity, 2)}}</td>
<td>{{currentUser.currency}} {{formatNumber(detail.taxe * detail.quantity , 2)}}</td>
<td>{{currentUser.currency}} {{detail.subtotal.toFixed(2)}}</td>
<td v-show="detail.no_unit !== 0 || detail.product_type == 'is_service'">
<i v-if="currentUserPermissions && currentUserPermissions.includes('edit_product_sale')"
@click="Modal_Updat_Detail(detail)" class="i-Edit text-25 text-success cursor-pointer"></i>
<i @click="delete_Product_Detail(detail.detail_id)" class="i-Close-Window text-25 text-danger cursor-pointer"></i>
</td>
</tr>
</tbody>
</table>
</div>
</b-col>
<div class="offset-md-9 col-md-3 mt-4">
<table class="table table-striped table-sm">
<tbody>
<tr>
<td class="bold">{{$t('OrderTax')}}</td>
<td>
<span>{{currentUser.currency}} {{sale.TaxNet.toFixed(2)}} ({{formatNumber(sale.tax_rate ,2)}} %)</span>
</td>
</tr>
<tr>
<td class="bold">{{$t('Discount')}}</td>
<td>{{currentUser.currency}} {{sale.discount.toFixed(2)}}</td>
</tr>
<tr>
<td class="bold">{{$t('Shipping')}}</td>
<td>{{currentUser.currency}} {{sale.shipping.toFixed(2)}}</td>
</tr>
<tr>
<td>
<span class="font-weight-bold">{{$t('Total')}}</span>
</td>
<td>
<span
class="font-weight-bold"
>{{currentUser.currency}} {{GrandTotal.toFixed(2)}}</span>
</td>
</tr>
</tbody>
</table>
</div>
<!-- Order Tax -->
<b-col lg="4" md="4" sm="12" class="mb-3" v-if="currentUserPermissions && currentUserPermissions.includes('edit_tax_discount_shipping_sale')">
<validation-provider
name="Order Tax"
:rules="{ regex: /^\d*\.?\d*$/}"
v-slot="validationContext"
>
<b-form-group :label="$t('OrderTax')">
<b-input-group append="%">
<b-form-input
:state="getValidationState(validationContext)"
aria-describedby="OrderTax-feedback"
label="Order Tax"
v-model.number="sale.tax_rate"
@keyup="keyup_OrderTax()"
></b-form-input>
</b-input-group>
<b-form-invalid-feedback
id="OrderTax-feedback"
>{{ validationContext.errors[0] }}</b-form-invalid-feedback>
</b-form-group>
</validation-provider>
</b-col>
<!-- Discount -->
<b-col lg="4" md="4" sm="12" class="mb-3" v-if="currentUserPermissions && currentUserPermissions.includes('edit_tax_discount_shipping_sale')">
<validation-provider
name="Discount"
:rules="{ regex: /^\d*\.?\d*$/}"
v-slot="validationContext"
>
<b-form-group :label="$t('Discount')">
<b-input-group :append="currentUser.currency">
<b-form-input
:state="getValidationState(validationContext)"
aria-describedby="Discount-feedback"
label="Discount"
v-model.number="sale.discount"
@keyup="keyup_Discount()"
></b-form-input>
</b-input-group>
<b-form-invalid-feedback
id="Discount-feedback"
>{{ validationContext.errors[0] }}</b-form-invalid-feedback>
</b-form-group>
</validation-provider>
</b-col>
<!-- Shipping -->
<b-col lg="4" md="4" sm="12" class="mb-3" v-if="currentUserPermissions && currentUserPermissions.includes('edit_tax_discount_shipping_sale')">
<validation-provider
name="Shipping"
:rules="{ regex: /^\d*\.?\d*$/}"
v-slot="validationContext"
>
<b-form-group :label="$t('Shipping')">
<b-input-group :append="currentUser.currency">
<b-form-input
:state="getValidationState(validationContext)"
aria-describedby="Shipping-feedback"
label="Shipping"
v-model.number="sale.shipping"
@keyup="keyup_Shipping()"
></b-form-input>
</b-input-group>
<b-form-invalid-feedback
id="Shipping-feedback"
>{{ validationContext.errors[0] }}</b-form-invalid-feedback>
</b-form-group>
</validation-provider>
</b-col>
<!-- Status -->
<b-col lg="4" md="4" sm="12" class="mb-3">
<validation-provider name="Status" :rules="{ required: true}">
<b-form-group slot-scope="{ valid, errors }" :label="$t('Status') + ' ' + '*'">
<v-select
:class="{'is-invalid': !!errors.length}"
:state="errors[0] ? false : (valid ? true : null)"
v-model="sale.statut"
:reduce="label => label.value"
:placeholder="$t('Choose_Status')"
:options="
[
{label: 'completed', value: 'completed'},
{label: 'Pending', value: 'pending'},
{label: 'ordered', value: 'ordered'}
]"
></v-select>
<b-form-invalid-feedback>{{ errors[0] }}</b-form-invalid-feedback>
</b-form-group>
</validation-provider>
</b-col>
<b-col md="12">
<b-form-group :label="$t('Note')">
<textarea
v-model="sale.notes"
rows="4"
class="form-control"
:placeholder="$t('Afewwords')"
></textarea>
</b-form-group>
</b-col>
<b-col md="12">
<b-form-group>
<b-button variant="primary" @click="Submit_Sale" :disabled="SubmitProcessing"><i class="i-Yes me-2 font-weight-bold"></i> {{$t('submit')}}</b-button>
<div v-once class="typo__p" v-if="SubmitProcessing">
<div class="spinner sm spinner-primary mt-3"></div>
</div>
</b-form-group>
</b-col>
</b-row>
</b-card>
</b-col>
</b-row>
</b-form>
</validation-observer>
<!-- Modal Update Detail Product -->
<validation-observer ref="Update_Detail">
<b-modal hide-footer size="lg" id="form_Update_Detail" :title="detail.name">
<b-form @submit.prevent="submit_Update_Detail">
<b-row>
<!-- Unit Price -->
<b-col lg="6" md="6" sm="12">
<validation-provider
name="Product Price"
:rules="{ required: true , regex: /^\d*\.?\d*$/}"
v-slot="validationContext"
>
<b-form-group :label="$t('ProductPrice') + ' ' + '*'" id="Price-input">
<b-form-input
label="Product Price"
v-model.number="detail.Unit_price"
:state="getValidationState(validationContext)"
aria-describedby="Price-feedback"
></b-form-input>
<b-form-invalid-feedback id="Price-feedback">{{ validationContext.errors[0] }}</b-form-invalid-feedback>
</b-form-group>
</validation-provider>
</b-col>
<!-- Tax Method -->
<b-col lg="6" md="6" sm="12">
<validation-provider name="Tax Method" :rules="{ required: true}">
<b-form-group slot-scope="{ valid, errors }" :label="$t('TaxMethod') + ' ' + '*'">
<v-select
:class="{'is-invalid': !!errors.length}"
:state="errors[0] ? false : (valid ? true : null)"
v-model="detail.tax_method"
:reduce="label => label.value"
:placeholder="$t('Choose_Method')"
:options="
[
{label: 'Exclusive', value: '1'},
{label: 'Inclusive', value: '2'}
]"
></v-select>
<b-form-invalid-feedback>{{ errors[0] }}</b-form-invalid-feedback>
</b-form-group>
</validation-provider>
</b-col>
<!-- Tax Rate -->
<b-col lg="6" md="6" sm="12">
<validation-provider
name="Order Tax"
:rules="{ required: true , regex: /^\d*\.?\d*$/}"
v-slot="validationContext"
>
<b-form-group :label="$t('OrderTax') + ' ' + '*'">
<b-input-group append="%">
<b-form-input
label="Order Tax"
v-model.number="detail.tax_percent"
:state="getValidationState(validationContext)"
aria-describedby="OrderTax-feedback"
></b-form-input>
</b-input-group>
<b-form-invalid-feedback id="OrderTax-feedback">{{ validationContext.errors[0] }}</b-form-invalid-feedback>
</b-form-group>
</validation-provider>
</b-col>
<!-- Discount Method -->
<b-col lg="6" md="6" sm="12">
<validation-provider name="Discount Method" :rules="{ required: true}">
<b-form-group slot-scope="{ valid, errors }" :label="$t('Discount_Method') + ' ' + '*'">
<v-select
v-model="detail.discount_Method"
:reduce="label => label.value"
:placeholder="$t('Choose_Method')"
:class="{'is-invalid': !!errors.length}"
:state="errors[0] ? false : (valid ? true : null)"
:options="
[
{label: 'Percent %', value: '1'},
{label: 'Fixed', value: '2'}
]"
></v-select>
<b-form-invalid-feedback>{{ errors[0] }}</b-form-invalid-feedback>
</b-form-group>
</validation-provider>
</b-col>
<!-- Discount Rate -->
<b-col lg="6" md="6" sm="12">
<validation-provider
name="Discount Rate"
:rules="{ required: true , regex: /^\d*\.?\d*$/}"
v-slot="validationContext"
>
<b-form-group :label="$t('Discount') + ' ' + '*'">
<b-form-input
label="Discount"
v-model.number="detail.discount"
:state="getValidationState(validationContext)"
aria-describedby="Discount-feedback"
></b-form-input>
<b-form-invalid-feedback id="Discount-feedback">{{ validationContext.errors[0] }}</b-form-invalid-feedback>
</b-form-group>
</validation-provider>
</b-col>
<!-- Imei or serial numbers -->
<b-col lg="12" md="12" sm="12" v-show="detail.is_imei">
<b-form-group :label="$t('Add_product_IMEI_Serial_number')">
<b-form-input
label="Add_product_IMEI_Serial_number"
v-model="detail.imei_number"
:placeholder="$t('Add_product_IMEI_Serial_number')"
></b-form-input>
</b-form-group>
</b-col>
<b-col md="12">
<b-form-group>
<b-button
variant="primary"
type="submit"
:disabled="Submit_Processing_detail"
><i class="i-Yes me-2 font-weight-bold"></i> {{$t('submit')}}</b-button>
<div v-once class="typo__p" v-if="Submit_Processing_detail">
<div class="spinner sm spinner-primary mt-3"></div>
</div>
</b-form-group>
</b-col>
</b-row>
</b-form>
</b-modal>
</validation-observer>
</div>
</template>
<script>
import { mapActions, mapGetters } from "vuex";
import NProgress from "nprogress";
export default {
metaInfo: {
title: "Edit Sale"
},
data() {
return {
focused: false,
timer:null,
search_input:'',
product_filter:[],
isLoading: true,
SubmitProcessing:false,
Submit_Processing_detail:false,
warehouses: [],
clients: [],
products: [],
details: [],
detail: {},
sales: [],
sale: {
id: "",
date: "",
statut: "",
notes: "",
client_id: "",
warehouse_id: "",
tax_rate: 0,
TaxNet: 0,
shipping: 0,
discount: 0
},
total: 0,
GrandTotal: 0,
product: {
id: "",
code: "",
stock: "",
quantity: 1,
discount: "",
DiscountNet: "",
discount_Method: "",
sale_unit_id: "",
no_unit:"",
name: "",
unitSale: "",
Net_price: "",
Total_price: "",
Unit_price: "",
subtotal: "",
product_id: "",
detail_id: "",
taxe: "",
tax_percent: "",
tax_method: "",
product_variant_id: "",
del: "",
etat: "",
is_imei: "",
imei_number:"",
}
};
},
computed: {
...mapGetters(["currentUserPermissions","currentUser"])
},
methods: {
showModal() {
this.$bvModal.show('open_scan');
},
onScan (decodedText, decodedResult) {
const code = decodedText;
this.search_input = code;
this.search();
this.$bvModal.hide('open_scan');
},
handleFocus() {
this.focused = true
},
handleBlur() {
this.focused = false
},
//--- Submit Validate Update Sale
Submit_Sale() {
this.$refs.edit_sale.validate().then(success => {
if (!success) {
this.makeToast(
"danger",
this.$t("Please_fill_the_form_correctly"),
this.$t("Failed")
);
} else {
this.Update_Sale();
}
});
},
//---Submit Validation Update Detail
submit_Update_Detail() {
this.$refs.Update_Detail.validate().then(success => {
if (!success) {
return;
} else {
this.Update_Detail();
}
});
},
//---Validate State Fields
getValidationState({ dirty, validated, valid = null }) {
return dirty || validated ? valid : null;
},
//------ Toast
makeToast(variant, msg, title) {
this.$root.$bvToast.toast(msg, {
title: title,
variant: variant,
solid: true
});
},
//---------------------------- Show Modal Update Detail Product
Modal_Updat_Detail(detail) {
NProgress.start();
NProgress.set(0.1);
this.detail = {};
this.detail.name = detail.name;
this.detail.detail_id = detail.detail_id;
this.detail.Unit_price = detail.Unit_price;
this.detail.tax_method = detail.tax_method;
this.detail.discount_Method = detail.discount_Method;
this.detail.discount = detail.discount;
this.detail.quantity = detail.quantity;
this.detail.tax_percent = detail.tax_percent;
this.detail.is_imei = detail.is_imei;
this.detail.imei_number = detail.imei_number;
setTimeout(() => {
NProgress.done();
this.$bvModal.show("form_Update_Detail");
}, 1000);
},
//---------------------------- Submit Update Detail Product
Update_Detail() {
NProgress.start();
NProgress.set(0.1);
this.Submit_Processing_detail = true;
for (var i = 0; i < this.details.length; i++) {
if (this.details[i].detail_id === this.detail.detail_id) {
this.details[i].tax_percent = this.detail.tax_percent;
this.details[i].Unit_price = this.detail.Unit_price;
this.details[i].quantity = this.detail.quantity;
this.details[i].tax_method = this.detail.tax_method;
this.details[i].discount_Method = this.detail.discount_Method;
this.details[i].discount = this.detail.discount;
this.details[i].imei_number = this.detail.imei_number;
if (this.details[i].discount_Method == "2") {
//Fixed
this.details[i].DiscountNet = this.detail.discount;
} else {
//Percentage %
this.details[i].DiscountNet = parseFloat(
(this.detail.Unit_price * this.details[i].discount) / 100
);
}
if (this.details[i].tax_method == "1") {
//Exclusive
this.details[i].Net_price = parseFloat(
this.detail.Unit_price - this.details[i].DiscountNet
);
this.details[i].taxe = parseFloat(
(this.detail.tax_percent *
(this.detail.Unit_price - this.details[i].DiscountNet)) /
100
);
} else {
//Inclusive
this.details[i].taxe = parseFloat(
(this.detail.Unit_price - this.details[i].DiscountNet) *
(this.detail.tax_percent / 100)
);
this.details[i].Net_price = parseFloat(
this.detail.Unit_price -
this.details[i].taxe -
this.details[i].DiscountNet
);
}
this.$forceUpdate();
}
}
this.Calcul_Total();
setTimeout(() => {
NProgress.done();
this.Submit_Processing_detail = false;
this.$bvModal.hide("form_Update_Detail");
}, 1000);
},
// Search Products
search(){
if (this.timer) {
clearTimeout(this.timer);
this.timer = null;
}
if (this.search_input.length < 2) {
return this.product_filter= [];
}
if (this.sale.warehouse_id != "" && this.sale.warehouse_id != null) {
this.timer = setTimeout(() => {
const product_filter = this.products.filter(product => product.code === this.search_input || product.barcode.includes(this.search_input));
if(product_filter.length === 1){
this.SearchProduct(product_filter[0])
}else{
this.product_filter= this.products.filter(product => {
return (
product.name.toLowerCase().includes(this.search_input.toLowerCase()) ||
product.code.toLowerCase().includes(this.search_input.toLowerCase()) ||
product.barcode.toLowerCase().includes(this.search_input.toLowerCase())
);
});
// Check if product_filter is empty and show alert
if (this.product_filter.length <= 0) {
this.makeToast(
"warning",
"Product Not Found",
"Warning"
);
}
}
}, 800);
} else {
this.makeToast(
"warning",
this.$t("SelectWarehouse"),
this.$t("Warning")
);
}
},
//-------------- get Result Value Search Product
getResultValue(result) {
return result.code + " " + "(" + result.name + ")";
},
//-------------- Submit Search Product
SearchProduct(result) {
this.product = {};
if (
this.details.length > 0 &&
this.details.some(detail => detail.code === result.code)
) {
this.makeToast("warning", this.$t("AlreadyAdd"), this.$t("Warning"));
} else {
if( result.product_type =='is_service'){
this.product.quantity = 1;
this.product.code = result.code;
}else{
this.product.code = result.code;
this.product.no_unit = 1;
this.product.stock = result.qte_sale;
if (result.qte_sale < 1) {
this.product.quantity = result.qte_sale;
} else {
this.product.quantity = 1;
}
}
this.product.product_variant_id = result.product_variant_id;
this.Get_Product_Details(result.id, result.product_variant_id);
}
this.search_input= '';
this.$refs.product_autocomplete.value = "";
this.product_filter = [];
},
//---------------------- Event Select Warehouse ------------------------------\\
Selected_Warehouse(value) {
this.search_input= '';
this.product_filter = [];
this.Get_Products_By_Warehouse(value);
},
//------------------------------------ Get Products By Warehouse -------------------------\\
Get_Products_By_Warehouse(id) {
// Start the progress bar.
NProgress.start();
NProgress.set(0.1);
axios
.get("get_Products_by_warehouse/" + id + "?stock=" + 1 + "&is_sale=" + 1 + "&product_service=" + 1 + "&product_combo=" + 1)
.then(response => {
this.products = response.data;
NProgress.done();
})
.catch(error => {
});
},
//----------------------------------------- Add Product to order list -------------------------\\
add_product() {
if (this.details.length > 0) {
this.Last_Detail_id();
} else if (this.details.length === 0) {
this.product.detail_id = 1;
}
this.details.push(this.product);
if(this.product.is_imei){
this.Modal_Updat_Detail(this.product);
}
},
//-----------------------------------Verified QTY ------------------------------\\
Verified_Qty(detail, id) {
for (var i = 0; i < this.details.length; i++) {
if (this.details[i].detail_id === id) {
if (isNaN(detail.quantity)) {
this.details[i].quantity = detail.qte_copy;
}
if (detail.etat == "new" && detail.quantity > detail.stock) {
this.makeToast("warning", this.$t("LowStock"), this.$t("Warning"));
this.details[i].quantity = detail.stock;
} else if (
detail.etat == "current" &&
detail.quantity > detail.stock + detail.qte_copy
) {
this.makeToast("warning", this.$t("LowStock"), this.$t("Warning"));
this.details[i].quantity = detail.qte_copy;
} else {
this.details[i].quantity = detail.quantity;
}
}
}
this.$forceUpdate();
this.Calcul_Total();
},
//-----------------------------------increment QTY ------------------------------\\
increment(detail, id) {
for (var i = 0; i < this.details.length; i++) {
if (this.details[i].detail_id == id) {
if (detail.etat == "new" && detail.quantity + 1 > detail.stock) {
this.makeToast("warning", this.$t("LowStock"), this.$t("Warning"));
} else if (
detail.etat == "current" &&
detail.quantity + 1 > detail.stock + detail.qte_copy
) {
this.makeToast("warning", this.$t("LowStock"), this.$t("Warning"));
} else {
this.formatNumber(this.details[i].quantity++, 2);
}
}
}
this.$forceUpdate();
this.Calcul_Total();
},
//-----------------------------------decrement QTY ------------------------------\\
decrement(detail, id) {
for (var i = 0; i < this.details.length; i++) {
if (this.details[i].detail_id == id) {
if (detail.quantity - 1 > 0) {
if (detail.etat == "new" && detail.quantity - 1 > detail.stock) {
this.makeToast(
"warning",
this.$t("LowStock"),
this.$t("Warning")
);
} else if (
detail.etat == "current" &&
detail.quantity - 1 > detail.stock + detail.qte_copy
) {
this.makeToast(
"warning",
this.$t("LowStock"),
this.$t("Warning")
);
} else {
this.formatNumber(this.details[i].quantity--, 2);
}
}
}
}
this.$forceUpdate();
this.Calcul_Total();
},
//---------- keyup OrderTax
keyup_OrderTax() {
if (isNaN(this.sale.tax_rate)) {
this.sale.tax_rate = 0;
} else if(this.sale.tax_rate == ''){
this.sale.tax_rate = 0;
this.Calcul_Total();
}else {
this.Calcul_Total();
}
},
//---------- keyup Discount
keyup_Discount() {
if (isNaN(this.sale.discount)) {
this.sale.discount = 0;
} else if(this.sale.discount == ''){
this.sale.discount = 0;
this.Calcul_Total();
}else {
this.Calcul_Total();
}
},
//---------- keyup Shipping
keyup_Shipping() {
if (isNaN(this.sale.shipping)) {
this.sale.shipping = 0;
} else if(this.sale.shipping == ''){
this.sale.shipping = 0;
this.Calcul_Total();
}else {
this.Calcul_Total();
}
},
//------------------------------Formetted Numbers -------------------------\\
formatNumber(number, dec) {
const value = (typeof number === "string"
? number
: number.toString()
).split(".");
if (dec <= 0) return value[0];
let formated = value[1] || "";
if (formated.length > dec)
return `${value[0]}.${formated.substr(0, dec)}`;
while (formated.length < dec) formated += "0";
return `${value[0]}.${formated}`;
},
//-----------------------------------------Calcul Total ------------------------------\\
Calcul_Total() {
this.total = 0;
for (var i = 0; i < this.details.length; i++) {
var tax = this.details[i].taxe * this.details[i].quantity;
this.details[i].subtotal = parseFloat(
this.details[i].quantity * this.details[i].Net_price + tax
);
this.total = parseFloat(this.total + this.details[i].subtotal);
}
const total_without_discount = parseFloat(
this.total - this.sale.discount
);
this.sale.TaxNet = parseFloat(
(total_without_discount * this.sale.tax_rate) / 100
);
this.GrandTotal = parseFloat(
total_without_discount + this.sale.TaxNet + this.sale.shipping
);
var grand_total = this.GrandTotal.toFixed(2);
this.GrandTotal = parseFloat(grand_total);
},
//-----------------------------------Delete Detail Product ------------------------------\\
delete_Product_Detail(id) {
for (var i = 0; i < this.details.length; i++) {
if (id === this.details[i].detail_id) {
this.details.splice(i, 1);
this.Calcul_Total();
}
}
},
//-----------------------------------verified Order List ------------------------------\\
verifiedForm() {
if (this.details.length <= 0) {
this.makeToast(
"warning",
this.$t("AddProductToList"),
this.$t("Warning")
);
return false;
} else {
var count = 0;
for (var i = 0; i < this.details.length; i++) {
if (
this.details[i].quantity == "" ||
this.details[i].quantity === 0
) {
count += 1;
}
}
if (count > 0) {
this.makeToast("warning", this.$t("AddQuantity"), this.$t("Warning"));
return false;
} else {
return true;
}
}
},
//--------------------------------- Update Sale -------------------------\\
Update_Sale() {
if (this.verifiedForm()) {
this.SubmitProcessing = true;
// Start the progress bar.
NProgress.start();
NProgress.set(0.1);
let id = this.$route.params.id;
axios
.put(`sales/${id}`, {
date: this.sale.date,
client_id: this.sale.client_id,
GrandTotal: this.GrandTotal,
warehouse_id: this.sale.warehouse_id,
statut: this.sale.statut,
notes: this.sale.notes,
tax_rate: this.sale.tax_rate?this.sale.tax_rate:0,
TaxNet: this.sale.TaxNet?this.sale.TaxNet:0,
discount: this.sale.discount?this.sale.discount:0,
shipping: this.sale.shipping?this.sale.shipping:0,
details: this.details
})
.then(response => {
this.makeToast(
"success",
this.$t("Update.TitleSale"),
this.$t("Success")
);
NProgress.done();
this.SubmitProcessing = false;
this.$router.push({ name: "index_sales" });
})
.catch(error => {
NProgress.done();
this.makeToast("danger", this.$t("InvalidData"), this.$t("Failed"));
this.SubmitProcessing = false;
});
}
},
//-------------------------------- Get Last Detail Id -------------------------\\
Last_Detail_id() {
this.product.detail_id = 0;
var len = this.details.length;
this.product.detail_id = this.details[len - 1].detail_id + 1;
},
//---------------------------------Get Product Details ------------------------\\
Get_Product_Details(product_id, variant_id) {
axios.get("/show_product_data/" + product_id +"/"+ variant_id).then(response => {
this.product.del = 0;
this.product.id = 0;
this.product.etat = "new";
this.product.discount = 0;
this.product.DiscountNet = 0;
this.product.discount_Method = "2";
this.product.product_id = response.data.id;
this.product.name = response.data.name;
this.product.product_type = response.data.product_type;
this.product.Net_price = response.data.Net_price;
this.product.Unit_price = response.data.Unit_price;
this.product.taxe = response.data.tax_price;
this.product.tax_method = response.data.tax_method;
this.product.tax_percent = response.data.tax_percent;
this.product.unitSale = response.data.unitSale;
this.product.sale_unit_id = response.data.sale_unit_id;
this.product.is_imei = response.data.is_imei;
this.product.imei_number = '';
this.add_product();
this.Calcul_Total();
});
},
//--------------------------------------- Get Elements ------------------------------\\
GetElements() {
let id = this.$route.params.id;
axios
.get(`sales/${id}/edit`)
.then(response => {
this.sale = response.data.sale;
this.details = response.data.details;
this.clients = response.data.clients;
this.warehouses = response.data.warehouses;
this.Get_Products_By_Warehouse(this.sale.warehouse_id);
this.Calcul_Total();
this.isLoading = false;
})
.catch(response => {
setTimeout(() => {
this.isLoading = false;
}, 500);
});
}
},
//----------------------------- Created function-------------------
created() {
this.GetElements();
}
};
</script>
<style>
.input-with-icon {
display: flex;
align-items: center;
}
.scan-icon {
width: 50px; /* Adjust size as needed */
height: 50px;
margin-right: 8px; /* Adjust spacing as needed */
cursor: pointer;
}
</style>