bug fix in sell invoices
This commit is contained in:
parent
69c27c0109
commit
b9c3201b9f
|
@ -95,6 +95,7 @@ class PersonsController extends AbstractController
|
||||||
$response['bs'] = $bs;
|
$response['bs'] = $bs;
|
||||||
$response['bd'] = $bd;
|
$response['bd'] = $bd;
|
||||||
$response['balance'] = $bs - $bd;
|
$response['balance'] = $bs - $bd;
|
||||||
|
|
||||||
return $this->json($response);
|
return $this->json($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -499,6 +500,7 @@ class PersonsController extends AbstractController
|
||||||
): JsonResponse {
|
): JsonResponse {
|
||||||
$acc = $access->hasRole('person');
|
$acc = $access->hasRole('person');
|
||||||
if (!$acc) {
|
if (!$acc) {
|
||||||
|
var_dump($acc);
|
||||||
throw $this->createAccessDeniedException();
|
throw $this->createAccessDeniedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -130,50 +130,50 @@ class PrintersController extends AbstractController
|
||||||
$params = json_decode($content, true);
|
$params = json_decode($content, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$settings->setSellBidInfo($params['sell']['bidInfo']);
|
$settings->setSellBidInfo($params['sell']['bidInfo'] ?? false);
|
||||||
$settings->setSellTaxInfo($params['sell']['taxInfo']);
|
$settings->setSellTaxInfo($params['sell']['taxInfo'] ?? false);
|
||||||
$settings->setSellDiscountInfo($params['sell']['discountInfo']);
|
$settings->setSellDiscountInfo($params['sell']['discountInfo'] ?? false);
|
||||||
$settings->setSellNote($params['sell']['note']);
|
$settings->setSellNote($params['sell']['note'] ?? false);
|
||||||
$settings->setSellNoteString($params['sell']['noteString']);
|
$settings->setSellNoteString($params['sell']['noteString']);
|
||||||
$settings->setSellPays($params['sell']['pays']);
|
$settings->setSellPays($params['sell']['pays'] ?? false);
|
||||||
$settings->setSellPaper($params['sell']['paper']);
|
$settings->setSellPaper($params['sell']['paper']);
|
||||||
$settings->setSellBusinessStamp($params['sell']['businessStamp']);
|
$settings->setSellBusinessStamp($params['sell']['businessStamp'] ?? false);
|
||||||
$settings->setSellInvoiceIndex($params['sell']['invoiceIndex']);
|
$settings->setSellInvoiceIndex($params['sell']['invoiceIndex'] ?? false);
|
||||||
if ($params['buy']['bidInfo'] == null) {
|
if ($params['buy']['bidInfo'] == null) {
|
||||||
$settings->setBuyBidInfo(false);
|
$settings->setBuyBidInfo(false);
|
||||||
} else {
|
} else {
|
||||||
$settings->setBuyBidInfo(true);
|
$settings->setBuyBidInfo(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$settings->setBuyTaxInfo($params['buy']['taxInfo']);
|
$settings->setBuyTaxInfo($params['buy']['taxInfo'] ?? false);
|
||||||
$settings->setBuyDiscountInfo($params['buy']['discountInfo']);
|
$settings->setBuyDiscountInfo($params['buy']['discountInfo'] ?? false);
|
||||||
$settings->setBuyNote($params['buy']['note']);
|
$settings->setBuyNote($params['buy']['note'] ?? false);
|
||||||
$settings->setBuyNoteString($params['buy']['noteString']);
|
$settings->setBuyNoteString($params['buy']['noteString']);
|
||||||
$settings->setBuyPays($params['buy']['pays']);
|
$settings->setBuyPays($params['buy']['pays'] ?? false);
|
||||||
$settings->setBuyPaper($params['buy']['paper']);
|
$settings->setBuyPaper($params['buy']['paper']);
|
||||||
|
|
||||||
$settings->setRfbuyBidInfo($params['rfbuy']['bidInfo']);
|
$settings->setRfbuyBidInfo($params['rfbuy']['bidInfo'] ?? false);
|
||||||
$settings->setRfbuyTaxInfo($params['rfbuy']['taxInfo']);
|
$settings->setRfbuyTaxInfo($params['rfbuy']['taxInfo'] ?? false);
|
||||||
$settings->setRfbuyDiscountInfo($params['rfbuy']['discountInfo']);
|
$settings->setRfbuyDiscountInfo($params['rfbuy']['discountInfo'] ?? false);
|
||||||
$settings->setRfbuyNote($params['rfbuy']['note']);
|
$settings->setRfbuyNote($params['rfbuy']['note'] ?? false);
|
||||||
$settings->setRfbuyNoteString($params['rfbuy']['noteString']);
|
$settings->setRfbuyNoteString($params['rfbuy']['noteString']);
|
||||||
$settings->setRfbuyPays($params['rfbuy']['pays']);
|
$settings->setRfbuyPays($params['rfbuy']['pays'] ?? false);
|
||||||
$settings->setRfbuyPaper($params['rfbuy']['paper']);
|
$settings->setRfbuyPaper($params['rfbuy']['paper']);
|
||||||
|
|
||||||
$settings->setRfsellBidInfo($params['rfsell']['bidInfo']);
|
$settings->setRfsellBidInfo($params['rfsell']['bidInfo'] ?? false);
|
||||||
$settings->setRfsellTaxInfo($params['rfsell']['taxInfo']);
|
$settings->setRfsellTaxInfo($params['rfsell']['taxInfo'] ?? false);
|
||||||
$settings->setRfsellDiscountInfo($params['rfsell']['discountInfo']);
|
$settings->setRfsellDiscountInfo($params['rfsell']['discountInfo'] ?? false);
|
||||||
$settings->setRfsellNote($params['rfsell']['note']);
|
$settings->setRfsellNote($params['rfsell']['note'] ?? false);
|
||||||
$settings->setRfsellNoteString($params['rfsell']['noteString']);
|
$settings->setRfsellNoteString($params['rfsell']['noteString']);
|
||||||
$settings->setRfsellPays($params['rfsell']['pays']);
|
$settings->setRfsellPays($params['rfsell']['pays'] ?? false);
|
||||||
$settings->setRfSellPaper($params['rfsell']['paper']);
|
$settings->setRfSellPaper($params['rfsell']['paper']);
|
||||||
|
|
||||||
$settings->setRepserviceNoteString($params['repservice']['noteString']);
|
$settings->setRepserviceNoteString($params['repservice']['noteString']);
|
||||||
$settings->setRepServicePaper($params['repservice']['paper']);
|
$settings->setRepServicePaper($params['repservice']['paper']);
|
||||||
|
|
||||||
$settings->setFastsellCashdeskTicket($params['fastsell']['cashdeskTicket']);
|
$settings->setFastsellCashdeskTicket($params['fastsell']['cashdeskTicket'] ?? false);
|
||||||
$settings->setFastsellInvoice($params['fastsell']['invoice']);
|
$settings->setFastsellInvoice($params['fastsell']['invoice'] ?? false);
|
||||||
$settings->setFastsellPdf($params['fastsell']['pdf']);
|
$settings->setFastsellPdf($params['fastsell']['pdf'] ?? false);
|
||||||
|
|
||||||
$settings->setLeftFooter($params['global']['leftFooter']);
|
$settings->setLeftFooter($params['global']['leftFooter']);
|
||||||
$settings->setRightFooter($params['global']['rightFooter']);
|
$settings->setRightFooter($params['global']['rightFooter']);
|
||||||
|
|
|
@ -926,18 +926,20 @@ class SellController extends AbstractController
|
||||||
$sumTax = 0;
|
$sumTax = 0;
|
||||||
$sumTotal = 0;
|
$sumTotal = 0;
|
||||||
foreach ($params['items'] as $item) {
|
foreach ($params['items'] as $item) {
|
||||||
$sumTax += $item['tax'] ?? 0;
|
$itemTotal = $item['total'] ?? 0;
|
||||||
$sumTotal += $item['total'] ?? 0;
|
$itemTax = $item['tax'] ?? 0;
|
||||||
|
$sumTotal += $itemTotal;
|
||||||
|
$sumTax += $itemTax;
|
||||||
|
|
||||||
$hesabdariRow = new HesabdariRow();
|
$hesabdariRow = new HesabdariRow();
|
||||||
$hesabdariRow->setDes($item['description'] ?? '');
|
$hesabdariRow->setDes($item['description'] ?? '');
|
||||||
$hesabdariRow->setBid($acc['bid']);
|
$hesabdariRow->setBid($acc['bid']);
|
||||||
$hesabdariRow->setYear($acc['year']);
|
$hesabdariRow->setYear($acc['year']);
|
||||||
$hesabdariRow->setDoc($doc);
|
$hesabdariRow->setDoc($doc);
|
||||||
$hesabdariRow->setBs($item['total'] + ($item['tax'] ?? 0));
|
$hesabdariRow->setBs($itemTotal); // فقط مبلغ کالا بدون مالیات
|
||||||
$hesabdariRow->setBd(0);
|
$hesabdariRow->setBd(0);
|
||||||
$hesabdariRow->setDiscount($item['discountAmount'] ?? 0);
|
$hesabdariRow->setDiscount($item['discountAmount'] ?? 0);
|
||||||
$hesabdariRow->setTax($item['tax'] ?? 0);
|
$hesabdariRow->setTax($itemTax);
|
||||||
$hesabdariRow->setDiscountType($item['showPercentDiscount'] ? 'percent' : 'fixed');
|
$hesabdariRow->setDiscountType($item['showPercentDiscount'] ? 'percent' : 'fixed');
|
||||||
$hesabdariRow->setDiscountPercent($item['discountPercent'] ?? 0);
|
$hesabdariRow->setDiscountPercent($item['discountPercent'] ?? 0);
|
||||||
|
|
||||||
|
@ -1221,13 +1223,21 @@ class SellController extends AbstractController
|
||||||
$itemDiscountPercent = $row->getDiscountPercent() ?? 0;
|
$itemDiscountPercent = $row->getDiscountPercent() ?? 0;
|
||||||
$itemTax = $row->getTax() ?? 0;
|
$itemTax = $row->getTax() ?? 0;
|
||||||
|
|
||||||
// محاسبه تخفیف سطری
|
// محاسبه قیمت واحد و تخفیف
|
||||||
if ($itemDiscountType === 'percent') {
|
if ($itemDiscountType === 'percent' && $itemDiscountPercent > 0) {
|
||||||
$itemDiscount = round(($basePrice * $itemDiscountPercent) / 100);
|
// محاسبه قیمت اصلی در حالت تخفیف درصدی
|
||||||
|
$originalPrice = $basePrice / (1 - ($itemDiscountPercent / 100));
|
||||||
|
$itemDiscount = round(($originalPrice * $itemDiscountPercent) / 100);
|
||||||
|
} else {
|
||||||
|
// محاسبه قیمت اصلی در حالت تخفیف مقداری
|
||||||
|
$originalPrice = $basePrice + $itemDiscount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// محاسبه قیمت واحد
|
||||||
|
$unitPrice = $row->getCommdityCount() > 0 ? $originalPrice / $row->getCommdityCount() : 0;
|
||||||
|
|
||||||
// محاسبه قیمت خالص (بدون مالیات)
|
// محاسبه قیمت خالص (بدون مالیات)
|
||||||
$netPrice = $basePrice - $itemDiscount;
|
$netPrice = $basePrice;
|
||||||
$totalInvoice += $netPrice;
|
$totalInvoice += $netPrice;
|
||||||
|
|
||||||
$items[] = [
|
$items[] = [
|
||||||
|
@ -1237,7 +1247,7 @@ class SellController extends AbstractController
|
||||||
'code' => $row->getCommodity()->getCode()
|
'code' => $row->getCommodity()->getCode()
|
||||||
],
|
],
|
||||||
'count' => $row->getCommdityCount(),
|
'count' => $row->getCommdityCount(),
|
||||||
'price' => $row->getCommdityCount() > 0 ? $netPrice / $row->getCommdityCount() : 0,
|
'price' => $unitPrice,
|
||||||
'discountPercent' => $itemDiscountPercent,
|
'discountPercent' => $itemDiscountPercent,
|
||||||
'discountAmount' => $itemDiscount,
|
'discountAmount' => $itemDiscount,
|
||||||
'total' => $netPrice,
|
'total' => $netPrice,
|
||||||
|
@ -1256,6 +1266,14 @@ class SellController extends AbstractController
|
||||||
$totalDiscount = $discountAll;
|
$totalDiscount = $discountAll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// محاسبه مبلغ نهایی با در نظر گرفتن تخفیف کلی و مالیات
|
||||||
|
$finalTotal = $totalInvoice - $totalDiscount + $transferCost;
|
||||||
|
$totalTax = 0;
|
||||||
|
foreach ($items as $item) {
|
||||||
|
$totalTax += $item['tax'];
|
||||||
|
}
|
||||||
|
$finalTotal += $totalTax;
|
||||||
|
|
||||||
return $this->json([
|
return $this->json([
|
||||||
'result' => 1,
|
'result' => 1,
|
||||||
'data' => [
|
'data' => [
|
||||||
|
@ -1275,7 +1293,7 @@ class SellController extends AbstractController
|
||||||
'shippingCost' => $transferCost,
|
'shippingCost' => $transferCost,
|
||||||
'showTotalPercentDiscount' => $discountType === 'percent',
|
'showTotalPercentDiscount' => $discountType === 'percent',
|
||||||
'items' => $items,
|
'items' => $items,
|
||||||
'finalTotal' => $doc->getAmount(),
|
'finalTotal' => $finalTotal,
|
||||||
'payments' => $payments
|
'payments' => $payments
|
||||||
]
|
]
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -69,6 +69,13 @@ class Access
|
||||||
'bid'=>$bid
|
'bid'=>$bid
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
$year = $this->em->getRepository(Year::class)->findOneBy([
|
||||||
|
'head' => true,
|
||||||
|
'bid'=>$bid
|
||||||
|
]);
|
||||||
|
if (!$year) { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->request->headers->get('activeMoney')) {
|
if ($this->request->headers->get('activeMoney')) {
|
||||||
$money = $this->em->getRepository(Money::class)->findOneBy([
|
$money = $this->em->getRepository(Money::class)->findOneBy([
|
||||||
|
@ -78,6 +85,7 @@ class Access
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
$money = $bid->getMoney();
|
$money = $bid->getMoney();
|
||||||
|
if (!$money) { return false; }
|
||||||
}
|
}
|
||||||
|
|
||||||
$accessArray = [
|
$accessArray = [
|
||||||
|
|
|
@ -3,11 +3,11 @@
|
||||||
v-model="inputValue"
|
v-model="inputValue"
|
||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
:class="$attrs.class"
|
:class="$attrs.class"
|
||||||
type="number"
|
type="text"
|
||||||
:rules="combinedRules"
|
:rules="combinedRules"
|
||||||
:error-messages="errorMessages"
|
:error-messages="errorMessages"
|
||||||
@keydown="restrictToNumbers"
|
|
||||||
@input="handleInput"
|
@input="handleInput"
|
||||||
|
@keydown="restrictInput"
|
||||||
dir="ltr"
|
dir="ltr"
|
||||||
dense
|
dense
|
||||||
:hide-details="$attrs['hide-details'] || 'auto'"
|
:hide-details="$attrs['hide-details'] || 'auto'"
|
||||||
|
@ -19,6 +19,8 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { debounce } from 'lodash'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'HNumberInput',
|
name: 'HNumberInput',
|
||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
|
@ -34,18 +36,29 @@ export default {
|
||||||
},
|
},
|
||||||
allowDecimal: {
|
allowDecimal: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: true
|
||||||
},
|
},
|
||||||
allowNegative: {
|
allowNegative: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
|
},
|
||||||
|
maxDecimals: {
|
||||||
|
type: Number,
|
||||||
|
default: 2
|
||||||
|
},
|
||||||
|
useThousandSeparator: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
inputValue: '',
|
inputValue: '',
|
||||||
errorMessages: []
|
errorMessages: [],
|
||||||
|
integerPart: '',
|
||||||
|
decimalPart: '',
|
||||||
|
isProcessing: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -53,15 +66,16 @@ export default {
|
||||||
combinedRules() {
|
combinedRules() {
|
||||||
return [
|
return [
|
||||||
v => {
|
v => {
|
||||||
if (!v && v !== '0') return true // اجازه خالی بودن
|
if (!v && v !== '0') return true
|
||||||
const pattern = this.allowDecimal
|
const cleaned = v.replace(/,/g, '')
|
||||||
|
const regex = this.allowDecimal
|
||||||
? this.allowNegative
|
? this.allowNegative
|
||||||
? /^-?\d*\.?\d*$/
|
? new RegExp(`^-?\\d*\\.?\\d{0,${this.maxDecimals}}$`)
|
||||||
: /^\d*\.?\d*$/
|
: new RegExp(`^\\d*\\.?\\d{0,${this.maxDecimals}}$`)
|
||||||
: this.allowNegative
|
: this.allowNegative
|
||||||
? /^-?\d+$/
|
? /^-?\d+$/
|
||||||
: /^\d+$/
|
: /^\d+$/
|
||||||
return pattern.test(v) || this.$t('numberinput.invalid_number')
|
return regex.test(cleaned) || 'فقط عدد با ممیز اعشاری (.) مجاز است'
|
||||||
},
|
},
|
||||||
...this.rules
|
...this.rules
|
||||||
]
|
]
|
||||||
|
@ -74,97 +88,198 @@ export default {
|
||||||
handler(newVal) {
|
handler(newVal) {
|
||||||
if (newVal === null || newVal === undefined) {
|
if (newVal === null || newVal === undefined) {
|
||||||
this.inputValue = ''
|
this.inputValue = ''
|
||||||
|
this.integerPart = ''
|
||||||
|
this.decimalPart = ''
|
||||||
} else {
|
} else {
|
||||||
const cleaned = String(newVal).replace(this.allowDecimal ? /[^0-9.-]/g : /[^0-9-]/g, '')
|
const num = Number(newVal)
|
||||||
this.inputValue = cleaned
|
if (!isNaN(num)) {
|
||||||
|
this.setPartsFromNumber(num)
|
||||||
|
this.inputValue = this.formatNumber()
|
||||||
|
} else {
|
||||||
|
this.setPartsFromString(String(newVal))
|
||||||
|
this.inputValue = this.formatNumber()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
inputValue(newVal) {
|
inputValue: {
|
||||||
if (newVal === '' || newVal === null || newVal === undefined) {
|
immediate: true,
|
||||||
|
handler: debounce(function (newVal) {
|
||||||
|
if (this.isProcessing) return
|
||||||
|
this.isProcessing = true
|
||||||
|
|
||||||
|
if (!newVal) {
|
||||||
|
this.integerPart = ''
|
||||||
|
this.decimalPart = ''
|
||||||
this.$emit('update:modelValue', null)
|
this.$emit('update:modelValue', null)
|
||||||
this.errorMessages = []
|
this.errorMessages = []
|
||||||
|
this.isProcessing = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const cleaned = String(newVal).replace(this.allowDecimal ? /[^0-9.-]/g : /[^0-9-]/g, '')
|
const cleaned = newVal.replace(/,/g, '').trim()
|
||||||
const pattern = this.allowDecimal
|
|
||||||
|
const regex = this.allowDecimal
|
||||||
? this.allowNegative
|
? this.allowNegative
|
||||||
? /^-?\d*\.?\d*$/
|
? new RegExp(`^-?\\d*\\.?\\d{0,${this.maxDecimals}}$`)
|
||||||
: /^\d*\.?\d*$/
|
: new RegExp(`^\\d*\\.?\\d{0,${this.maxDecimals}}$`)
|
||||||
: this.allowNegative
|
: this.allowNegative
|
||||||
? /^-?\d+$/
|
? /^-?\d+$/
|
||||||
: /^\d+$/
|
: /^\d+$/
|
||||||
|
|
||||||
if (pattern.test(cleaned)) {
|
if (regex.test(cleaned)) {
|
||||||
let numericValue
|
this.setPartsFromString(cleaned)
|
||||||
if (this.allowDecimal) {
|
const formatted = this.formatNumber()
|
||||||
numericValue = cleaned === '' || cleaned === '-' ? null : parseFloat(cleaned)
|
if (this.inputValue !== formatted) {
|
||||||
} else {
|
this.inputValue = formatted
|
||||||
numericValue = cleaned === '' || cleaned === '-' ? null : parseInt(cleaned, 10)
|
|
||||||
}
|
}
|
||||||
this.$emit('update:modelValue', isNaN(numericValue) ? null : numericValue)
|
const numericValue = this.getNumericValue()
|
||||||
|
this.$emit('update:modelValue', numericValue)
|
||||||
this.errorMessages = []
|
this.errorMessages = []
|
||||||
} else {
|
} else {
|
||||||
this.errorMessages = [this.$t('numberinput.invalid_number')]
|
this.errorMessages = ['فقط عدد با ممیز اعشاری (.) مجاز است']
|
||||||
|
this.inputValue = this.formatNumber()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.isProcessing = false
|
||||||
|
}, 150)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
restrictToNumbers(event) {
|
convertPersianToEnglish(str) {
|
||||||
|
const persianNumbers = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹']
|
||||||
|
const englishNumbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
|
||||||
|
|
||||||
|
let result = str || ''
|
||||||
|
persianNumbers.forEach((num, index) => {
|
||||||
|
result = result.replace(new RegExp(num, 'g'), englishNumbers[index])
|
||||||
|
})
|
||||||
|
|
||||||
|
return result
|
||||||
|
},
|
||||||
|
|
||||||
|
setPartsFromNumber(num) {
|
||||||
|
const isNegative = num < 0
|
||||||
|
const absValue = Math.abs(num)
|
||||||
|
const strValue = this.allowDecimal
|
||||||
|
? absValue.toString()
|
||||||
|
: Math.floor(absValue).toString()
|
||||||
|
const parts = strValue.split('.')
|
||||||
|
this.integerPart = isNegative ? `-${parts[0]}` : parts[0]
|
||||||
|
this.decimalPart = parts[1] || ''
|
||||||
|
},
|
||||||
|
|
||||||
|
setPartsFromString(str) {
|
||||||
|
const cleaned = this.convertPersianToEnglish(str).replace(/,/g, '')
|
||||||
|
const isNegative = cleaned.startsWith('-')
|
||||||
|
const absValue = cleaned.replace(/^-/, '')
|
||||||
|
const parts = absValue.split('.')
|
||||||
|
this.integerPart = parts[0] || ''
|
||||||
|
this.integerPart = isNegative && this.integerPart ? `-${this.integerPart}` : this.integerPart
|
||||||
|
this.decimalPart = this.allowDecimal && parts[1] ? parts[1].slice(0, this.maxDecimals) : ''
|
||||||
|
},
|
||||||
|
|
||||||
|
formatNumber() {
|
||||||
|
if (!this.integerPart && !this.decimalPart) return ''
|
||||||
|
|
||||||
|
let integer = this.integerPart.replace(/^-/, '')
|
||||||
|
if (this.useThousandSeparator) {
|
||||||
|
integer = integer.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
|
||||||
|
}
|
||||||
|
const isNegative = this.integerPart.startsWith('-')
|
||||||
|
let result = isNegative ? `-${integer}` : integer
|
||||||
|
|
||||||
|
if (this.allowDecimal && this.decimalPart) {
|
||||||
|
result += '.' + this.decimalPart
|
||||||
|
} else if (this.allowDecimal && this.inputValue.endsWith('.')) {
|
||||||
|
result += '.'
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
},
|
||||||
|
|
||||||
|
getNumericValue() {
|
||||||
|
const cleaned = `${this.integerPart}.${this.decimalPart || '0'}`
|
||||||
|
const num = this.allowDecimal ? parseFloat(cleaned) : parseInt(cleaned, 10)
|
||||||
|
return isNaN(num) ? null : num
|
||||||
|
},
|
||||||
|
|
||||||
|
restrictInput(event) {
|
||||||
const key = event.key
|
const key = event.key
|
||||||
const input = this.inputValue || ''
|
const input = this.inputValue || ''
|
||||||
|
|
||||||
// اجازه دادن به کلیدهای کنترلی
|
if (['Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'Tab', 'Enter'].includes(key) ||
|
||||||
if (
|
(event.ctrlKey || event.metaKey)) {
|
||||||
['Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'Tab', 'Enter'].includes(key) ||
|
|
||||||
(event.ctrlKey || event.metaKey)
|
|
||||||
) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.allowDecimal) {
|
if (this.allowDecimal) {
|
||||||
// اجازه ورود اعداد، ممیز، کاما (برای کیبوردهای محلی) و (در صورت اجازه) منفی
|
if (!/[0-9.]/.test(key)) {
|
||||||
if (!/[0-9.,]/.test(key) && (!this.allowNegative || key !== '-')) {
|
|
||||||
event.preventDefault()
|
|
||||||
}
|
|
||||||
// جلوگیری از بیش از یک ممیز
|
|
||||||
if ((key === '.' || key === ',') && input.includes('.')) {
|
|
||||||
event.preventDefault()
|
|
||||||
}
|
|
||||||
// جلوگیری از ممیز در ابتدا یا بعد از منفی
|
|
||||||
if ((key === '.' || key === ',') && (input === '' || input === '-')) {
|
|
||||||
event.preventDefault()
|
|
||||||
}
|
|
||||||
// جلوگیری از بیش از یک منفی
|
|
||||||
if (key === '-' && (input.includes('-') || !this.allowNegative)) {
|
|
||||||
event.preventDefault()
|
|
||||||
}
|
|
||||||
// منفی فقط در ابتدا
|
|
||||||
if (key === '-' && input !== '') {
|
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// فقط اعداد و (در صورت اجازه) منفی
|
if (!/[0-9-]/.test(key)) {
|
||||||
if (!/[0-9]/.test(key) && (!this.allowNegative || key !== '-')) {
|
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
// جلوگیری از بیش از یک منفی
|
|
||||||
if (key === '-' && (input.includes('-') || !this.allowNegative)) {
|
|
||||||
event.preventDefault()
|
|
||||||
}
|
}
|
||||||
// منفی فقط در ابتدا
|
|
||||||
if (key === '-' && input !== '') {
|
if (key === '.') {
|
||||||
|
if (!this.allowDecimal) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (input.includes('.') || this.decimalPart) {
|
||||||
|
event.preventDefault()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.integerPart) {
|
||||||
|
event.preventDefault()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key === '-') {
|
||||||
|
if (!this.allowNegative || input.includes('-')) {
|
||||||
|
event.preventDefault()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.allowDecimal && this.decimalPart && /[0-9]/.test(key)) {
|
||||||
|
if (this.decimalPart.length >= this.maxDecimals) {
|
||||||
|
event.preventDefault()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
handleInput(event) {
|
handleInput(event) {
|
||||||
// تبدیل کاما به ممیز برای کیبوردهای محلی
|
let value = event.target.value || ''
|
||||||
if (this.allowDecimal && event.target.value.includes(',')) {
|
|
||||||
this.inputValue = event.target.value.replace(',', '.')
|
value = this.convertPersianToEnglish(value)
|
||||||
|
value = value.replace(/,/g, '')
|
||||||
|
|
||||||
|
const regex = this.allowDecimal ? /[^0-9.-]/g : /[^0-9-]/g
|
||||||
|
value = value.replace(regex, '')
|
||||||
|
|
||||||
|
// حذف نقاط اضافی
|
||||||
|
const parts = value.split('.')
|
||||||
|
if (parts.length > 2) {
|
||||||
|
value = parts[0] + '.' + parts.slice(1).join('')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// اگر نقطه در انتهای عدد باشد، اجازه میدهیم باقی بماند
|
||||||
|
if (value.endsWith('.')) {
|
||||||
|
this.setPartsFromString(value.slice(0, -1))
|
||||||
|
this.inputValue = this.formatNumber() + '.'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setPartsFromString(value)
|
||||||
|
this.inputValue = this.formatNumber()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,6 +293,6 @@ export default {
|
||||||
|
|
||||||
:deep(.v-text-field .v-input__prepend-inner) {
|
:deep(.v-text-field .v-input__prepend-inner) {
|
||||||
padding-right: 0;
|
padding-right: 0;
|
||||||
margin-right: 0;
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
|
@ -67,11 +67,11 @@
|
||||||
<Hcommoditysearch v-model="item.name" density="compact" hide-details class="my-0" style="font-size: 0.8rem;" return-object @update:modelValue="handleCommodityChange(item)"></Hcommoditysearch>
|
<Hcommoditysearch v-model="item.name" density="compact" hide-details class="my-0" style="font-size: 0.8rem;" return-object @update:modelValue="handleCommodityChange(item)"></Hcommoditysearch>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-center px-2">
|
<td class="text-center px-2">
|
||||||
<Hnumberinput v-model="item.count" density="compact" @update:modelValue="recalculateTotals" class="my-0" style="font-size: 0.8rem;" :allow-decimal="true"></Hnumberinput>
|
<Hnumberinput v-model="item.count" density="compact" @update:modelValue="recalculateTotals" class="my-0" style="font-size: 0.8rem;" :max-decimals="2" :allow-decimal="true"></Hnumberinput>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-center px-2">
|
<td class="text-center px-2">
|
||||||
<div class="d-flex align-center justify-center">
|
<div class="d-flex align-center justify-center">
|
||||||
<Hnumberinput v-model="item.price" density="compact" @update:modelValue="recalculateTotals" class="my-0" style="font-size: 0.8rem;" :allow-decimal="true"></Hnumberinput>
|
<Hnumberinput v-model="item.price" density="compact" @update:modelValue="recalculateTotals" class="my-0" style="font-size: 0.8rem;" :allow-decimal="false"></Hnumberinput>
|
||||||
<v-tooltip v-if="item.name && item.price < item.name.priceBuy" text="قیمت فروش کمتر از قیمت خرید است" location="bottom">
|
<v-tooltip v-if="item.name && item.price < item.name.priceBuy" text="قیمت فروش کمتر از قیمت خرید است" location="bottom">
|
||||||
<template v-slot:activator="{ props }">
|
<template v-slot:activator="{ props }">
|
||||||
<v-icon v-bind="props" color="warning" size="small" class="mr-1">mdi-alert</v-icon>
|
<v-icon v-bind="props" color="warning" size="small" class="mr-1">mdi-alert</v-icon>
|
||||||
|
@ -906,24 +906,24 @@ export default {
|
||||||
this.totalInvoice = Number(data.totalInvoice);
|
this.totalInvoice = Number(data.totalInvoice);
|
||||||
this.finalTotal = Number(data.finalTotal);
|
this.finalTotal = Number(data.finalTotal);
|
||||||
|
|
||||||
// تبدیل قیمتها به قیمت خالص (بدون مالیات)
|
// تبدیل قیمتها به قیمت پایه (بدون مالیات)
|
||||||
this.items = data.items.map(item => {
|
this.items = data.items.map(item => {
|
||||||
const basePrice = Number(item.price);
|
const basePrice = Number(item.price);
|
||||||
const tax = Number(item.tax);
|
const tax = Number(item.tax);
|
||||||
const netPrice = Math.round(basePrice - tax);
|
const priceWithoutTax = Math.round(basePrice / (1 + (this.taxPercent / 100)));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: {
|
name: {
|
||||||
id: item.name.id,
|
id: item.name.id,
|
||||||
name: item.name.name,
|
name: item.name.name,
|
||||||
code: item.name.code,
|
code: item.name.code,
|
||||||
priceSell: netPrice // قیمت فروش بدون مالیات
|
priceSell: basePrice // قیمت فروش با مالیات
|
||||||
},
|
},
|
||||||
count: Number(item.count),
|
count: Number(item.count),
|
||||||
price: netPrice, // قیمت واحد بدون مالیات
|
price: basePrice, // قیمت واحد با مالیات
|
||||||
discountPercent: Number(item.discountPercent),
|
discountPercent: Number(item.discountPercent),
|
||||||
discountAmount: Number(item.discountAmount),
|
discountAmount: Number(item.discountAmount),
|
||||||
total: netPrice, // جمع ردیف بدون مالیات
|
total: Number(item.total),
|
||||||
description: item.description,
|
description: item.description,
|
||||||
showPercentDiscount: item.showPercentDiscount,
|
showPercentDiscount: item.showPercentDiscount,
|
||||||
tax: tax
|
tax: tax
|
||||||
|
|
|
@ -109,31 +109,46 @@ export default defineComponent({
|
||||||
this.totalRec = response.data.relatedDocs.reduce((sum: number, rdoc: any) => sum + parseInt(rdoc.amount), 0);
|
this.totalRec = response.data.relatedDocs.reduce((sum: number, rdoc: any) => sum + parseInt(rdoc.amount), 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
axios.get(`/api/sell/get/info/${this.$route.params.id}`).then((response) => {
|
axios.get(`/api/sell/v2/get/${this.$route.params.id}`).then((response) => {
|
||||||
this.person = response.data.person;
|
if (response.data.result === 1) {
|
||||||
this.discountAll = response.data.discountAll;
|
const data = response.data.data;
|
||||||
this.transferCost = response.data.transferCost;
|
this.person = {
|
||||||
this.item.doc.profit = response.data.profit;
|
id: data.person?.id,
|
||||||
this.commoditys = response.data.rows
|
nikename: data.person?.name,
|
||||||
.filter((item: any) => item.commodity != null)
|
mobile: '',
|
||||||
.map((item: any) => {
|
tel: '',
|
||||||
this.totalTax += parseInt(item.tax);
|
addres: '',
|
||||||
this.totalDiscount += parseInt(item.discount);
|
postalcode: ''
|
||||||
|
};
|
||||||
|
this.discountAll = data.totalDiscount;
|
||||||
|
this.transferCost = data.shippingCost;
|
||||||
|
this.item.doc.profit = 0; // این مقدار در API جدید موجود نیست
|
||||||
|
this.totalTax = 0;
|
||||||
|
this.totalDiscount = 0;
|
||||||
|
|
||||||
|
this.commoditys = data.items.map((item: any) => {
|
||||||
|
this.totalTax += item.tax;
|
||||||
|
this.totalDiscount += item.discountAmount;
|
||||||
return {
|
return {
|
||||||
commodity: item.commodity,
|
commodity: {
|
||||||
count: item.commodity_count,
|
id: item.name.id,
|
||||||
price: parseInt((parseInt(item.bs) - parseInt(item.tax) + parseInt(item.discount)) / parseFloat(item.commodity_count)),
|
name: item.name.name,
|
||||||
bs: item.bs,
|
unit: 'عدد'
|
||||||
bd: item.bd,
|
},
|
||||||
id: item.commodity.id,
|
count: item.count,
|
||||||
des: item.des,
|
price: item.price,
|
||||||
discount: item.discount,
|
bs: item.total,
|
||||||
|
bd: item.discountAmount,
|
||||||
|
id: item.name.id,
|
||||||
|
des: item.description,
|
||||||
|
discount: item.discountAmount,
|
||||||
tax: item.tax,
|
tax: item.tax,
|
||||||
sumWithoutTax: item.bs - item.tax,
|
sumWithoutTax: item.total - item.tax,
|
||||||
sumTotal: item.bs,
|
sumTotal: item.total,
|
||||||
table: 53,
|
table: 53,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
axios.post(`/api/business/get/info/${localStorage.getItem('activeBid')}`).then((response) => {
|
axios.post(`/api/business/get/info/${localStorage.getItem('activeBid')}`).then((response) => {
|
||||||
|
|
Loading…
Reference in a new issue