This commit is contained in:
@@ -37,28 +37,7 @@
|
||||
@input="fieldValueChanged('customerId')"
|
||||
></gz-pick-list>
|
||||
</v-col>
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'CustomerSignature') &&
|
||||
!(
|
||||
value.userIsSubContractorFull ||
|
||||
value.userIsSubContractorRestricted
|
||||
)
|
||||
"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<GzWoSignature
|
||||
v-model="value"
|
||||
:form-key="formCustomTemplateKey"
|
||||
:readonly="formState.readOnly || value.userIsTechRestricted"
|
||||
:pvm="pvm"
|
||||
variant="customer"
|
||||
data-cy="customerSignature"
|
||||
/>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'WorkOrderStatus') &&
|
||||
@@ -72,14 +51,14 @@
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<GzWoState
|
||||
<GzQuoteState
|
||||
v-model="value"
|
||||
:form-key="formCustomTemplateKey"
|
||||
:readonly="formState.readOnly"
|
||||
:pvm="pvm"
|
||||
data-cy="woState"
|
||||
:all-states="pvm.selectLists.wostatus"
|
||||
:allowed-states="pvm.selectLists.allowedwostatus"
|
||||
:all-states="pvm.selectLists.quotestatus"
|
||||
:allowed-states="pvm.selectLists.allowedquotestatus"
|
||||
/>
|
||||
</v-col>
|
||||
|
||||
@@ -101,29 +80,6 @@
|
||||
/>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'TechSignature') &&
|
||||
!(
|
||||
value.userIsSubContractorFull ||
|
||||
value.userIsSubContractorRestricted
|
||||
)
|
||||
"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<GzWoSignature
|
||||
v-model="value"
|
||||
:form-key="formCustomTemplateKey"
|
||||
:readonly="formState.readOnly || value.userIsTechRestricted"
|
||||
:pvm="pvm"
|
||||
variant="tech"
|
||||
data-cy="techSignature"
|
||||
/>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'WorkOrderSummary') &&
|
||||
@@ -450,14 +406,12 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* XXXeslint-disable */
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
import GzWoState from "./work-order-state.vue";
|
||||
import GzQuoteState from "./quote-state.vue";
|
||||
import GzWoAddress from "./work-order-address.vue";
|
||||
import GzWoSignature from "./work-order-signature.vue";
|
||||
export default {
|
||||
components: {
|
||||
GzWoState,
|
||||
GzWoAddress,
|
||||
GzWoSignature
|
||||
GzQuoteState,
|
||||
GzWoAddress
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -543,7 +497,7 @@ Example workorder
|
||||
wiki: null,
|
||||
customFields: null,
|
||||
tags: [],
|
||||
workOrderId: 10,
|
||||
quoteId: 10,
|
||||
techNotes: "technotes",
|
||||
workorderItemStatusId: null,
|
||||
workorderItemPriorityId: null,
|
||||
@@ -565,7 +519,7 @@ Example workorder
|
||||
stopDate: null,
|
||||
serviceRateId: null,
|
||||
isDirty: false,
|
||||
workOrderItemId: 21
|
||||
quoteItemId: 21
|
||||
},
|
||||
{
|
||||
id: 42,
|
||||
@@ -576,7 +530,7 @@ Example workorder
|
||||
stopDate: null,
|
||||
serviceRateId: null,
|
||||
isDirty: false,
|
||||
workOrderItemId: 21
|
||||
quoteItemId: 21
|
||||
}
|
||||
],
|
||||
tasks: [],
|
||||
@@ -591,7 +545,7 @@ Example workorder
|
||||
wiki: null,
|
||||
customFields: null,
|
||||
tags: [],
|
||||
workOrderId: 10,
|
||||
quoteId: 10,
|
||||
techNotes: "technotes",
|
||||
workorderItemStatusId: null,
|
||||
workorderItemPriorityId: null,
|
||||
@@ -613,7 +567,7 @@ Example workorder
|
||||
stopDate: null,
|
||||
serviceRateId: null,
|
||||
isDirty: false,
|
||||
workOrderItemId: 22
|
||||
quoteItemId: 22
|
||||
},
|
||||
{
|
||||
id: 44,
|
||||
@@ -624,7 +578,7 @@ Example workorder
|
||||
stopDate: null,
|
||||
serviceRateId: null,
|
||||
isDirty: false,
|
||||
workOrderItemId: 22
|
||||
quoteItemId: 22
|
||||
}
|
||||
],
|
||||
tasks: [],
|
||||
@@ -637,7 +591,7 @@ Example workorder
|
||||
{
|
||||
id: 37,
|
||||
concurrency: 7728489,
|
||||
workOrderId: 10,
|
||||
quoteId: 10,
|
||||
workOrderStatusId: 2,
|
||||
created: "2021-05-29T21:30:31.421011Z",
|
||||
userId: 37,
|
||||
@@ -647,7 +601,7 @@ Example workorder
|
||||
{
|
||||
id: 38,
|
||||
concurrency: 7728489,
|
||||
workOrderId: 10,
|
||||
quoteId: 10,
|
||||
workOrderStatusId: 3,
|
||||
created: "2021-05-29T22:25:31.421011Z",
|
||||
userId: 10,
|
||||
@@ -657,7 +611,7 @@ Example workorder
|
||||
{
|
||||
id: 39,
|
||||
concurrency: 7728489,
|
||||
workOrderId: 10,
|
||||
quoteId: 10,
|
||||
workOrderStatusId: 1,
|
||||
created: "2021-05-29T22:30:31.421011Z",
|
||||
userId: 31,
|
||||
@@ -667,7 +621,7 @@ Example workorder
|
||||
{
|
||||
id: 40,
|
||||
concurrency: 7728489,
|
||||
workOrderId: 10,
|
||||
quoteId: 10,
|
||||
workOrderStatusId: 3,
|
||||
created: "2021-05-29T23:25:31.421011Z",
|
||||
userId: 2,
|
||||
@@ -677,7 +631,7 @@ Example workorder
|
||||
{
|
||||
id: 41,
|
||||
concurrency: 7728489,
|
||||
workOrderId: 10,
|
||||
quoteId: 10,
|
||||
workOrderStatusId: 9,
|
||||
created: "2021-04-06T00:10:44.636Z",
|
||||
userId: 1,
|
||||
|
||||
798
ayanova/src/components/quote-item-expenses.vue
Normal file
798
ayanova/src/components/quote-item-expenses.vue
Normal file
@@ -0,0 +1,798 @@
|
||||
<template>
|
||||
<div v-if="value != null" class="mt-8">
|
||||
<v-row>
|
||||
<v-col cols="12">
|
||||
<v-menu offset-y max-width="600px">
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<div class="text-h6">
|
||||
<v-icon large :color="hasData ? 'primary' : null" class="mr-2"
|
||||
>$ayiMoneyBillWave</v-icon
|
||||
>
|
||||
{{ $ay.t("WorkOrderItemExpenseList") }}
|
||||
<v-btn v-if="!parentDeleted" large icon v-bind="attrs" v-on="on">
|
||||
<v-icon small color="primary">$ayiEllipsisV</v-icon>
|
||||
</v-btn>
|
||||
</div>
|
||||
</template>
|
||||
<v-list>
|
||||
<v-list-item v-if="canAdd" @click="newItem">
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiPlus</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{ $ay.t("New") }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item v-if="canDelete && isDeleted" @click="unDeleteItem">
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiTrashRestoreAlt</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{ $ay.t("Undelete") }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item v-if="canDelete && !isDeleted" @click="deleteItem">
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiTrashAlt</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{ $ay.t("SoftDelete") }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item v-if="canDeleteAll" @click="deleteAllItem">
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiDumpster</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{
|
||||
$ay.t("SoftDeleteAll")
|
||||
}}</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</v-col>
|
||||
|
||||
<template v-if="hasData">
|
||||
<!-- ############################################################### -->
|
||||
<v-col cols="12" class="mb-10">
|
||||
<v-data-table
|
||||
:headers="headerList"
|
||||
:items="itemList"
|
||||
item-key="index"
|
||||
v-model="selectedRow"
|
||||
class="elevation-1"
|
||||
disable-pagination
|
||||
disable-filtering
|
||||
disable-sort
|
||||
hide-default-footer
|
||||
data-cy="expensesTable"
|
||||
dense
|
||||
:item-class="itemRowClasses"
|
||||
@click:row="handleRowClick"
|
||||
:show-select="$vuetify.breakpoint.xs"
|
||||
single-select
|
||||
>
|
||||
<template v-slot:[`item.reimburseUser`]="{ item }">
|
||||
<v-simple-checkbox
|
||||
v-model="item.reimburseUser"
|
||||
disabled
|
||||
></v-simple-checkbox>
|
||||
</template>
|
||||
|
||||
<template v-slot:[`item.chargeToCustomer`]="{ item }">
|
||||
<v-simple-checkbox
|
||||
v-model="item.chargeToCustomer"
|
||||
disabled
|
||||
></v-simple-checkbox>
|
||||
</template>
|
||||
</v-data-table>
|
||||
</v-col>
|
||||
</template>
|
||||
<template v-if="hasData && hasSelection">
|
||||
<div ref="expensetopform"></div>
|
||||
<v-btn
|
||||
v-if="canDelete && isDeleted"
|
||||
large
|
||||
@click="unDeleteItem"
|
||||
color="primary"
|
||||
>{{ $ay.t("Undelete")
|
||||
}}<v-icon right large>$ayiTrashRestoreAlt</v-icon></v-btn
|
||||
>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemExpenseName')"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<v-text-field
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].expenses[activeItemIndex].name
|
||||
"
|
||||
:readonly="formState.readOnly"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemExpenseName')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].name`
|
||||
"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].name`
|
||||
)
|
||||
"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].name`
|
||||
)
|
||||
"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemExpenseTotalCost')"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-currency
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].expenses[activeItemIndex].totalCost
|
||||
"
|
||||
:readonly="formState.readOnly || isDeleted"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemExpenseTotalCost')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].totalCost`
|
||||
"
|
||||
data-cy="expenseTotalCost"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].totalCost`
|
||||
)
|
||||
"
|
||||
:rules="[
|
||||
form().decimalValid(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].totalCost`
|
||||
),
|
||||
form().required(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].totalCost`
|
||||
)
|
||||
]"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].totalCost`
|
||||
)
|
||||
"
|
||||
></gz-currency>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'WorkOrderItemExpenseChargeAmount') &&
|
||||
!value.userIsRestrictedType
|
||||
"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-currency
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].expenses[activeItemIndex]
|
||||
.chargeAmount
|
||||
"
|
||||
:readonly="formState.readOnly || isDeleted"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemExpenseChargeAmount')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].chargeAmount`
|
||||
"
|
||||
data-cy="expenseChargeAmount"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].chargeAmount`
|
||||
)
|
||||
"
|
||||
:rules="[
|
||||
form().decimalValid(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].chargeAmount`
|
||||
),
|
||||
form().required(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].chargeAmount`
|
||||
)
|
||||
]"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].chargeAmount`
|
||||
)
|
||||
"
|
||||
></gz-currency>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'WorkOrderItemExpenseChargeToCustomer') &&
|
||||
!value.userIsRestrictedType
|
||||
"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<v-checkbox
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].expenses[activeItemIndex]
|
||||
.chargeToCustomer
|
||||
"
|
||||
:readonly="formState.readOnly"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemExpenseChargeToCustomer')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].chargeToCustomer`
|
||||
"
|
||||
data-cy="chargeToCustomer"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].chargeToCustomer`
|
||||
)
|
||||
"
|
||||
@change="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].chargeToCustomer`
|
||||
)
|
||||
"
|
||||
></v-checkbox>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemExpenseTaxPaid')"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-currency
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].expenses[activeItemIndex].taxPaid
|
||||
"
|
||||
:readonly="formState.readOnly || isDeleted"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemExpenseTaxPaid')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].taxPaid`
|
||||
"
|
||||
data-cy="expenseTaxPaid"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].taxPaid`
|
||||
)
|
||||
"
|
||||
:rules="[
|
||||
form().decimalValid(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].taxPaid`
|
||||
),
|
||||
form().required(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].taxPaid`
|
||||
)
|
||||
]"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].taxPaid`
|
||||
)
|
||||
"
|
||||
></gz-currency>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'WorkOrderItemExpenseChargeTaxCodeID') &&
|
||||
!value.userIsRestrictedType
|
||||
"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-pick-list
|
||||
:aya-type="$ay.ayt().TaxCode"
|
||||
show-edit-icon
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].expenses[activeItemIndex]
|
||||
.chargeTaxCodeId
|
||||
"
|
||||
:readonly="formState.readOnly || isDeleted"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemExpenseChargeTaxCodeID')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].chargeTaxCodeId`
|
||||
"
|
||||
data-cy="expenseChargeTaxCode"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].chargeTaxCodeId`
|
||||
)
|
||||
"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].chargeTaxCodeId`
|
||||
)
|
||||
"
|
||||
@update:name="taxCodeChange"
|
||||
></gz-pick-list>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'WorkOrderItemExpenseReimburseUser') &&
|
||||
!value.userIsRestrictedType
|
||||
"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<v-checkbox
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].expenses[activeItemIndex]
|
||||
.reimburseUser
|
||||
"
|
||||
:readonly="formState.readOnly"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemExpenseReimburseUser')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].reimburseUser`
|
||||
"
|
||||
data-cy="expenseReimburseUser"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].reimburseUser`
|
||||
)
|
||||
"
|
||||
@change="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].reimburseUser`
|
||||
)
|
||||
"
|
||||
></v-checkbox>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemExpenseUserID')"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-pick-list
|
||||
:aya-type="$ay.ayt().User"
|
||||
variant="tech"
|
||||
:show-edit-icon="!value.userIsRestrictedType"
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].expenses[activeItemIndex].userId
|
||||
"
|
||||
:readonly="
|
||||
formState.readOnly || isDeleted || value.userIsRestrictedType
|
||||
"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemExpenseUserID')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].userId`
|
||||
"
|
||||
data-cy="expenseUser"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].userId`
|
||||
)
|
||||
"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].userId`
|
||||
)
|
||||
"
|
||||
@update:name="userChange"
|
||||
></gz-pick-list>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemExpenseDescription')"
|
||||
cols="12"
|
||||
>
|
||||
<v-textarea
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].expenses[activeItemIndex]
|
||||
.description
|
||||
"
|
||||
:readonly="formState.readOnly"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemExpenseDescription')"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].description`
|
||||
)
|
||||
"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].description`
|
||||
"
|
||||
data-cy="expenseDescription"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].expenses[${activeItemIndex}].description`
|
||||
)
|
||||
"
|
||||
auto-grow
|
||||
></v-textarea>
|
||||
</v-col>
|
||||
</template>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* XXXeslint-disable */
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
export default {
|
||||
created() {
|
||||
this.setDefaultView();
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeItemIndex: null,
|
||||
selectedRow: []
|
||||
};
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
default: null,
|
||||
type: Object
|
||||
},
|
||||
pvm: {
|
||||
default: null,
|
||||
type: Object
|
||||
},
|
||||
activeWoItemIndex: {
|
||||
default: null,
|
||||
type: Number
|
||||
},
|
||||
gotoIndex: {
|
||||
default: null,
|
||||
type: Number
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
activeWoItemIndex(val, oldVal) {
|
||||
if (val != oldVal) {
|
||||
this.setDefaultView();
|
||||
}
|
||||
},
|
||||
gotoIndex(val, oldVal) {
|
||||
if (val != oldVal) {
|
||||
let gotoIndex = val;
|
||||
if (val < 0) {
|
||||
//it's a create request
|
||||
gotoIndex = this.newItem();
|
||||
}
|
||||
|
||||
this.selectedRow = [{ index: gotoIndex }];
|
||||
this.activeItemIndex = gotoIndex;
|
||||
this.$nextTick(() => {
|
||||
const el = this.$refs.expensetopform;
|
||||
if (el) {
|
||||
el.scrollIntoView({ behavior: "smooth" });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
userChange(newName) {
|
||||
this.value.items[this.activeWoItemIndex].expenses[
|
||||
this.activeItemIndex
|
||||
].userViz = newName;
|
||||
},
|
||||
taxCodeChange(newName) {
|
||||
this.value.items[this.activeWoItemIndex].expenses[
|
||||
this.activeItemIndex
|
||||
].taxCodeViz = newName;
|
||||
},
|
||||
newItem() {
|
||||
let newIndex = this.value.items[this.activeWoItemIndex].expenses.length;
|
||||
|
||||
//#################################### IMPORTANT ##################################################
|
||||
//NOTE: default values are critical and must match server validation ExpenseValidateAsync for restricted users
|
||||
//so that they are in agreement otherwise restricted users will never be able to create new records
|
||||
|
||||
this.value.items[this.activeWoItemIndex].expenses.push({
|
||||
id: 0,
|
||||
concurrency: 0,
|
||||
description: null,
|
||||
name: null,
|
||||
totalCost: 0,
|
||||
chargeAmount: 0,
|
||||
taxPaid: 0,
|
||||
chargeTaxCodeId: null,
|
||||
taxCodeViz: null,
|
||||
reimburseUser: false,
|
||||
userId: this.$store.getters.isScheduleableUser
|
||||
? this.$store.state.userId
|
||||
: null,
|
||||
userViz: this.$store.getters.isScheduleableUser
|
||||
? this.$store.state.userName
|
||||
: null,
|
||||
chargeToCustomer: false,
|
||||
isDirty: true,
|
||||
quoteItemId: this.value.items[this.activeWoItemIndex].id,
|
||||
uid: Date.now() //used for error tracking / display
|
||||
});
|
||||
this.$emit("change");
|
||||
this.selectedRow = [{ index: newIndex }];
|
||||
this.activeItemIndex = newIndex;
|
||||
return newIndex; //for create new on goto
|
||||
},
|
||||
unDeleteItem() {
|
||||
this.value.items[this.activeWoItemIndex].expenses[
|
||||
this.activeItemIndex
|
||||
].deleted = false;
|
||||
this.setDefaultView();
|
||||
},
|
||||
deleteItem() {
|
||||
this.value.items[this.activeWoItemIndex].expenses[
|
||||
this.activeItemIndex
|
||||
].deleted = true;
|
||||
this.setDefaultView();
|
||||
this.$emit("change");
|
||||
},
|
||||
deleteAllItem() {
|
||||
this.value.items[this.activeWoItemIndex].expenses.forEach(
|
||||
z => (z.deleted = true)
|
||||
);
|
||||
this.setDefaultView();
|
||||
this.$emit("change");
|
||||
},
|
||||
setDefaultView: function() {
|
||||
//if only one record left then display it otherwise just let the datatable show what the user can click on
|
||||
if (
|
||||
this.hasData &&
|
||||
this.value.items[this.activeWoItemIndex].expenses.length == 1
|
||||
) {
|
||||
this.selectedRow = [{ index: 0 }];
|
||||
this.activeItemIndex = 0;
|
||||
} else {
|
||||
this.selectedRow = [];
|
||||
this.activeItemIndex = null; //select nothing in essence resetting a child selects and this one too clearing form
|
||||
}
|
||||
},
|
||||
handleRowClick: function(item) {
|
||||
this.activeItemIndex = item.index;
|
||||
this.selectedRow = [{ index: item.index }];
|
||||
},
|
||||
form() {
|
||||
return window.$gz.form;
|
||||
},
|
||||
fieldValueChanged(ref) {
|
||||
if (!this.formState.loading && !this.formState.readonly) {
|
||||
//flag this record dirty so it gets picked up by save
|
||||
this.value.items[this.activeWoItemIndex].expenses[
|
||||
this.activeItemIndex
|
||||
].isDirty = true;
|
||||
window.$gz.form.fieldValueChanged(this.pvm, ref);
|
||||
|
||||
// //set viz if applicable
|
||||
// if(ref==""){
|
||||
// let selectedPartWarehouse = vm.$refs.partWarehouseId.getFullSelectionValue();
|
||||
// }
|
||||
}
|
||||
},
|
||||
itemRowClasses: function(item) {
|
||||
let ret = "";
|
||||
const isDeleted =
|
||||
this.value.items[this.activeWoItemIndex].expenses[item.index]
|
||||
.deleted === true;
|
||||
|
||||
const hasError = this.form().childRowHasError(
|
||||
this,
|
||||
`Items[${this.activeWoItemIndex}].Expenses[${item.index}].`
|
||||
);
|
||||
|
||||
if (isDeleted) {
|
||||
ret += this.form().tableRowDeletedClass();
|
||||
}
|
||||
if (hasError) {
|
||||
ret += this.form().tableRowErrorClass();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isDeleted: function() {
|
||||
if (
|
||||
this.value.items[this.activeWoItemIndex].expenses[
|
||||
this.activeItemIndex
|
||||
] == null
|
||||
) {
|
||||
this.setDefaultView();
|
||||
return true;
|
||||
}
|
||||
return (
|
||||
this.value.items[this.activeWoItemIndex].expenses[this.activeItemIndex]
|
||||
.deleted === true
|
||||
);
|
||||
},
|
||||
parentDeleted: function() {
|
||||
return this.value.items[this.activeWoItemIndex].deleted === true;
|
||||
},
|
||||
|
||||
headerList: function() {
|
||||
/*
|
||||
If the column is a text, left-align it
|
||||
If the column is a number or number + unit, (or date) right-align it (like excel)
|
||||
*/
|
||||
let headers = [];
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemExpenseName")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemExpenseName"),
|
||||
align: "start",
|
||||
value: "name"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemExpenseTotalCost")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemExpenseTotalCost"),
|
||||
align: "right",
|
||||
value: "totalCost"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemExpenseChargeAmount")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemExpenseChargeAmount"),
|
||||
align: "right",
|
||||
value: "chargeAmount"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemExpenseChargeToCustomer")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemExpenseChargeToCustomer"),
|
||||
align: "center",
|
||||
value: "chargeToCustomer"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemExpenseTaxPaid")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemExpenseTaxPaid"),
|
||||
align: "right",
|
||||
value: "taxPaid"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemExpenseChargeTaxCodeID")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("Tax"),
|
||||
align: "left",
|
||||
value: "taxCodeViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "ExpenseTaxAViz")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("TaxAAmt"),
|
||||
align: "right",
|
||||
value: "taxAViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "ExpenseTaxBViz")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("TaxBAmt"),
|
||||
align: "right",
|
||||
value: "taxBViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "ExpenseLineTotalViz")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("LineTotal"),
|
||||
align: "right",
|
||||
value: "lineTotalViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemExpenseReimburseUser")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemExpenseReimburseUser"),
|
||||
align: "center",
|
||||
value: "reimburseUser"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemExpenseUserID")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemExpenseUserID"),
|
||||
align: "left",
|
||||
value: "userViz"
|
||||
});
|
||||
}
|
||||
|
||||
return headers;
|
||||
},
|
||||
itemList: function() {
|
||||
return this.value.items[this.activeWoItemIndex].expenses.map((x, i) => {
|
||||
return {
|
||||
index: i,
|
||||
id: x.id,
|
||||
name: x.name,
|
||||
totalCost: window.$gz.locale.currencyLocalized(
|
||||
x.totalCost,
|
||||
this.pvm.languageName,
|
||||
this.pvm.currencyName
|
||||
),
|
||||
chargeAmount: window.$gz.locale.currencyLocalized(
|
||||
x.chargeAmount,
|
||||
this.pvm.languageName,
|
||||
this.pvm.currencyName
|
||||
),
|
||||
chargeToCustomer: x.chargeToCustomer,
|
||||
taxPaid: window.$gz.locale.currencyLocalized(
|
||||
x.taxPaid,
|
||||
this.pvm.languageName,
|
||||
this.pvm.currencyName
|
||||
),
|
||||
taxCodeViz: x.taxCodeViz,
|
||||
taxAViz: window.$gz.locale.currencyLocalized(
|
||||
x.taxAViz,
|
||||
this.pvm.languageName,
|
||||
this.pvm.currencyName
|
||||
),
|
||||
taxBViz: window.$gz.locale.currencyLocalized(
|
||||
x.taxBViz,
|
||||
this.pvm.languageName,
|
||||
this.pvm.currencyName
|
||||
),
|
||||
lineTotalViz: window.$gz.locale.currencyLocalized(
|
||||
x.lineTotalViz,
|
||||
this.pvm.languageName,
|
||||
this.pvm.currencyName
|
||||
),
|
||||
reimburseUser: x.reimburseUser,
|
||||
userViz: x.userViz
|
||||
};
|
||||
});
|
||||
},
|
||||
formState: function() {
|
||||
return this.pvm.formState;
|
||||
},
|
||||
formCustomTemplateKey: function() {
|
||||
return this.pvm.formCustomTemplateKey;
|
||||
},
|
||||
hasData: function() {
|
||||
return this.value.items[this.activeWoItemIndex].expenses.length > 0;
|
||||
},
|
||||
hasSelection: function() {
|
||||
return this.activeItemIndex != null;
|
||||
},
|
||||
canAdd: function() {
|
||||
return this.pvm.rights.change;
|
||||
},
|
||||
canDelete: function() {
|
||||
return this.activeItemIndex != null && this.pvm.rights.change;
|
||||
},
|
||||
canDeleteAll: function() {
|
||||
return this.pvm.rights.change && !this.value.userIsRestrictedType;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
997
ayanova/src/components/quote-item-labors.vue
Normal file
997
ayanova/src/components/quote-item-labors.vue
Normal file
@@ -0,0 +1,997 @@
|
||||
<template>
|
||||
<div v-if="value != null" class="mt-8">
|
||||
<v-row>
|
||||
<v-col cols="12">
|
||||
<v-menu offset-y max-width="600px">
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<div class="text-h6">
|
||||
<v-icon large :color="hasData ? 'primary' : null" class="mr-2"
|
||||
>$ayiHammer</v-icon
|
||||
>
|
||||
{{ $ay.t("WorkOrderItemLaborList") }}
|
||||
<v-btn v-if="!parentDeleted" large icon v-bind="attrs" v-on="on">
|
||||
<v-icon small color="primary">$ayiEllipsisV</v-icon>
|
||||
</v-btn>
|
||||
</div>
|
||||
</template>
|
||||
<v-list>
|
||||
<v-list-item v-if="canAdd" @click="newItem">
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiPlus</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{ $ay.t("New") }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item
|
||||
v-if="hasSelection && !formState.readOnly"
|
||||
@click="appendTasks"
|
||||
>
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiTasks</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{ $ay.t("AppendTasks") }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item v-if="canDelete && isDeleted" @click="unDeleteItem">
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiTrashRestoreAlt</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{ $ay.t("Undelete") }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item v-if="canDelete && !isDeleted" @click="deleteItem">
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiTrashAlt</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{ $ay.t("SoftDelete") }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item v-if="canDeleteAll" @click="deleteAllItem">
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiDumpster</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{
|
||||
$ay.t("SoftDeleteAll")
|
||||
}}</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</v-col>
|
||||
|
||||
<template v-if="hasData">
|
||||
<!-- ############################################################### -->
|
||||
<v-col cols="12" class="mb-10">
|
||||
<v-data-table
|
||||
:headers="headerList"
|
||||
:items="itemList"
|
||||
item-key="index"
|
||||
v-model="selectedRow"
|
||||
class="elevation-1"
|
||||
disable-pagination
|
||||
disable-filtering
|
||||
disable-sort
|
||||
hide-default-footer
|
||||
data-cy="laborsTable"
|
||||
dense
|
||||
:item-class="itemRowClasses"
|
||||
@click:row="handleRowClick"
|
||||
:show-select="$vuetify.breakpoint.xs"
|
||||
single-select
|
||||
>
|
||||
</v-data-table>
|
||||
</v-col>
|
||||
</template>
|
||||
<template v-if="hasData && hasSelection">
|
||||
<div ref="labortopform"></div>
|
||||
<v-btn
|
||||
v-if="canDelete && isDeleted"
|
||||
large
|
||||
@click="unDeleteItem"
|
||||
color="primary"
|
||||
>{{ $ay.t("Undelete")
|
||||
}}<v-icon right large>$ayiTrashRestoreAlt</v-icon></v-btn
|
||||
>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemLaborServiceStartDate')"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-date-time-picker
|
||||
:label="$ay.t('WorkOrderItemLaborServiceStartDate')"
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].labors[activeItemIndex]
|
||||
.serviceStartDate
|
||||
"
|
||||
:readonly="formState.readOnly"
|
||||
:disabled="isDeleted"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].serviceStartDate`
|
||||
"
|
||||
data-cy="serviceStartDate"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].serviceStartDate`
|
||||
)
|
||||
"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].serviceStartDate`
|
||||
)
|
||||
"
|
||||
></gz-date-time-picker>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemLaborServiceStopDate')"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-date-time-picker
|
||||
:label="$ay.t('WorkOrderItemLaborServiceStopDate')"
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].labors[activeItemIndex]
|
||||
.serviceStopDate
|
||||
"
|
||||
:readonly="formState.readOnly"
|
||||
:disabled="isDeleted"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].serviceStopDate`
|
||||
"
|
||||
data-cy="serviceStopDate"
|
||||
:rules="[
|
||||
form().datePrecedence(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].serviceStartDate`,
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].serviceStopDate`
|
||||
)
|
||||
]"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].serviceStopDate`
|
||||
)
|
||||
"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].serviceStopDate`
|
||||
)
|
||||
"
|
||||
></gz-date-time-picker>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemLaborServiceRateQuantity')"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-decimal
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].labors[activeItemIndex]
|
||||
.serviceRateQuantity
|
||||
"
|
||||
:readonly="formState.readOnly || isDeleted"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemLaborServiceRateQuantity')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].serviceRateQuantity`
|
||||
"
|
||||
data-cy="laborServiceRateQuantity"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].serviceRateQuantity`
|
||||
)
|
||||
"
|
||||
:rules="[
|
||||
form().decimalValid(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].serviceRateQuantity`
|
||||
),
|
||||
form().required(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].serviceRateQuantity`
|
||||
)
|
||||
]"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].serviceRateQuantity`
|
||||
)
|
||||
"
|
||||
></gz-decimal>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemLaborServiceRateID')"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-pick-list
|
||||
:aya-type="$ay.ayt().ServiceRate"
|
||||
:variant="'contractid:' + value.contractId"
|
||||
:show-edit-icon="!value.userIsRestrictedType"
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].labors[activeItemIndex]
|
||||
.serviceRateId
|
||||
"
|
||||
:readonly="formState.readOnly || isDeleted"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemLaborServiceRateID')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].serviceRateId`
|
||||
"
|
||||
data-cy="labors.serviceRateId"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].serviceRateId`
|
||||
)
|
||||
"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].serviceRateId`
|
||||
)
|
||||
"
|
||||
@update:name="rateChange"
|
||||
></gz-pick-list>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemLaborUserID')"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-pick-list
|
||||
:aya-type="$ay.ayt().User"
|
||||
variant="tech"
|
||||
:show-edit-icon="!value.userIsRestrictedType"
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].labors[activeItemIndex].userId
|
||||
"
|
||||
:readonly="
|
||||
formState.readOnly || isDeleted || value.userIsRestrictedType
|
||||
"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemLaborUserID')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].userId`
|
||||
"
|
||||
data-cy="labors.userid"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].userId`
|
||||
)
|
||||
"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].userId`
|
||||
)
|
||||
"
|
||||
@update:name="userChange"
|
||||
></gz-pick-list>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemLaborNoChargeQuantity')"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-decimal
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].labors[activeItemIndex]
|
||||
.noChargeQuantity
|
||||
"
|
||||
:readonly="formState.readOnly || isDeleted"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemLaborNoChargeQuantity')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].noChargeQuantity`
|
||||
"
|
||||
data-cy="laborNoChargeQuantity"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].noChargeQuantity`
|
||||
)
|
||||
"
|
||||
:rules="[
|
||||
form().decimalValid(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].noChargeQuantity`
|
||||
),
|
||||
form().required(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].noChargeQuantity`
|
||||
)
|
||||
]"
|
||||
@input="
|
||||
fieldValueChanged(`Items[${activeWoItemIndex}].labors[
|
||||
${activeItemIndex}
|
||||
].noChargeQuantity`)
|
||||
"
|
||||
></gz-decimal>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'WorkOrderItemLaborTaxRateSaleID') &&
|
||||
!value.userIsRestrictedType
|
||||
"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-pick-list
|
||||
:aya-type="$ay.ayt().TaxCode"
|
||||
show-edit-icon
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].labors[activeItemIndex]
|
||||
.taxCodeSaleId
|
||||
"
|
||||
:readonly="formState.readOnly || isDeleted"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemLaborTaxRateSaleID')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].taxCodeSaleId`
|
||||
"
|
||||
data-cy="laborTaxCodeSaleId"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].taxCodeSaleId`
|
||||
)
|
||||
"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].taxCodeSaleId`
|
||||
)
|
||||
"
|
||||
@update:name="taxCodeChange"
|
||||
></gz-pick-list>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'LaborPriceOverride') &&
|
||||
!value.userIsRestrictedType
|
||||
"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-currency
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].labors[activeItemIndex]
|
||||
.priceOverride
|
||||
"
|
||||
can-clear
|
||||
:readonly="formState.readOnly || isDeleted"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('PriceOverride')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].priceOverride`
|
||||
"
|
||||
data-cy="laborpriceoverride"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].priceOverride`
|
||||
)
|
||||
"
|
||||
:rules="[
|
||||
form().decimalValid(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].priceOverride`
|
||||
)
|
||||
]"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].priceOverride`
|
||||
)
|
||||
"
|
||||
></gz-currency>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemLaborServiceDetails')"
|
||||
cols="12"
|
||||
>
|
||||
<v-textarea
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].labors[activeItemIndex]
|
||||
.serviceDetails
|
||||
"
|
||||
:readonly="formState.readOnly"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemLaborServiceDetails')"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].serviceDetails`
|
||||
)
|
||||
"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].serviceDetails`
|
||||
"
|
||||
data-cy="laborserviceDetails"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].labors[${activeItemIndex}].serviceDetails`
|
||||
)
|
||||
"
|
||||
auto-grow
|
||||
></v-textarea>
|
||||
</v-col>
|
||||
</template>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* XXXeslint-disable */
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
export default {
|
||||
created() {
|
||||
this.setDefaultView();
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeItemIndex: null,
|
||||
selectedRow: []
|
||||
};
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
default: null,
|
||||
type: Object
|
||||
},
|
||||
pvm: {
|
||||
default: null,
|
||||
type: Object
|
||||
},
|
||||
activeWoItemIndex: {
|
||||
default: null,
|
||||
type: Number
|
||||
},
|
||||
gotoIndex: {
|
||||
default: null,
|
||||
type: Number
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
activeWoItemIndex(val, oldVal) {
|
||||
if (val != oldVal) {
|
||||
this.setDefaultView();
|
||||
}
|
||||
},
|
||||
gotoIndex(val, oldVal) {
|
||||
if (val != oldVal) {
|
||||
let gotoIndex = val;
|
||||
if (val < 0) {
|
||||
//it's a create request
|
||||
gotoIndex = this.newItem();
|
||||
}
|
||||
this.selectedRow = [{ index: gotoIndex }];
|
||||
this.activeItemIndex = gotoIndex;
|
||||
this.$nextTick(() => {
|
||||
const el = this.$refs.labortopform;
|
||||
if (el) {
|
||||
el.scrollIntoView({ behavior: "smooth" });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
appendTasks() {
|
||||
const tasks = this.value.items[this.activeWoItemIndex].tasks;
|
||||
if (tasks.length == 0) {
|
||||
return;
|
||||
}
|
||||
const l = this.value.items[this.activeWoItemIndex].labors[
|
||||
this.activeItemIndex
|
||||
];
|
||||
let at = "";
|
||||
tasks.forEach(z => {
|
||||
at += `${z.task} - ${z.statusViz}\n`;
|
||||
});
|
||||
l.serviceDetails += `\n${at}`;
|
||||
},
|
||||
userChange(newName) {
|
||||
this.value.items[this.activeWoItemIndex].labors[
|
||||
this.activeItemIndex
|
||||
].userViz = newName;
|
||||
},
|
||||
rateChange(newName) {
|
||||
this.value.items[this.activeWoItemIndex].labors[
|
||||
this.activeItemIndex
|
||||
].serviceRateViz = newName;
|
||||
},
|
||||
taxCodeChange(newName) {
|
||||
this.value.items[this.activeWoItemIndex].labors[
|
||||
this.activeItemIndex
|
||||
].taxCodeViz = newName;
|
||||
},
|
||||
newItem() {
|
||||
let newIndex = this.value.items[this.activeWoItemIndex].labors.length;
|
||||
|
||||
this.value.items[this.activeWoItemIndex].labors.push({
|
||||
id: 0,
|
||||
concurrency: 0,
|
||||
userId: this.$store.getters.isScheduleableUser
|
||||
? this.$store.state.userId
|
||||
: null,
|
||||
serviceStartDate: null,
|
||||
serviceStopDate: null,
|
||||
serviceRateId: null,
|
||||
serviceDetails: null,
|
||||
serviceRateQuantity: 0,
|
||||
noChargeQuantity: 0,
|
||||
taxCodeSaleId: null,
|
||||
price: 0,
|
||||
priceOverride: null,
|
||||
isDirty: true,
|
||||
quoteItemId: this.value.items[this.activeWoItemIndex].id,
|
||||
uid: Date.now(),
|
||||
userViz: this.$store.getters.isScheduleableUser
|
||||
? this.$store.state.userName
|
||||
: null,
|
||||
serviceRateViz: null,
|
||||
taxCodeViz: null
|
||||
});
|
||||
this.$emit("change");
|
||||
this.selectedRow = [{ index: newIndex }];
|
||||
this.activeItemIndex = newIndex;
|
||||
return newIndex; //for create new on goto
|
||||
},
|
||||
unDeleteItem() {
|
||||
this.value.items[this.activeWoItemIndex].labors[
|
||||
this.activeItemIndex
|
||||
].deleted = false;
|
||||
this.setDefaultView();
|
||||
},
|
||||
deleteItem() {
|
||||
this.value.items[this.activeWoItemIndex].labors[
|
||||
this.activeItemIndex
|
||||
].deleted = true;
|
||||
this.setDefaultView();
|
||||
this.$emit("change");
|
||||
},
|
||||
deleteAllItem() {
|
||||
this.value.items[this.activeWoItemIndex].labors.forEach(
|
||||
z => (z.deleted = true)
|
||||
);
|
||||
this.setDefaultView();
|
||||
this.$emit("change");
|
||||
},
|
||||
setDefaultView: function() {
|
||||
//if only one record left then display it otherwise just let the datatable show what the user can click on
|
||||
if (this.value.items[this.activeWoItemIndex].labors.length == 1) {
|
||||
this.selectedRow = [{ index: 0 }];
|
||||
this.activeItemIndex = 0;
|
||||
} else {
|
||||
this.selectedRow = [];
|
||||
this.activeItemIndex = null; //select nothing in essence resetting a child selects and this one too clearing form
|
||||
}
|
||||
},
|
||||
handleRowClick: function(item) {
|
||||
this.activeItemIndex = item.index;
|
||||
this.selectedRow = [{ index: item.index }];
|
||||
},
|
||||
form() {
|
||||
return window.$gz.form;
|
||||
},
|
||||
fieldValueChanged(ref) {
|
||||
if (!this.formState.loading && !this.formState.readonly) {
|
||||
//flag this record dirty so it gets picked up by save
|
||||
this.value.items[this.activeWoItemIndex].labors[
|
||||
this.activeItemIndex
|
||||
].isDirty = true;
|
||||
window.$gz.form.fieldValueChanged(this.pvm, ref);
|
||||
//------- SPECIAL HANDLING OF CHANGES -----------
|
||||
const isNew =
|
||||
this.value.items[this.activeWoItemIndex].labors[this.activeItemIndex]
|
||||
.id == 0;
|
||||
|
||||
//Auto calculate dates / quantities / global defaults
|
||||
const dStart = this.value.items[this.activeWoItemIndex].labors[
|
||||
this.activeItemIndex
|
||||
].serviceStartDate;
|
||||
const dStop = this.value.items[this.activeWoItemIndex].labors[
|
||||
this.activeItemIndex
|
||||
].serviceStopDate;
|
||||
if (ref.includes("serviceStartDate") && dStart != null) {
|
||||
this.handleStartDateChange(isNew, dStart, dStop);
|
||||
}
|
||||
if (ref.includes("serviceStopDate") && dStop != null) {
|
||||
this.handleStopDateChange(isNew, dStart, dStop);
|
||||
}
|
||||
//------------------------------------------------------
|
||||
}
|
||||
},
|
||||
handleStartDateChange: function(isNew, dStart, dStop) {
|
||||
const globalMinutes =
|
||||
window.$gz.store.state.globalSettings.workLaborScheduleDefaultMinutes;
|
||||
|
||||
if (isNew && dStop == null) {
|
||||
if (globalMinutes != 0) {
|
||||
//set stop date based on start date and global minutes
|
||||
this.value.items[this.activeWoItemIndex].labors[
|
||||
this.activeItemIndex
|
||||
].serviceStopDate = window.$gz.locale.addMinutesToUTC8601String(
|
||||
dStart,
|
||||
globalMinutes
|
||||
);
|
||||
|
||||
this.value.items[this.activeWoItemIndex].labors[
|
||||
this.activeItemIndex
|
||||
].serviceRateQuantity = globalMinutes;
|
||||
}
|
||||
} else {
|
||||
//Existing record or both dates filled, just update quantity
|
||||
if (dStop != null) {
|
||||
this.value.items[this.activeWoItemIndex].labors[
|
||||
this.activeItemIndex
|
||||
].serviceRateQuantity = window.$gz.locale.diffHoursFromUTC8601String(
|
||||
dStart,
|
||||
dStop
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
handleStopDateChange: function(isNew, dStart, dStop) {
|
||||
const globalMinutes =
|
||||
window.$gz.store.state.globalSettings.workLaborScheduleDefaultMinutes;
|
||||
|
||||
if (isNew && dStart == null) {
|
||||
if (globalMinutes != 0) {
|
||||
//set start date based on stop date and global minutes
|
||||
this.value.items[this.activeWoItemIndex].labors[
|
||||
this.activeItemIndex
|
||||
].serviceStartDate = window.$gz.locale.addMinutesToUTC8601String(
|
||||
dStop,
|
||||
0 - globalMinutes
|
||||
);
|
||||
|
||||
this.value.items[this.activeWoItemIndex].labors[
|
||||
this.activeItemIndex
|
||||
].serviceRateQuantity = globalMinutes;
|
||||
}
|
||||
} else {
|
||||
//Existing record or both dates filled, just update quantity
|
||||
if (dStart != null) {
|
||||
this.value.items[this.activeWoItemIndex].labors[
|
||||
this.activeItemIndex
|
||||
].serviceRateQuantity = window.$gz.locale.diffHoursFromUTC8601String(
|
||||
dStart,
|
||||
dStop
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
itemRowClasses: function(item) {
|
||||
let ret = "";
|
||||
const isDeleted =
|
||||
this.value.items[this.activeWoItemIndex].labors[item.index].deleted ===
|
||||
true;
|
||||
|
||||
const hasError = this.form().childRowHasError(
|
||||
this,
|
||||
`Items[${this.activeWoItemIndex}].Labors[${item.index}].`
|
||||
);
|
||||
|
||||
if (isDeleted) {
|
||||
ret += this.form().tableRowDeletedClass();
|
||||
}
|
||||
if (hasError) {
|
||||
ret += this.form().tableRowErrorClass();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
//---
|
||||
},
|
||||
computed: {
|
||||
isDeleted: function() {
|
||||
if (
|
||||
this.value.items[this.activeWoItemIndex].labors[this.activeItemIndex] ==
|
||||
null
|
||||
) {
|
||||
this.setDefaultView();
|
||||
return true;
|
||||
}
|
||||
return (
|
||||
this.value.items[this.activeWoItemIndex].labors[this.activeItemIndex]
|
||||
.deleted === true
|
||||
);
|
||||
},
|
||||
parentDeleted: function() {
|
||||
return this.value.items[this.activeWoItemIndex].deleted === true;
|
||||
},
|
||||
|
||||
headerList: function() {
|
||||
/*
|
||||
If the column is a text, left-align it
|
||||
If the column is a number or number + unit, (or date) right-align it (like excel)
|
||||
*/
|
||||
let headers = [];
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemLaborServiceStartDate")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemLaborServiceStartDate"),
|
||||
align: "right",
|
||||
value: "serviceStartDate"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemLaborServiceStopDate")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemLaborServiceStopDate"),
|
||||
align: "right",
|
||||
value: "serviceStopDate"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemLaborServiceRateQuantity")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemLaborServiceRateQuantity"),
|
||||
align: "right",
|
||||
value: "serviceRateQuantity"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemLaborServiceRateID")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemLaborServiceRateID"),
|
||||
align: "left",
|
||||
value: "serviceRateViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemLaborServiceDetails")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemLaborServiceDetails"),
|
||||
align: "left",
|
||||
value: "serviceDetails"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemLaborUserID")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemLaborUserID"),
|
||||
align: "left",
|
||||
value: "userViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemLaborNoChargeQuantity")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemLaborNoChargeQuantity"),
|
||||
align: "right",
|
||||
value: "noChargeQuantity"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "LaborUnitOfMeasureViz")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("UnitOfMeasure"),
|
||||
align: "left",
|
||||
value: "unitOfMeasureViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "LaborCostViz") &&
|
||||
this.value.userCanViewLaborOrTravelRateCosts &&
|
||||
!this.value.userIsRestrictedType
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("Cost"),
|
||||
align: "right",
|
||||
value: "costViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "LaborListPriceViz") &&
|
||||
!this.value.userIsRestrictedType
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("ListPrice"),
|
||||
align: "right",
|
||||
value: "listPriceViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "LaborPriceOverride") &&
|
||||
!this.value.userIsRestrictedType
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("PriceOverride"),
|
||||
align: "right",
|
||||
value: "priceOverride"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "LaborPriceViz") &&
|
||||
!this.value.userIsRestrictedType
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("Price"),
|
||||
align: "right",
|
||||
value: "priceViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "WorkOrderItemLaborTaxRateSaleID") &&
|
||||
!this.value.userIsRestrictedType
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("Tax"),
|
||||
align: "left",
|
||||
value: "taxCodeViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "LaborNetViz") &&
|
||||
!this.value.userIsRestrictedType
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("NetPrice"),
|
||||
align: "right",
|
||||
value: "netViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "LaborTaxAViz") &&
|
||||
!this.value.userIsRestrictedType
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("TaxAAmt"),
|
||||
align: "right",
|
||||
value: "taxAViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "LaborTaxBViz") &&
|
||||
!this.value.userIsRestrictedType
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("TaxBAmt"),
|
||||
align: "right",
|
||||
value: "taxBViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "LaborLineTotalViz") &&
|
||||
!this.value.userIsRestrictedType
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("LineTotal"),
|
||||
align: "right",
|
||||
value: "lineTotalViz"
|
||||
});
|
||||
}
|
||||
return headers;
|
||||
},
|
||||
itemList: function() {
|
||||
return this.value.items[this.activeWoItemIndex].labors.map((x, i) => {
|
||||
return {
|
||||
index: i,
|
||||
id: x.id,
|
||||
serviceStartDate: window.$gz.locale.utcDateToShortDateAndTimeLocalized(
|
||||
x.serviceStartDate,
|
||||
this.pvm.timeZoneName,
|
||||
this.pvm.languageName,
|
||||
this.pvm.hour12
|
||||
),
|
||||
serviceStopDate: window.$gz.locale.utcDateToShortDateAndTimeLocalized(
|
||||
x.serviceStopDate,
|
||||
this.pvm.timeZoneName,
|
||||
this.pvm.languageName,
|
||||
this.pvm.hour12
|
||||
),
|
||||
|
||||
serviceRateQuantity: window.$gz.locale.decimalLocalized(
|
||||
x.serviceRateQuantity,
|
||||
this.pvm.languageName
|
||||
),
|
||||
serviceRateViz: x.serviceRateViz,
|
||||
userViz: x.userViz,
|
||||
noChargeQuantity: window.$gz.locale.decimalLocalized(
|
||||
x.noChargeQuantity,
|
||||
this.pvm.languageName
|
||||
),
|
||||
unitOfMeasureViz: x.unitOfMeasureViz,
|
||||
costViz: window.$gz.locale.currencyLocalized(
|
||||
x.costViz,
|
||||
this.pvm.languageName,
|
||||
this.pvm.currencyName
|
||||
),
|
||||
listPriceViz: window.$gz.locale.currencyLocalized(
|
||||
x.listPriceViz,
|
||||
this.pvm.languageName,
|
||||
this.pvm.currencyName
|
||||
),
|
||||
priceViz: window.$gz.locale.currencyLocalized(
|
||||
x.priceViz,
|
||||
this.pvm.languageName,
|
||||
this.pvm.currencyName
|
||||
),
|
||||
taxCodeViz: x.taxCodeViz,
|
||||
priceOverride: window.$gz.locale.currencyLocalized(
|
||||
x.priceOverride,
|
||||
this.pvm.languageName,
|
||||
this.pvm.currencyName
|
||||
),
|
||||
netViz: window.$gz.locale.currencyLocalized(
|
||||
x.netViz,
|
||||
this.pvm.languageName,
|
||||
this.pvm.currencyName
|
||||
),
|
||||
taxAViz: window.$gz.locale.currencyLocalized(
|
||||
x.taxAViz,
|
||||
this.pvm.languageName,
|
||||
this.pvm.currencyName
|
||||
),
|
||||
taxBViz: window.$gz.locale.currencyLocalized(
|
||||
x.taxBViz,
|
||||
this.pvm.languageName,
|
||||
this.pvm.currencyName
|
||||
),
|
||||
lineTotalViz: window.$gz.locale.currencyLocalized(
|
||||
x.lineTotalViz,
|
||||
this.pvm.languageName,
|
||||
this.pvm.currencyName
|
||||
),
|
||||
serviceDetails: window.$gz.util.truncateString(
|
||||
x.serviceDetails,
|
||||
this.pvm.maxTableNotesLength
|
||||
)
|
||||
};
|
||||
});
|
||||
},
|
||||
formState: function() {
|
||||
return this.pvm.formState;
|
||||
},
|
||||
formCustomTemplateKey: function() {
|
||||
return this.pvm.formCustomTemplateKey;
|
||||
},
|
||||
hasData: function() {
|
||||
return this.value.items[this.activeWoItemIndex].labors.length > 0;
|
||||
},
|
||||
hasSelection: function() {
|
||||
return this.activeItemIndex != null;
|
||||
},
|
||||
canAdd: function() {
|
||||
return this.pvm.rights.change;
|
||||
},
|
||||
canDelete: function() {
|
||||
return this.activeItemIndex != null && this.pvm.rights.change;
|
||||
},
|
||||
canDeleteAll: function() {
|
||||
return this.pvm.rights.change && !this.value.userIsRestrictedType;
|
||||
}
|
||||
//----
|
||||
}
|
||||
};
|
||||
</script>
|
||||
885
ayanova/src/components/quote-item-loans.vue
Normal file
885
ayanova/src/components/quote-item-loans.vue
Normal file
@@ -0,0 +1,885 @@
|
||||
<template>
|
||||
<div v-if="value != null" class="mt-8">
|
||||
<v-row>
|
||||
<v-col cols="12">
|
||||
<v-menu offset-y max-width="600px">
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<div class="text-h6">
|
||||
<v-icon large :color="hasData ? 'primary' : null" class="mr-2"
|
||||
>$ayiPlug</v-icon
|
||||
>
|
||||
{{ $ay.t("WorkOrderItemLoanList") }}
|
||||
<v-btn v-if="!parentDeleted" large icon v-bind="attrs" v-on="on">
|
||||
<v-icon small color="primary">$ayiEllipsisV</v-icon>
|
||||
</v-btn>
|
||||
</div>
|
||||
</template>
|
||||
<v-list>
|
||||
<v-list-item v-if="canAdd" @click="newItem">
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiPlus</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{
|
||||
$ay.t("New")
|
||||
}}</v-list-item-title> </v-list-item
|
||||
><v-list-item v-if="canDelete && isDeleted" @click="unDeleteItem">
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiTrashRestoreAlt</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{ $ay.t("Undelete") }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item v-if="canDelete && !isDeleted" @click="deleteItem">
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiTrashAlt</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{ $ay.t("SoftDelete") }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item v-if="canDeleteAll" @click="deleteAllItem">
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiDumpster</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{
|
||||
$ay.t("SoftDeleteAll")
|
||||
}}</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</v-col>
|
||||
|
||||
<template v-if="hasData">
|
||||
<!-- ############################################################### -->
|
||||
<v-col cols="12" class="mb-10">
|
||||
<v-data-table
|
||||
:headers="headerList"
|
||||
:items="itemList"
|
||||
item-key="index"
|
||||
v-model="selectedRow"
|
||||
class="elevation-1"
|
||||
disable-pagination
|
||||
disable-filtering
|
||||
disable-sort
|
||||
hide-default-footer
|
||||
data-cy="loansTable"
|
||||
dense
|
||||
:item-class="itemRowClasses"
|
||||
@click:row="handleRowClick"
|
||||
:show-select="$vuetify.breakpoint.xs"
|
||||
single-select
|
||||
>
|
||||
</v-data-table>
|
||||
</v-col>
|
||||
</template>
|
||||
<template v-if="hasData && hasSelection">
|
||||
<div ref="loantopform"></div>
|
||||
<v-btn
|
||||
v-if="canDelete && isDeleted"
|
||||
large
|
||||
@click="unDeleteItem"
|
||||
color="primary"
|
||||
>{{ $ay.t("Undelete")
|
||||
}}<v-icon right large>$ayiTrashRestoreAlt</v-icon></v-btn
|
||||
>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemLoanUnit')"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-pick-list
|
||||
:aya-type="$ay.ayt().LoanUnit"
|
||||
:show-edit-icon="!value.userIsRestrictedType"
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].loans[activeItemIndex].loanUnitId
|
||||
"
|
||||
:readonly="
|
||||
formState.readOnly || isDeleted || value.userIsRestrictedType
|
||||
"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemLoanUnit')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].loans[${activeItemIndex}].loanUnitId`
|
||||
"
|
||||
data-cy="loans.loanUnitId"
|
||||
:rules="[
|
||||
form().required(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].loans[${activeItemIndex}].loanUnitId`
|
||||
)
|
||||
]"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].loans[${activeItemIndex}].loanUnitId`
|
||||
)
|
||||
"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].loans[${activeItemIndex}].loanUnitId`
|
||||
)
|
||||
"
|
||||
@update:name="loanUnitChange"
|
||||
></gz-pick-list>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'WorkOrderItemLoanRate') &&
|
||||
!value.userIsRestrictedType
|
||||
"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<v-select
|
||||
v-model="value.items[activeWoItemIndex].loans[activeItemIndex].rate"
|
||||
:items="pvm.selectLists.loanUnitRateUnits"
|
||||
item-text="name"
|
||||
item-value="id"
|
||||
:readonly="formState.readOnly || isDeleted"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemLoanRate')"
|
||||
:ref="`Items[${activeWoItemIndex}].loans[${activeItemIndex}].rate`"
|
||||
data-cy="loanUnitRateUnit"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].loans[${activeItemIndex}].rate`
|
||||
)
|
||||
"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].loans[${activeItemIndex}].rate`
|
||||
)
|
||||
"
|
||||
@change="loanUnitRateUnitChange"
|
||||
></v-select>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'WorkOrderItemLoanQuantity') &&
|
||||
!value.userIsRestrictedType
|
||||
"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-decimal
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].loans[activeItemIndex].quantity
|
||||
"
|
||||
:readonly="formState.readOnly || isDeleted"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemLoanQuantity')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].loans[${activeItemIndex}].quantity`
|
||||
"
|
||||
data-cy="loanQuantity"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].loans[${activeItemIndex}].quantity`
|
||||
)
|
||||
"
|
||||
:rules="[
|
||||
form().decimalValid(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].loans[${activeItemIndex}].quantity`
|
||||
),
|
||||
form().required(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].loans[${activeItemIndex}].quantity`
|
||||
)
|
||||
]"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].loans[${activeItemIndex}].quantity`
|
||||
)
|
||||
"
|
||||
></gz-decimal>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemLoanOutDate')"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-date-time-picker
|
||||
:label="$ay.t('WorkOrderItemLoanOutDate')"
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].loans[activeItemIndex].outDate
|
||||
"
|
||||
:readonly="formState.readOnly || value.userIsRestrictedType"
|
||||
:disabled="isDeleted"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].loans[${activeItemIndex}].outDate`
|
||||
"
|
||||
data-cy="loanUnitOutDate"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].loans[${activeItemIndex}].outDate`
|
||||
)
|
||||
"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].loans[${activeItemIndex}].outDate`
|
||||
)
|
||||
"
|
||||
></gz-date-time-picker>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemLoanDueDate')"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-date-time-picker
|
||||
:label="$ay.t('WorkOrderItemLoanDueDate')"
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].loans[activeItemIndex].dueDate
|
||||
"
|
||||
:readonly="formState.readOnly || value.userIsRestrictedType"
|
||||
:disabled="isDeleted"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].loans[${activeItemIndex}].dueDate`
|
||||
"
|
||||
data-cy="loanUnitDueDate"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].loans[${activeItemIndex}].dueDate`
|
||||
)
|
||||
"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].loans[${activeItemIndex}].dueDate`
|
||||
)
|
||||
"
|
||||
></gz-date-time-picker>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemLoanReturnDate')"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-date-time-picker
|
||||
:label="$ay.t('WorkOrderItemLoanReturnDate')"
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].loans[activeItemIndex].returnDate
|
||||
"
|
||||
:readonly="formState.readOnly || value.userIsRestrictedType"
|
||||
:disabled="isDeleted"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].loans[${activeItemIndex}].returnDate`
|
||||
"
|
||||
data-cy="loanUnitReturnDate"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].loans[${activeItemIndex}].returnDate`
|
||||
)
|
||||
"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].loans[${activeItemIndex}].returnDate`
|
||||
)
|
||||
"
|
||||
></gz-date-time-picker>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'WorkOrderItemLoanTaxCodeID') &&
|
||||
!value.userIsRestrictedType
|
||||
"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-pick-list
|
||||
:aya-type="$ay.ayt().TaxCode"
|
||||
show-edit-icon
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].loans[activeItemIndex].taxCodeId
|
||||
"
|
||||
:readonly="formState.readOnly || isDeleted"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemLoanTaxCodeID')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].loans[${activeItemIndex}].taxCodeId`
|
||||
"
|
||||
data-cy="loanTaxCodeSaleId"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].loans[${activeItemIndex}].taxCodeId`
|
||||
)
|
||||
"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].loans[${activeItemIndex}].taxCodeId`
|
||||
)
|
||||
"
|
||||
@update:name="taxCodeChange"
|
||||
></gz-pick-list>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'LoanPriceOverride') &&
|
||||
!value.userIsRestrictedType
|
||||
"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-currency
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].loans[activeItemIndex]
|
||||
.priceOverride
|
||||
"
|
||||
can-clear
|
||||
:readonly="formState.readOnly || isDeleted"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('PriceOverride')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].loans[${activeItemIndex}].priceOverride`
|
||||
"
|
||||
data-cy="loanpriceoverride"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].loans[${activeItemIndex}].priceOverride`
|
||||
)
|
||||
"
|
||||
:rules="[
|
||||
form().decimalValid(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].loans[${activeItemIndex}].priceOverride`
|
||||
)
|
||||
]"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].loans[${activeItemIndex}].priceOverride`
|
||||
)
|
||||
"
|
||||
></gz-currency>
|
||||
</v-col>
|
||||
|
||||
<v-col v-if="form().showMe(this, 'WorkOrderItemLoanNotes')" cols="12">
|
||||
<v-textarea
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].loans[activeItemIndex].notes
|
||||
"
|
||||
:readonly="formState.readOnly || value.userIsRestrictedType"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemLoanNotes')"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].loans[${activeItemIndex}].notes`
|
||||
)
|
||||
"
|
||||
:ref="`Items[${activeWoItemIndex}].loans[${activeItemIndex}].notes`"
|
||||
data-cy="loanUnitNotes"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].loans[${activeItemIndex}].notes`
|
||||
)
|
||||
"
|
||||
auto-grow
|
||||
></v-textarea>
|
||||
</v-col>
|
||||
</template>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* XXXeslint-disable */
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
export default {
|
||||
created() {
|
||||
this.setDefaultView();
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeItemIndex: null,
|
||||
selectedRow: []
|
||||
};
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
default: null,
|
||||
type: Object
|
||||
},
|
||||
pvm: {
|
||||
default: null,
|
||||
type: Object
|
||||
},
|
||||
activeWoItemIndex: {
|
||||
default: null,
|
||||
type: Number
|
||||
},
|
||||
gotoIndex: {
|
||||
default: null,
|
||||
type: Number
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
activeWoItemIndex(val, oldVal) {
|
||||
if (val != oldVal) {
|
||||
this.setDefaultView();
|
||||
}
|
||||
},
|
||||
gotoIndex(val, oldVal) {
|
||||
if (val != oldVal) {
|
||||
let gotoIndex = val;
|
||||
if (val < 0) {
|
||||
//it's a create request
|
||||
gotoIndex = this.newItem();
|
||||
}
|
||||
this.selectedRow = [{ index: gotoIndex }];
|
||||
this.activeItemIndex = gotoIndex;
|
||||
this.$nextTick(() => {
|
||||
const el = this.$refs.loantopform;
|
||||
if (el) {
|
||||
el.scrollIntoView({ behavior: "smooth" });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
loanUnitRateUnitChange(newId) {
|
||||
this.value.items[this.activeWoItemIndex].loans[
|
||||
this.activeItemIndex
|
||||
].unitOfMeasureViz = this.pvm.selectLists.loanUnitRateUnits.find(
|
||||
s => s.id == newId
|
||||
).name;
|
||||
},
|
||||
loanUnitChange(newName) {
|
||||
this.value.items[this.activeWoItemIndex].loans[
|
||||
this.activeItemIndex
|
||||
].loanUnitViz = newName;
|
||||
},
|
||||
taxCodeChange(newName) {
|
||||
this.value.items[this.activeWoItemIndex].loans[
|
||||
this.activeItemIndex
|
||||
].taxCodeViz = newName;
|
||||
},
|
||||
newItem() {
|
||||
let newIndex = this.value.items[this.activeWoItemIndex].loans.length;
|
||||
|
||||
this.value.items[this.activeWoItemIndex].loans.push({
|
||||
id: 0,
|
||||
concurrency: 0,
|
||||
notes: null,
|
||||
outDate: null,
|
||||
dueDate: null,
|
||||
returnDate: null,
|
||||
taxCodeId: null,
|
||||
loanUnitId: 0, //zero to break rule on new
|
||||
quantity: 1,
|
||||
rate: 1,
|
||||
cost: 0,
|
||||
priceOverride: null,
|
||||
isDirty: true,
|
||||
quoteItemId: this.value.items[this.activeWoItemIndex].id,
|
||||
uid: Date.now(),
|
||||
loanUnitViz: null,
|
||||
taxCodeViz: null,
|
||||
unitOfMeasureViz: null
|
||||
});
|
||||
this.$emit("change");
|
||||
this.selectedRow = [{ index: newIndex }];
|
||||
this.activeItemIndex = newIndex;
|
||||
//trigger rule breaking / validation
|
||||
this.$nextTick(() => {
|
||||
this.value.items[this.activeWoItemIndex].loans[
|
||||
this.activeItemIndex
|
||||
].loanUnitId = null;
|
||||
this.fieldValueChanged(
|
||||
`Items[${this.activeWoItemIndex}].loans[${this.activeItemIndex}].loanUnitId`
|
||||
);
|
||||
});
|
||||
return newIndex; //for create new on goto
|
||||
},
|
||||
unDeleteItem() {
|
||||
this.value.items[this.activeWoItemIndex].loans[
|
||||
this.activeItemIndex
|
||||
].deleted = false;
|
||||
this.setDefaultView();
|
||||
},
|
||||
deleteItem() {
|
||||
this.value.items[this.activeWoItemIndex].loans[
|
||||
this.activeItemIndex
|
||||
].deleted = true;
|
||||
this.setDefaultView();
|
||||
this.$emit("change");
|
||||
},
|
||||
deleteAllItem() {
|
||||
this.value.items[this.activeWoItemIndex].loans.forEach(
|
||||
z => (z.deleted = true)
|
||||
);
|
||||
this.setDefaultView();
|
||||
this.$emit("change");
|
||||
},
|
||||
setDefaultView: function() {
|
||||
//if only one record left then display it otherwise just let the datatable show what the user can click on
|
||||
if (this.value.items[this.activeWoItemIndex].loans.length == 1) {
|
||||
this.selectedRow = [{ index: 0 }];
|
||||
this.activeItemIndex = 0;
|
||||
} else {
|
||||
this.selectedRow = [];
|
||||
this.activeItemIndex = null; //select nothing in essence resetting a child selects and this one too clearing form
|
||||
}
|
||||
},
|
||||
handleRowClick: function(item) {
|
||||
this.activeItemIndex = item.index;
|
||||
this.selectedRow = [{ index: item.index }];
|
||||
},
|
||||
form() {
|
||||
return window.$gz.form;
|
||||
},
|
||||
fieldValueChanged(ref) {
|
||||
if (!this.formState.loading && !this.formState.readonly) {
|
||||
//flag this record dirty so it gets picked up by save
|
||||
this.value.items[this.activeWoItemIndex].loans[
|
||||
this.activeItemIndex
|
||||
].isDirty = true;
|
||||
window.$gz.form.fieldValueChanged(this.pvm, ref);
|
||||
}
|
||||
},
|
||||
itemRowClasses: function(item) {
|
||||
let ret = "";
|
||||
const isDeleted =
|
||||
this.value.items[this.activeWoItemIndex].loans[item.index].deleted ===
|
||||
true;
|
||||
|
||||
const hasError = this.form().childRowHasError(
|
||||
this,
|
||||
`Items[${this.activeWoItemIndex}].Loans[${item.index}].`
|
||||
);
|
||||
|
||||
if (isDeleted) {
|
||||
ret += this.form().tableRowDeletedClass();
|
||||
}
|
||||
if (hasError) {
|
||||
ret += this.form().tableRowErrorClass();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
//---
|
||||
},
|
||||
computed: {
|
||||
isDeleted: function() {
|
||||
if (
|
||||
this.value.items[this.activeWoItemIndex].loans[this.activeItemIndex] ==
|
||||
null
|
||||
) {
|
||||
this.setDefaultView();
|
||||
return true;
|
||||
}
|
||||
return (
|
||||
this.value.items[this.activeWoItemIndex].loans[this.activeItemIndex]
|
||||
.deleted === true
|
||||
);
|
||||
},
|
||||
parentDeleted: function() {
|
||||
return this.value.items[this.activeWoItemIndex].deleted === true;
|
||||
},
|
||||
|
||||
headerList: function() {
|
||||
/*
|
||||
If the column is a text, left-align it
|
||||
If the column is a number or number + unit, (or date) right-align it (like excel)
|
||||
*/
|
||||
let headers = [];
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemLoanUnit")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemLoanUnit"),
|
||||
align: "left",
|
||||
value: "loanUnitViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "WorkOrderItemLoanRate") &&
|
||||
!this.value.userIsRestrictedType
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemLoanRate"),
|
||||
align: "left",
|
||||
value: "unitOfMeasureViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "WorkOrderItemLoanQuantity") &&
|
||||
!this.value.userIsRestrictedType
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemLoanQuantity"),
|
||||
align: "right",
|
||||
value: "quantity"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemLoanOutDate")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemLoanOutDate"),
|
||||
align: "right",
|
||||
value: "outDate"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemLoanDueDate")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemLoanDueDate"),
|
||||
align: "right",
|
||||
value: "dueDate"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemLoanReturnDate")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemLoanReturnDate"),
|
||||
align: "right",
|
||||
value: "returnDate"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemLoanNotes")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemLoanNotes"),
|
||||
align: "left",
|
||||
value: "notes"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "LoanCost") &&
|
||||
this.value.userCanViewLoanerCosts &&
|
||||
!this.value.userIsRestrictedType
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("Cost"),
|
||||
align: "right",
|
||||
value: "cost"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "LoanListPrice") &&
|
||||
!this.value.userIsRestrictedType
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("ListPrice"),
|
||||
align: "right",
|
||||
value: "listPrice"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "LoanPriceOverride") &&
|
||||
!this.value.userIsRestrictedType
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("PriceOverride"),
|
||||
align: "right",
|
||||
value: "priceOverride"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "LoanPriceViz") &&
|
||||
!this.value.userIsRestrictedType
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("Price"),
|
||||
align: "right",
|
||||
value: "priceViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "WorkOrderItemLoanTaxCodeID") &&
|
||||
!this.value.userIsRestrictedType
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("Tax"),
|
||||
align: "left",
|
||||
value: "taxCodeViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "LoanNetViz") &&
|
||||
!this.value.userIsRestrictedType
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("NetPrice"),
|
||||
align: "right",
|
||||
value: "netViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "LoanTaxAViz") &&
|
||||
!this.value.userIsRestrictedType
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("TaxAAmt"),
|
||||
align: "right",
|
||||
value: "taxAViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "LoanTaxBViz") &&
|
||||
!this.value.userIsRestrictedType
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("TaxBAmt"),
|
||||
align: "right",
|
||||
value: "taxBViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "LoanLineTotalViz") &&
|
||||
!this.value.userIsRestrictedType
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("LineTotal"),
|
||||
align: "right",
|
||||
value: "lineTotalViz"
|
||||
});
|
||||
}
|
||||
return headers;
|
||||
},
|
||||
itemList: function() {
|
||||
return this.value.items[this.activeWoItemIndex].loans.map((x, i) => {
|
||||
return {
|
||||
index: i,
|
||||
id: x.id,
|
||||
loanUnitViz: x.loanUnitViz,
|
||||
unitOfMeasureViz: x.unitOfMeasureViz,
|
||||
quantity: window.$gz.locale.decimalLocalized(
|
||||
x.quantity,
|
||||
this.pvm.languageName
|
||||
),
|
||||
outDate: window.$gz.locale.utcDateToShortDateAndTimeLocalized(
|
||||
x.outDate,
|
||||
this.pvm.timeZoneName,
|
||||
this.pvm.languageName,
|
||||
this.pvm.hour12
|
||||
),
|
||||
dueDate: window.$gz.locale.utcDateToShortDateAndTimeLocalized(
|
||||
x.dueDate,
|
||||
this.pvm.timeZoneName,
|
||||
this.pvm.languageName,
|
||||
this.pvm.hour12
|
||||
),
|
||||
returnDate: window.$gz.locale.utcDateToShortDateAndTimeLocalized(
|
||||
x.returnDate,
|
||||
this.pvm.timeZoneName,
|
||||
this.pvm.languageName,
|
||||
this.pvm.hour12
|
||||
),
|
||||
notes: window.$gz.util.truncateString(
|
||||
x.notes,
|
||||
this.pvm.maxTableNotesLength
|
||||
),
|
||||
|
||||
cost: window.$gz.locale.currencyLocalized(
|
||||
x.cost,
|
||||
this.pvm.languageName,
|
||||
this.pvm.currencyName
|
||||
),
|
||||
listPrice: window.$gz.locale.currencyLocalized(
|
||||
x.listPrice,
|
||||
this.pvm.languageName,
|
||||
this.pvm.currencyName
|
||||
),
|
||||
priceViz: window.$gz.locale.currencyLocalized(
|
||||
x.priceViz,
|
||||
this.pvm.languageName,
|
||||
this.pvm.currencyName
|
||||
),
|
||||
taxCodeViz: x.taxCodeViz,
|
||||
priceOverride: window.$gz.locale.currencyLocalized(
|
||||
x.priceOverride,
|
||||
this.pvm.languageName,
|
||||
this.pvm.currencyName
|
||||
),
|
||||
netViz: window.$gz.locale.currencyLocalized(
|
||||
x.netViz,
|
||||
this.pvm.languageName,
|
||||
this.pvm.currencyName
|
||||
),
|
||||
taxAViz: window.$gz.locale.currencyLocalized(
|
||||
x.taxAViz,
|
||||
this.pvm.languageName,
|
||||
this.pvm.currencyName
|
||||
),
|
||||
taxBViz: window.$gz.locale.currencyLocalized(
|
||||
x.taxBViz,
|
||||
this.pvm.languageName,
|
||||
this.pvm.currencyName
|
||||
),
|
||||
lineTotalViz: window.$gz.locale.currencyLocalized(
|
||||
x.lineTotalViz,
|
||||
this.pvm.languageName,
|
||||
this.pvm.currencyName
|
||||
)
|
||||
};
|
||||
});
|
||||
},
|
||||
formState: function() {
|
||||
return this.pvm.formState;
|
||||
},
|
||||
formCustomTemplateKey: function() {
|
||||
return this.pvm.formCustomTemplateKey;
|
||||
},
|
||||
hasData: function() {
|
||||
return this.value.items[this.activeWoItemIndex].loans.length > 0;
|
||||
},
|
||||
hasSelection: function() {
|
||||
return this.activeItemIndex != null;
|
||||
},
|
||||
canAdd: function() {
|
||||
return this.pvm.rights.change && !this.value.userIsRestrictedType;
|
||||
},
|
||||
canDelete: function() {
|
||||
return (
|
||||
this.activeItemIndex != null &&
|
||||
this.canDeleteAll &&
|
||||
!this.value.userIsRestrictedType
|
||||
);
|
||||
},
|
||||
canDeleteAll: function() {
|
||||
return this.pvm.rights.change && !this.value.userIsRestrictedType;
|
||||
}
|
||||
|
||||
//----
|
||||
}
|
||||
};
|
||||
</script>
|
||||
1098
ayanova/src/components/quote-item-outside-services.vue
Normal file
1098
ayanova/src/components/quote-item-outside-services.vue
Normal file
File diff suppressed because it is too large
Load Diff
1129
ayanova/src/components/quote-item-parts.vue
Normal file
1129
ayanova/src/components/quote-item-parts.vue
Normal file
File diff suppressed because it is too large
Load Diff
710
ayanova/src/components/quote-item-scheduled-users.vue
Normal file
710
ayanova/src/components/quote-item-scheduled-users.vue
Normal file
@@ -0,0 +1,710 @@
|
||||
<template>
|
||||
<div v-if="value != null" class="mt-8">
|
||||
<v-row>
|
||||
<v-col cols="12">
|
||||
<v-menu offset-y max-width="600px">
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<div class="text-h6">
|
||||
<v-icon large :color="hasData ? 'primary' : null" class="mr-2"
|
||||
>$ayiUserClock</v-icon
|
||||
>
|
||||
{{ $ay.t("WorkOrderItemScheduledUserList") }}
|
||||
<v-btn v-if="!parentDeleted" large icon v-bind="attrs" v-on="on">
|
||||
<v-icon small color="primary">$ayiEllipsisV</v-icon>
|
||||
</v-btn>
|
||||
</div>
|
||||
</template>
|
||||
<v-list>
|
||||
<v-list-item v-if="canAdd" @click="newItem">
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiPlus</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{ $ay.t("New") }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item
|
||||
v-if="hasSelection && !formState.readOnly"
|
||||
@click="convertToLabor"
|
||||
>
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiHammer</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{
|
||||
$ay.t("WorkOrderConvertScheduledUserToLabor")
|
||||
}}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item
|
||||
v-if="!formState.readOnly && hasMultipleItems"
|
||||
@click="convertAllToLabor"
|
||||
>
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiHammer</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{
|
||||
$ay.t("WorkOrderConvertAllScheduledUsersToLabor")
|
||||
}}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item v-if="canDelete && isDeleted" @click="unDeleteItem">
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiTrashRestoreAlt</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{ $ay.t("Undelete") }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item v-if="canDelete && !isDeleted" @click="deleteItem">
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiTrashAlt</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{ $ay.t("SoftDelete") }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item v-if="canDeleteAll" @click="deleteAllItem">
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiDumpster</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{
|
||||
$ay.t("SoftDeleteAll")
|
||||
}}</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</v-col>
|
||||
|
||||
<template v-if="hasData">
|
||||
<!-- ################################ SCHEDULED USERS TABLE ############################### -->
|
||||
<v-col cols="12" class="mb-10">
|
||||
<v-data-table
|
||||
:headers="headerList"
|
||||
:items="itemList"
|
||||
item-key="index"
|
||||
v-model="selectedRow"
|
||||
class="elevation-1"
|
||||
disable-pagination
|
||||
disable-filtering
|
||||
disable-sort
|
||||
hide-default-footer
|
||||
data-cy="scheduledUsersTable"
|
||||
dense
|
||||
:item-class="itemRowClasses"
|
||||
@click:row="handleRowClick"
|
||||
:show-select="$vuetify.breakpoint.xs"
|
||||
single-select
|
||||
>
|
||||
</v-data-table>
|
||||
</v-col>
|
||||
</template>
|
||||
<template v-if="hasData && hasSelection">
|
||||
<div ref="scheduledusertopform"></div>
|
||||
<v-btn
|
||||
v-if="canDelete && isDeleted"
|
||||
large
|
||||
@click="unDeleteItem"
|
||||
color="primary"
|
||||
>{{ $ay.t("Undelete")
|
||||
}}<v-icon right large>$ayiTrashRestoreAlt</v-icon></v-btn
|
||||
>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemScheduledUserStartDate')"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-date-time-picker
|
||||
:label="$ay.t('WorkOrderItemScheduledUserStartDate')"
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].scheduledUsers[activeItemIndex]
|
||||
.startDate
|
||||
"
|
||||
:readonly="formState.readOnly || value.userIsRestrictedType"
|
||||
:disabled="isDeleted"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].scheduledUsers[${activeItemIndex}].startDate`
|
||||
"
|
||||
data-cy="startDate"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].scheduledUsers[${activeItemIndex}].startDate`
|
||||
)
|
||||
"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].scheduledUsers[${activeItemIndex}].startDate`
|
||||
)
|
||||
"
|
||||
></gz-date-time-picker>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemScheduledUserStopDate')"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-date-time-picker
|
||||
:label="$ay.t('WorkOrderItemScheduledUserStopDate')"
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].scheduledUsers[activeItemIndex]
|
||||
.stopDate
|
||||
"
|
||||
:readonly="formState.readOnly || value.userIsRestrictedType"
|
||||
:disabled="isDeleted"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].scheduledUsers[${activeItemIndex}].stopDate`
|
||||
"
|
||||
data-cy="stopDate"
|
||||
:rules="[
|
||||
form().datePrecedence(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].scheduledUsers[${activeItemIndex}].startDate`,
|
||||
`Items[${activeWoItemIndex}].scheduledUsers[${activeItemIndex}].stopDate`
|
||||
)
|
||||
]"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].scheduledUsers[${activeItemIndex}].stopDate`
|
||||
)
|
||||
"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].scheduledUsers[${activeItemIndex}].stopDate`
|
||||
)
|
||||
"
|
||||
></gz-date-time-picker>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'WorkOrderItemScheduledUserEstimatedQuantity')
|
||||
"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-decimal
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].scheduledUsers[activeItemIndex]
|
||||
.estimatedQuantity
|
||||
"
|
||||
:readonly="
|
||||
formState.readOnly || isDeleted || value.userIsRestrictedType
|
||||
"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemScheduledUserEstimatedQuantity')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].scheduledUsers[${activeItemIndex}].estimatedQuantity`
|
||||
"
|
||||
data-cy="scheduledUsers.EstimatedQuantity"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].scheduledUsers[${activeItemIndex}].estimatedQuantity`
|
||||
)
|
||||
"
|
||||
:rules="[
|
||||
form().decimalValid(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].scheduledUsers[${activeItemIndex}].estimatedQuantity`
|
||||
),
|
||||
form().required(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].scheduledUsers[${activeItemIndex}].estimatedQuantity`
|
||||
)
|
||||
]"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].scheduledUsers[${activeItemIndex}].estimatedQuantity`
|
||||
)
|
||||
"
|
||||
></gz-decimal>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemScheduledUserUserID')"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-pick-list
|
||||
:aya-type="$ay.ayt().User"
|
||||
variant="tech"
|
||||
:show-edit-icon="!value.userIsRestrictedType"
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].scheduledUsers[activeItemIndex]
|
||||
.userId
|
||||
"
|
||||
:readonly="
|
||||
formState.readOnly || isDeleted || value.userIsRestrictedType
|
||||
"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemScheduledUserUserID')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].scheduledUsers[${activeItemIndex}].userId`
|
||||
"
|
||||
data-cy="scheduledUsers.userid"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].scheduledUsers[${activeItemIndex}].userId`
|
||||
)
|
||||
"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].scheduledUsers[${activeItemIndex}].userId`
|
||||
)
|
||||
"
|
||||
@update:name="userChange"
|
||||
></gz-pick-list>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemScheduledUserServiceRateID')"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-pick-list
|
||||
:aya-type="$ay.ayt().ServiceRate"
|
||||
:variant="'contractid:' + value.contractId"
|
||||
:show-edit-icon="!value.userIsRestrictedType"
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].scheduledUsers[activeItemIndex]
|
||||
.serviceRateId
|
||||
"
|
||||
:readonly="
|
||||
formState.readOnly || isDeleted || value.userIsRestrictedType
|
||||
"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemScheduledUserServiceRateID')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].scheduledUsers[${activeItemIndex}].serviceRateId`
|
||||
"
|
||||
data-cy="scheduledUsers.serviceRateId"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].scheduledUsers[${activeItemIndex}].serviceRateId`
|
||||
)
|
||||
"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].scheduledUsers[${activeItemIndex}].serviceRateId`
|
||||
)
|
||||
"
|
||||
@update:name="rateChange"
|
||||
></gz-pick-list>
|
||||
</v-col>
|
||||
</template>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* XXXeslint-disable */
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
export default {
|
||||
created() {
|
||||
this.setDefaultView();
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeItemIndex: null,
|
||||
selectedRow: []
|
||||
};
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
default: null,
|
||||
type: Object
|
||||
},
|
||||
pvm: {
|
||||
default: null,
|
||||
type: Object
|
||||
},
|
||||
activeWoItemIndex: {
|
||||
default: null,
|
||||
type: Number
|
||||
},
|
||||
gotoIndex: {
|
||||
default: null,
|
||||
type: Number
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
activeWoItemIndex(val, oldVal) {
|
||||
if (val != oldVal) {
|
||||
this.setDefaultView();
|
||||
}
|
||||
},
|
||||
gotoIndex(val, oldVal) {
|
||||
if (val != oldVal) {
|
||||
let gotoIndex = val;
|
||||
if (val < 0) {
|
||||
//it's a create request
|
||||
gotoIndex = this.newItem();
|
||||
}
|
||||
this.selectedRow = [{ index: gotoIndex }];
|
||||
this.activeItemIndex = gotoIndex;
|
||||
this.$nextTick(() => {
|
||||
const el = this.$refs.scheduledusertopform;
|
||||
if (el) {
|
||||
el.scrollIntoView({ behavior: "smooth" });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
convertAllToLabor() {
|
||||
this.value.items[this.activeWoItemIndex].scheduledUsers.forEach(z => {
|
||||
this.doConvertToLabor(z);
|
||||
});
|
||||
},
|
||||
convertToLabor() {
|
||||
this.doConvertToLabor(
|
||||
this.value.items[this.activeWoItemIndex].scheduledUsers[
|
||||
this.activeItemIndex
|
||||
]
|
||||
);
|
||||
},
|
||||
doConvertToLabor(s) {
|
||||
this.value.items[this.activeWoItemIndex].labors.push({
|
||||
id: 0,
|
||||
concurrency: 0,
|
||||
userId: s.userId,
|
||||
serviceStartDate: s.startDate,
|
||||
serviceStopDate: s.stopDate,
|
||||
serviceRateId: s.serviceRateId,
|
||||
serviceDetails: null,
|
||||
serviceRateQuantity: s.estimatedQuantity,
|
||||
noChargeQuantity: 0,
|
||||
taxCodeSaleId: null,
|
||||
price: 0,
|
||||
priceOverride: null,
|
||||
isDirty: true,
|
||||
quoteItemId: this.value.items[this.activeWoItemIndex].id,
|
||||
uid: Date.now(),
|
||||
userViz: s.userViz,
|
||||
serviceRateViz: s.serviceRateViz,
|
||||
taxCodeViz: null
|
||||
});
|
||||
this.$emit("change");
|
||||
},
|
||||
userChange(newName) {
|
||||
this.value.items[this.activeWoItemIndex].scheduledUsers[
|
||||
this.activeItemIndex
|
||||
].userViz = newName;
|
||||
},
|
||||
rateChange(newName) {
|
||||
this.value.items[this.activeWoItemIndex].scheduledUsers[
|
||||
this.activeItemIndex
|
||||
].serviceRateViz = newName;
|
||||
},
|
||||
newItem() {
|
||||
let newIndex = this.value.items[this.activeWoItemIndex].scheduledUsers
|
||||
.length;
|
||||
|
||||
this.value.items[this.activeWoItemIndex].scheduledUsers.push({
|
||||
id: 0,
|
||||
concurrency: 0,
|
||||
userId: this.$store.getters.isScheduleableUser
|
||||
? this.$store.state.userId
|
||||
: null,
|
||||
estimatedQuantity: 0,
|
||||
startDate: null,
|
||||
stopDate: null,
|
||||
serviceRateId: null,
|
||||
isDirty: true,
|
||||
quoteItemId: this.value.items[this.activeWoItemIndex].id,
|
||||
uid: Date.now(),
|
||||
userViz: this.$store.getters.isScheduleableUser
|
||||
? this.$store.state.userName
|
||||
: null,
|
||||
serviceRateViz: null
|
||||
});
|
||||
this.$emit("change");
|
||||
this.selectedRow = [{ index: newIndex }];
|
||||
this.activeItemIndex = newIndex;
|
||||
return newIndex; //for create new on goto
|
||||
},
|
||||
unDeleteItem() {
|
||||
this.value.items[this.activeWoItemIndex].scheduledUsers[
|
||||
this.activeItemIndex
|
||||
].deleted = false;
|
||||
this.setDefaultView();
|
||||
},
|
||||
deleteItem() {
|
||||
this.value.items[this.activeWoItemIndex].scheduledUsers[
|
||||
this.activeItemIndex
|
||||
].deleted = true;
|
||||
this.setDefaultView();
|
||||
this.$emit("change");
|
||||
},
|
||||
deleteAllItem() {
|
||||
this.value.items[this.activeWoItemIndex].scheduledUsers.forEach(
|
||||
z => (z.deleted = true)
|
||||
);
|
||||
this.setDefaultView();
|
||||
this.$emit("change");
|
||||
},
|
||||
setDefaultView: function() {
|
||||
//if only one record left then display it otherwise just let the datatable show what the user can click on
|
||||
if (this.value.items[this.activeWoItemIndex].scheduledUsers.length == 1) {
|
||||
this.selectedRow = [{ index: 0 }];
|
||||
this.activeItemIndex = 0;
|
||||
} else {
|
||||
this.selectedRow = [];
|
||||
this.activeItemIndex = null; //select nothing in essence resetting a child selects and this one too clearing form
|
||||
}
|
||||
},
|
||||
handleRowClick: function(item) {
|
||||
this.activeItemIndex = item.index;
|
||||
this.selectedRow = [{ index: item.index }];
|
||||
},
|
||||
form() {
|
||||
return window.$gz.form;
|
||||
},
|
||||
fieldValueChanged(ref) {
|
||||
if (!this.formState.loading && !this.formState.readonly) {
|
||||
//flag this record dirty so it gets picked up by save
|
||||
this.value.items[this.activeWoItemIndex].scheduledUsers[
|
||||
this.activeItemIndex
|
||||
].isDirty = true;
|
||||
window.$gz.form.fieldValueChanged(this.pvm, ref);
|
||||
//------- SPECIAL HANDLING OF CHANGES -----------
|
||||
const isNew =
|
||||
this.value.items[this.activeWoItemIndex].scheduledUsers[
|
||||
this.activeItemIndex
|
||||
].id == 0;
|
||||
|
||||
//Auto calculate dates / quantities / global defaults
|
||||
const dStart = this.value.items[this.activeWoItemIndex].scheduledUsers[
|
||||
this.activeItemIndex
|
||||
].startDate;
|
||||
const dStop = this.value.items[this.activeWoItemIndex].scheduledUsers[
|
||||
this.activeItemIndex
|
||||
].stopDate;
|
||||
if (ref.includes("startDate") && dStart != null) {
|
||||
this.handleStartDateChange(isNew, dStart, dStop);
|
||||
}
|
||||
if (ref.includes("stopDate") && dStop != null) {
|
||||
this.handleStopDateChange(isNew, dStart, dStop);
|
||||
}
|
||||
//------------------------------------------------------
|
||||
}
|
||||
},
|
||||
handleStartDateChange: function(isNew, dStart, dStop) {
|
||||
const globalMinutes =
|
||||
window.$gz.store.state.globalSettings.workLaborScheduleDefaultMinutes;
|
||||
|
||||
if (isNew && dStop == null) {
|
||||
if (globalMinutes != 0) {
|
||||
//set stop date based on start date and global minutes
|
||||
this.value.items[this.activeWoItemIndex].scheduledUsers[
|
||||
this.activeItemIndex
|
||||
].stopDate = window.$gz.locale.addMinutesToUTC8601String(
|
||||
dStart,
|
||||
globalMinutes
|
||||
);
|
||||
|
||||
this.value.items[this.activeWoItemIndex].scheduledUsers[
|
||||
this.activeItemIndex
|
||||
].estimatedQuantity = globalMinutes;
|
||||
}
|
||||
} else {
|
||||
//Existing record or both dates filled, just update quantity
|
||||
if (dStop != null) {
|
||||
this.value.items[this.activeWoItemIndex].scheduledUsers[
|
||||
this.activeItemIndex
|
||||
].estimatedQuantity = window.$gz.locale.diffHoursFromUTC8601String(
|
||||
dStart,
|
||||
dStop
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
handleStopDateChange: function(isNew, dStart, dStop) {
|
||||
const globalMinutes =
|
||||
window.$gz.store.state.globalSettings.workLaborScheduleDefaultMinutes;
|
||||
|
||||
if (isNew && dStart == null) {
|
||||
if (globalMinutes != 0) {
|
||||
//set start date based on stop date and global minutes
|
||||
this.value.items[this.activeWoItemIndex].scheduledUsers[
|
||||
this.activeItemIndex
|
||||
].startDate = window.$gz.locale.addMinutesToUTC8601String(
|
||||
dStop,
|
||||
0 - globalMinutes
|
||||
);
|
||||
|
||||
this.value.items[this.activeWoItemIndex].scheduledUsers[
|
||||
this.activeItemIndex
|
||||
].estimatedQuantity = globalMinutes;
|
||||
}
|
||||
} else {
|
||||
//Existing record or both dates filled, just update quantity
|
||||
if (dStart != null) {
|
||||
this.value.items[this.activeWoItemIndex].scheduledUsers[
|
||||
this.activeItemIndex
|
||||
].estimatedQuantity = window.$gz.locale.diffHoursFromUTC8601String(
|
||||
dStart,
|
||||
dStop
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
itemRowClasses: function(item) {
|
||||
let ret = "";
|
||||
const isDeleted =
|
||||
this.value.items[this.activeWoItemIndex].scheduledUsers[item.index]
|
||||
.deleted === true;
|
||||
|
||||
const hasError = this.form().childRowHasError(
|
||||
this,
|
||||
`Items[${this.activeWoItemIndex}].ScheduledUsers[${item.index}].`
|
||||
);
|
||||
|
||||
if (isDeleted) {
|
||||
ret += this.form().tableRowDeletedClass();
|
||||
}
|
||||
if (hasError) {
|
||||
ret += this.form().tableRowErrorClass();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isDeleted: function() {
|
||||
if (
|
||||
this.value.items[this.activeWoItemIndex].scheduledUsers[
|
||||
this.activeItemIndex
|
||||
] == null
|
||||
) {
|
||||
this.setDefaultView();
|
||||
return true;
|
||||
}
|
||||
return (
|
||||
this.value.items[this.activeWoItemIndex].scheduledUsers[
|
||||
this.activeItemIndex
|
||||
].deleted === true
|
||||
);
|
||||
},
|
||||
parentDeleted: function() {
|
||||
return this.value.items[this.activeWoItemIndex].deleted === true;
|
||||
},
|
||||
|
||||
headerList: function() {
|
||||
/*
|
||||
If the column is a text, left-align it
|
||||
If the column is a number or number + unit, (or date) right-align it (like excel)
|
||||
*/
|
||||
let headers = [];
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemScheduledUserStartDate")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemScheduledUserStartDate"),
|
||||
align: "right",
|
||||
value: "startDate"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemScheduledUserStopDate")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemScheduledUserStopDate"),
|
||||
align: "right",
|
||||
value: "stopDate"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "WorkOrderItemScheduledUserEstimatedQuantity")
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemScheduledUserEstimatedQuantity"),
|
||||
align: "right",
|
||||
value: "estimatedQuantity"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemScheduledUserUserID")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemScheduledUserUserID"),
|
||||
align: "left",
|
||||
value: "userViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemScheduledUserServiceRateID")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemScheduledUserServiceRateID"),
|
||||
align: "left",
|
||||
value: "serviceRateViz"
|
||||
});
|
||||
}
|
||||
|
||||
return headers;
|
||||
},
|
||||
itemList: function() {
|
||||
return this.value.items[this.activeWoItemIndex].scheduledUsers.map(
|
||||
(x, i) => {
|
||||
return {
|
||||
index: i,
|
||||
id: x.id,
|
||||
startDate: window.$gz.locale.utcDateToShortDateAndTimeLocalized(
|
||||
x.startDate,
|
||||
this.pvm.timeZoneName,
|
||||
this.pvm.languageName,
|
||||
this.pvm.hour12
|
||||
),
|
||||
stopDate: window.$gz.locale.utcDateToShortDateAndTimeLocalized(
|
||||
x.stopDate,
|
||||
this.pvm.timeZoneName,
|
||||
this.pvm.languageName,
|
||||
this.pvm.hour12
|
||||
),
|
||||
estimatedQuantity: window.$gz.locale.decimalLocalized(
|
||||
x.estimatedQuantity,
|
||||
this.pvm.languageName
|
||||
),
|
||||
userViz: x.userViz,
|
||||
serviceRateViz: x.serviceRateViz
|
||||
};
|
||||
}
|
||||
);
|
||||
},
|
||||
formState: function() {
|
||||
return this.pvm.formState;
|
||||
},
|
||||
formCustomTemplateKey: function() {
|
||||
return this.pvm.formCustomTemplateKey;
|
||||
},
|
||||
hasData: function() {
|
||||
return this.value.items[this.activeWoItemIndex].scheduledUsers.length > 0;
|
||||
},
|
||||
hasSelection: function() {
|
||||
return this.activeItemIndex != null;
|
||||
},
|
||||
canAdd: function() {
|
||||
return this.pvm.rights.change && !this.value.userIsRestrictedType;
|
||||
},
|
||||
canDelete: function() {
|
||||
return (
|
||||
this.activeItemIndex != null &&
|
||||
this.canDeleteAll &&
|
||||
!this.value.userIsRestrictedType
|
||||
);
|
||||
},
|
||||
canDeleteAll: function() {
|
||||
return this.pvm.rights.change && !this.value.userIsRestrictedType;
|
||||
},
|
||||
hasMultipleItems: function() {
|
||||
return this.value.items[this.activeWoItemIndex].scheduledUsers.length > 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
644
ayanova/src/components/quote-item-tasks.vue
Normal file
644
ayanova/src/components/quote-item-tasks.vue
Normal file
@@ -0,0 +1,644 @@
|
||||
<template>
|
||||
<div v-if="value != null" class="mt-8">
|
||||
<v-row>
|
||||
<v-col cols="12">
|
||||
<v-menu offset-y max-width="600px">
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<div class="text-h6">
|
||||
<v-icon large :color="hasData ? 'primary' : null" class="mr-2"
|
||||
>$ayiTasks</v-icon
|
||||
>
|
||||
{{ $ay.t("WorkOrderItemTasks") }}
|
||||
<v-btn v-if="!parentDeleted" large icon v-bind="attrs" v-on="on">
|
||||
<v-icon small color="primary">$ayiEllipsisV</v-icon>
|
||||
</v-btn>
|
||||
</div>
|
||||
</template>
|
||||
<v-list>
|
||||
<v-list-item v-if="canAdd" @click="newItem">
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiPlus</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{ $ay.t("New") }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item v-if="canAdd" @click="taskGroupDialog = true">
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiTasks</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{ $ay.t("TaskGroup") }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item v-if="canDelete && isDeleted" @click="unDeleteItem">
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiTrashRestoreAlt</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{ $ay.t("Undelete") }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item v-if="canDelete && !isDeleted" @click="deleteItem">
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiTrashAlt</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{ $ay.t("SoftDelete") }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item v-if="canDeleteAll" @click="deleteAllItem">
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiDumpster</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{
|
||||
$ay.t("SoftDeleteAll")
|
||||
}}</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</v-col>
|
||||
|
||||
<template v-if="hasData">
|
||||
<!-- ############################################################### -->
|
||||
<v-col cols="12" class="mb-10">
|
||||
<v-data-table
|
||||
:headers="headerList"
|
||||
:items="itemList"
|
||||
item-key="index"
|
||||
v-model="selectedRow"
|
||||
class="elevation-1"
|
||||
disable-pagination
|
||||
disable-filtering
|
||||
disable-sort
|
||||
hide-default-footer
|
||||
data-cy="expensesTable"
|
||||
dense
|
||||
:item-class="itemRowClasses"
|
||||
@click:row="handleRowClick"
|
||||
:show-select="$vuetify.breakpoint.xs"
|
||||
single-select
|
||||
>
|
||||
</v-data-table>
|
||||
</v-col>
|
||||
</template>
|
||||
<template v-if="hasData && hasSelection">
|
||||
<div ref="tasktopform"></div>
|
||||
<v-btn
|
||||
v-if="canDelete && isDeleted"
|
||||
large
|
||||
@click="unDeleteItem"
|
||||
color="primary"
|
||||
>{{ $ay.t("Undelete")
|
||||
}}<v-icon right large>$ayiTrashRestoreAlt</v-icon></v-btn
|
||||
>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemTaskSequence')"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<v-text-field
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].tasks[activeItemIndex].sequence
|
||||
"
|
||||
:readonly="formState.readOnly || value.userIsRestrictedType"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('Sequence')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].tasks[${activeItemIndex}].sequence`
|
||||
"
|
||||
:rules="[
|
||||
form().integerValid(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].tasks[${activeItemIndex}].sequence`
|
||||
)
|
||||
]"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].tasks[${activeItemIndex}].sequence`
|
||||
)
|
||||
"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].tasks[${activeItemIndex}].sequence`
|
||||
)
|
||||
"
|
||||
type="number"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(
|
||||
this,
|
||||
'WorkOrderItemTaskWorkOrderItemTaskCompletionType'
|
||||
)
|
||||
"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<v-select
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].tasks[activeItemIndex].status
|
||||
"
|
||||
:items="pvm.selectLists.woItemTaskCompletionTypes"
|
||||
item-text="name"
|
||||
item-value="id"
|
||||
:readonly="formState.readOnly || isDeleted"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemTaskWorkOrderItemTaskCompletionType')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].tasks[${activeItemIndex}].status`
|
||||
"
|
||||
data-cy="usertype"
|
||||
:rules="[
|
||||
form().integerValid(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].tasks[${activeItemIndex}].status`
|
||||
)
|
||||
]"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].tasks[${activeItemIndex}].status`
|
||||
)
|
||||
"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].tasks[${activeItemIndex}].status`
|
||||
)
|
||||
"
|
||||
@change="statusChange"
|
||||
></v-select>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemTaskUser')"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-pick-list
|
||||
:aya-type="$ay.ayt().User"
|
||||
variant="tech"
|
||||
:show-edit-icon="!value.userIsRestrictedType"
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].tasks[activeItemIndex]
|
||||
.completedByUserId
|
||||
"
|
||||
:readonly="
|
||||
formState.readOnly || isDeleted || value.userIsRestrictedType
|
||||
"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemTaskUser')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].tasks[${activeItemIndex}].completedByUserId`
|
||||
"
|
||||
data-cy="expenseUser"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].tasks[${activeItemIndex}].completedByUserId`
|
||||
)
|
||||
"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].tasks[${activeItemIndex}].completedByUserId`
|
||||
)
|
||||
"
|
||||
@update:name="userChange"
|
||||
></gz-pick-list>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemTaskCompletedDate')"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-date-time-picker
|
||||
:label="$ay.t('WorkOrderItemTaskCompletedDate')"
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].tasks[activeItemIndex]
|
||||
.completedDate
|
||||
"
|
||||
:readonly="formState.readOnly"
|
||||
:disabled="isDeleted"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].tasks[${activeItemIndex}].completedDate`
|
||||
"
|
||||
data-cy="travelCompletedDate"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].tasks[${activeItemIndex}].completedDate`
|
||||
)
|
||||
"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].tasks[${activeItemIndex}].completedDate`
|
||||
)
|
||||
"
|
||||
></gz-date-time-picker>
|
||||
</v-col>
|
||||
|
||||
<v-col v-if="form().showMe(this, 'WorkOrderItemTaskTaskID')" cols="12">
|
||||
<v-textarea
|
||||
v-model="value.items[activeWoItemIndex].tasks[activeItemIndex].task"
|
||||
:readonly="formState.readOnly || value.userIsRestrictedType"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemTaskTaskID')"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].tasks[${activeItemIndex}].task`
|
||||
)
|
||||
"
|
||||
:rules="[
|
||||
form().required(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].tasks[${activeItemIndex}].task`
|
||||
)
|
||||
]"
|
||||
:ref="`Items[${activeWoItemIndex}].tasks[${activeItemIndex}].task`"
|
||||
data-cy="task"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].tasks[${activeItemIndex}].task`
|
||||
)
|
||||
"
|
||||
auto-grow
|
||||
></v-textarea>
|
||||
</v-col>
|
||||
</template>
|
||||
</v-row>
|
||||
<!-- ################################################################################-->
|
||||
<!-- ########################## GROUP SELECTOR FORM ###############################-->
|
||||
<!-- ################################################################################-->
|
||||
<template>
|
||||
<v-row justify="center">
|
||||
<v-dialog max-width="600px" v-model="taskGroupDialog">
|
||||
<v-card>
|
||||
<v-card-title> </v-card-title>
|
||||
<v-card-text>
|
||||
<gz-pick-list
|
||||
:aya-type="$ay.ayt().TaskGroup"
|
||||
show-edit-icon
|
||||
v-model="selectedTaskGroup"
|
||||
:label="$ay.t('TaskGroupList')"
|
||||
ref="selectedTaskGroup"
|
||||
data-cy="selectedTaskGroup"
|
||||
></gz-pick-list>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-btn text @click="taskGroupDialog = false" color="primary">{{
|
||||
$ay.t("Cancel")
|
||||
}}</v-btn>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn
|
||||
:disabled="selectedTaskGroup == null"
|
||||
color="primary"
|
||||
text
|
||||
@click="addTaskGroup()"
|
||||
class="ml-4"
|
||||
>{{ $ay.t("Add") }}</v-btn
|
||||
>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</v-row>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* XXXeslint-disable */
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
export default {
|
||||
created() {
|
||||
this.setDefaultView();
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeItemIndex: null,
|
||||
selectedRow: [],
|
||||
taskGroupDialog: false,
|
||||
selectedTaskGroup: null
|
||||
};
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
default: null,
|
||||
type: Object
|
||||
},
|
||||
pvm: {
|
||||
default: null,
|
||||
type: Object
|
||||
},
|
||||
activeWoItemIndex: {
|
||||
default: null,
|
||||
type: Number
|
||||
},
|
||||
gotoIndex: {
|
||||
default: null,
|
||||
type: Number
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
activeWoItemIndex(val, oldVal) {
|
||||
if (val != oldVal) {
|
||||
this.setDefaultView();
|
||||
}
|
||||
},
|
||||
gotoIndex(val, oldVal) {
|
||||
if (val != oldVal) {
|
||||
let gotoIndex = val;
|
||||
if (val < 0) {
|
||||
//it's a create request
|
||||
gotoIndex = this.newItem();
|
||||
}
|
||||
this.selectedRow = [{ index: gotoIndex }];
|
||||
this.activeItemIndex = gotoIndex;
|
||||
this.$nextTick(() => {
|
||||
const el = this.$refs.tasktopform;
|
||||
if (el) {
|
||||
el.scrollIntoView({ behavior: "smooth" });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async addTaskGroup() {
|
||||
let res = await window.$gz.api.get(
|
||||
`task-group/${this.selectedTaskGroup}`
|
||||
);
|
||||
if (res.data && res.data.items) {
|
||||
let newIndex = this.value.items[this.activeWoItemIndex].tasks.length;
|
||||
let incompleteViz = this.pvm.selectLists.woItemTaskCompletionTypes.find(
|
||||
s => s.id == 1 //incomplete
|
||||
).name;
|
||||
res.data.items.forEach(z => {
|
||||
newIndex++;
|
||||
|
||||
this.value.items[this.activeWoItemIndex].tasks.push({
|
||||
id: 0,
|
||||
concurrency: 0,
|
||||
sequence: newIndex,
|
||||
task: z.task,
|
||||
status: 1, //incomplete==1
|
||||
statusViz: incompleteViz,
|
||||
completedByUserId: null,
|
||||
completedDate: null,
|
||||
isDirty: true,
|
||||
quoteItemId: this.value.items[this.activeWoItemIndex].id,
|
||||
uid: Date.now(),
|
||||
completedByUserViz: null
|
||||
});
|
||||
});
|
||||
this.$emit("change");
|
||||
this.selectedRow = [{ index: newIndex }];
|
||||
this.activeItemIndex = newIndex;
|
||||
}
|
||||
|
||||
this.taskGroupDialog = false;
|
||||
},
|
||||
userChange(newName) {
|
||||
this.value.items[this.activeWoItemIndex].tasks[
|
||||
this.activeItemIndex
|
||||
].completedByUserViz = newName;
|
||||
},
|
||||
statusChange(newStatusId) {
|
||||
this.value.items[this.activeWoItemIndex].tasks[
|
||||
this.activeItemIndex
|
||||
].statusViz = this.pvm.selectLists.woItemTaskCompletionTypes.find(
|
||||
s => s.id == newStatusId
|
||||
).name;
|
||||
|
||||
//completed date auto set by status change if not a todo
|
||||
if (newStatusId != 1) {
|
||||
this.value.items[this.activeWoItemIndex].tasks[
|
||||
this.activeItemIndex
|
||||
].completedDate = window.$gz.locale.nowUTC8601String();
|
||||
} else {
|
||||
this.value.items[this.activeWoItemIndex].tasks[
|
||||
this.activeItemIndex
|
||||
].completedDate = null;
|
||||
}
|
||||
},
|
||||
newItem() {
|
||||
let newIndex = this.value.items[this.activeWoItemIndex].tasks.length;
|
||||
this.value.items[this.activeWoItemIndex].tasks.push({
|
||||
id: 0,
|
||||
concurrency: 0,
|
||||
sequence: newIndex + 1, //indexes are zero based but sequences are visible to user so 1 based
|
||||
task: undefined, //to trigger validation on new
|
||||
status: 1, //incomplete==1
|
||||
completedByUserId: null,
|
||||
completedDate: null,
|
||||
isDirty: true,
|
||||
quoteItemId: this.value.items[this.activeWoItemIndex].id,
|
||||
uid: Date.now(),
|
||||
completedByUserViz: null,
|
||||
statusViz: null
|
||||
});
|
||||
this.$emit("change");
|
||||
this.selectedRow = [{ index: newIndex }];
|
||||
this.activeItemIndex = newIndex;
|
||||
//trigger rule breaking / validation
|
||||
this.$nextTick(() => {
|
||||
this.value.items[this.activeWoItemIndex].tasks[
|
||||
this.activeItemIndex
|
||||
].task = null;
|
||||
this.fieldValueChanged(
|
||||
`Items[${this.activeWoItemIndex}].tasks[${this.activeItemIndex}].task`
|
||||
);
|
||||
});
|
||||
return newIndex; //for create new on goto
|
||||
},
|
||||
unDeleteItem() {
|
||||
this.value.items[this.activeWoItemIndex].tasks[
|
||||
this.activeItemIndex
|
||||
].deleted = false;
|
||||
this.setDefaultView();
|
||||
},
|
||||
deleteItem() {
|
||||
this.value.items[this.activeWoItemIndex].tasks[
|
||||
this.activeItemIndex
|
||||
].deleted = true;
|
||||
this.setDefaultView();
|
||||
this.$emit("change");
|
||||
},
|
||||
deleteAllItem() {
|
||||
this.value.items[this.activeWoItemIndex].tasks.forEach(
|
||||
z => (z.deleted = true)
|
||||
);
|
||||
this.setDefaultView();
|
||||
this.$emit("change");
|
||||
},
|
||||
setDefaultView: function() {
|
||||
//if only one record left then display it otherwise just let the datatable show what the user can click on
|
||||
if (this.value.items[this.activeWoItemIndex].tasks.length == 1) {
|
||||
this.selectedRow = [{ index: 0 }];
|
||||
this.activeItemIndex = 0;
|
||||
} else {
|
||||
this.selectedRow = [];
|
||||
this.activeItemIndex = null; //select nothing in essence resetting a child selects and this one too clearing form
|
||||
}
|
||||
},
|
||||
handleRowClick: function(item) {
|
||||
this.activeItemIndex = item.index;
|
||||
this.selectedRow = [{ index: item.index }];
|
||||
},
|
||||
form() {
|
||||
return window.$gz.form;
|
||||
},
|
||||
fieldValueChanged(ref) {
|
||||
if (!this.formState.loading && !this.formState.readonly) {
|
||||
//flag this record dirty so it gets picked up by save
|
||||
this.value.items[this.activeWoItemIndex].tasks[
|
||||
this.activeItemIndex
|
||||
].isDirty = true;
|
||||
window.$gz.form.fieldValueChanged(this.pvm, ref);
|
||||
}
|
||||
},
|
||||
itemRowClasses: function(item) {
|
||||
let ret = "";
|
||||
const isDeleted =
|
||||
this.value.items[this.activeWoItemIndex].tasks[item.index].deleted ===
|
||||
true;
|
||||
|
||||
const hasError = this.form().childRowHasError(
|
||||
this,
|
||||
`Items[${this.activeWoItemIndex}].Tasks[${item.index}].`
|
||||
);
|
||||
|
||||
if (isDeleted) {
|
||||
ret += this.form().tableRowDeletedClass();
|
||||
}
|
||||
if (hasError) {
|
||||
ret += this.form().tableRowErrorClass();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isDeleted: function() {
|
||||
if (
|
||||
this.value.items[this.activeWoItemIndex].tasks[this.activeItemIndex] ==
|
||||
null
|
||||
) {
|
||||
this.setDefaultView();
|
||||
return true;
|
||||
}
|
||||
return (
|
||||
this.value.items[this.activeWoItemIndex].tasks[this.activeItemIndex]
|
||||
.deleted === true
|
||||
);
|
||||
},
|
||||
parentDeleted: function() {
|
||||
return this.value.items[this.activeWoItemIndex].deleted === true;
|
||||
},
|
||||
|
||||
headerList: function() {
|
||||
/*
|
||||
If the column is a text, left-align it
|
||||
If the column is a number or number + unit, (or date) right-align it (like excel)
|
||||
*/
|
||||
let headers = [];
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemTaskSequence")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("Sequence"),
|
||||
align: "left",
|
||||
value: "sequence"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemTaskTaskID")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemTaskTaskID"),
|
||||
align: "start",
|
||||
value: "task"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemTaskUser")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemTaskUser"),
|
||||
align: "start",
|
||||
value: "completedByUserViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(
|
||||
this,
|
||||
"WorkOrderItemTaskWorkOrderItemTaskCompletionType"
|
||||
)
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemTaskWorkOrderItemTaskCompletionType"),
|
||||
align: "start",
|
||||
value: "statusViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemTaskCompletedDate")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemTaskCompletedDate"),
|
||||
align: "right",
|
||||
value: "completedDate"
|
||||
});
|
||||
}
|
||||
return headers;
|
||||
},
|
||||
itemList: function() {
|
||||
return this.value.items[this.activeWoItemIndex].tasks
|
||||
.map((x, i) => {
|
||||
return {
|
||||
index: i,
|
||||
id: x.id,
|
||||
sequence: x.sequence,
|
||||
task: x.task,
|
||||
completedByUserViz: x.completedByUserViz,
|
||||
statusViz: x.statusViz,
|
||||
completedDate: window.$gz.locale.utcDateToShortDateAndTimeLocalized(
|
||||
x.completedDate,
|
||||
this.pvm.timeZoneName,
|
||||
this.pvm.languageName,
|
||||
this.pvm.hour12
|
||||
)
|
||||
};
|
||||
})
|
||||
.sort((a, b) => a.sequence - b.sequence);
|
||||
},
|
||||
formState: function() {
|
||||
return this.pvm.formState;
|
||||
},
|
||||
formCustomTemplateKey: function() {
|
||||
return this.pvm.formCustomTemplateKey;
|
||||
},
|
||||
hasData: function() {
|
||||
return this.value.items[this.activeWoItemIndex].tasks.length > 0;
|
||||
},
|
||||
hasSelection: function() {
|
||||
return this.activeItemIndex != null;
|
||||
},
|
||||
canAdd: function() {
|
||||
return this.pvm.rights.change && !this.value.userIsRestrictedType;
|
||||
},
|
||||
canDelete: function() {
|
||||
return (
|
||||
this.activeItemIndex != null &&
|
||||
this.canDeleteAll &&
|
||||
!this.value.userIsRestrictedType
|
||||
);
|
||||
},
|
||||
canDeleteAll: function() {
|
||||
return this.pvm.rights.change && !this.value.userIsRestrictedType;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
976
ayanova/src/components/quote-item-travels.vue
Normal file
976
ayanova/src/components/quote-item-travels.vue
Normal file
@@ -0,0 +1,976 @@
|
||||
<template>
|
||||
<div v-if="value != null" class="mt-8">
|
||||
<v-row>
|
||||
<v-col cols="12">
|
||||
<v-menu offset-y max-width="600px">
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<div class="text-h6">
|
||||
<v-icon large :color="hasData ? 'primary' : null" class="mr-2"
|
||||
>$ayiTruckMonster</v-icon
|
||||
>
|
||||
{{ $ay.t("WorkOrderItemTravelList") }}
|
||||
<v-btn v-if="!parentDeleted" large icon v-bind="attrs" v-on="on">
|
||||
<v-icon small color="primary">$ayiEllipsisV</v-icon>
|
||||
</v-btn>
|
||||
</div>
|
||||
</template>
|
||||
<v-list>
|
||||
<v-list-item v-if="canAdd" @click="newItem">
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiPlus</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{ $ay.t("New") }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item v-if="canDelete && isDeleted" @click="unDeleteItem">
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiTrashRestoreAlt</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{ $ay.t("Undelete") }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item v-if="canDelete && !isDeleted" @click="deleteItem">
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiTrashAlt</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{ $ay.t("SoftDelete") }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item v-if="canDeleteAll" @click="deleteAllItem">
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiDumpster</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{
|
||||
$ay.t("SoftDeleteAll")
|
||||
}}</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</v-col>
|
||||
|
||||
<template v-if="hasData">
|
||||
<!-- ############################################################### -->
|
||||
<v-col cols="12" class="mb-10">
|
||||
<v-data-table
|
||||
:headers="headerList"
|
||||
:items="itemList"
|
||||
item-key="index"
|
||||
v-model="selectedRow"
|
||||
class="elevation-1"
|
||||
disable-pagination
|
||||
disable-filtering
|
||||
disable-sort
|
||||
hide-default-footer
|
||||
data-cy="travelsTable"
|
||||
dense
|
||||
:item-class="itemRowClasses"
|
||||
@click:row="handleRowClick"
|
||||
:show-select="$vuetify.breakpoint.xs"
|
||||
single-select
|
||||
>
|
||||
</v-data-table>
|
||||
</v-col>
|
||||
</template>
|
||||
<template v-if="hasData && hasSelection">
|
||||
<div ref="traveltopform"></div>
|
||||
<v-btn
|
||||
v-if="canDelete && isDeleted"
|
||||
large
|
||||
@click="unDeleteItem"
|
||||
color="primary"
|
||||
>{{ $ay.t("Undelete")
|
||||
}}<v-icon right large>$ayiTrashRestoreAlt</v-icon></v-btn
|
||||
>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemTravelStartDate')"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-date-time-picker
|
||||
:label="$ay.t('WorkOrderItemTravelStartDate')"
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].travels[activeItemIndex]
|
||||
.travelStartDate
|
||||
"
|
||||
:readonly="formState.readOnly"
|
||||
:disabled="isDeleted"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].travelStartDate`
|
||||
"
|
||||
data-cy="travelStartDate"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].travelStartDate`
|
||||
)
|
||||
"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].travelStartDate`
|
||||
)
|
||||
"
|
||||
></gz-date-time-picker>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemTravelStopDate')"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-date-time-picker
|
||||
:label="$ay.t('WorkOrderItemTravelStopDate')"
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].travels[activeItemIndex]
|
||||
.travelStopDate
|
||||
"
|
||||
:readonly="formState.readOnly"
|
||||
:disabled="isDeleted"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].travelStopDate`
|
||||
"
|
||||
data-cy="travelStopDate"
|
||||
:rules="[
|
||||
form().datePrecedence(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].travelStartDate`,
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].travelStopDate`
|
||||
)
|
||||
]"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].travelStopDate`
|
||||
)
|
||||
"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].travelStopDate`
|
||||
)
|
||||
"
|
||||
></gz-date-time-picker>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemTravelRateQuantity')"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-decimal
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].travels[activeItemIndex]
|
||||
.travelRateQuantity
|
||||
"
|
||||
:readonly="formState.readOnly || isDeleted"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemTravelRateQuantity')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].travelRateQuantity`
|
||||
"
|
||||
data-cy="travelTravelRateQuantity"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].travelRateQuantity`
|
||||
)
|
||||
"
|
||||
:rules="[
|
||||
form().decimalValid(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].travelRateQuantity`
|
||||
),
|
||||
form().required(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].travelRateQuantity`
|
||||
)
|
||||
]"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].travelRateQuantity`
|
||||
)
|
||||
"
|
||||
></gz-decimal>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemTravelServiceRateID')"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-pick-list
|
||||
:aya-type="$ay.ayt().TravelRate"
|
||||
:variant="'contractid:' + value.contractId"
|
||||
:show-edit-icon="!value.userIsRestrictedType"
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].travels[activeItemIndex]
|
||||
.travelRateId
|
||||
"
|
||||
:readonly="formState.readOnly || isDeleted"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemTravelServiceRateID')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].travelRateId`
|
||||
"
|
||||
data-cy="travels.travelRateId"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].travelRateId`
|
||||
)
|
||||
"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].travelRateId`
|
||||
)
|
||||
"
|
||||
@update:name="rateChange"
|
||||
></gz-pick-list>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemTravelUserID')"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-pick-list
|
||||
:aya-type="$ay.ayt().User"
|
||||
variant="tech"
|
||||
:show-edit-icon="!value.userIsRestrictedType"
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].travels[activeItemIndex].userId
|
||||
"
|
||||
:readonly="
|
||||
formState.readOnly || isDeleted || value.userIsRestrictedType
|
||||
"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemTravelUserID')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].userId`
|
||||
"
|
||||
data-cy="travels.userid"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].userId`
|
||||
)
|
||||
"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].userId`
|
||||
)
|
||||
"
|
||||
@update:name="userChange"
|
||||
></gz-pick-list>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemTravelNoChargeQuantity')"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-decimal
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].travels[activeItemIndex]
|
||||
.noChargeQuantity
|
||||
"
|
||||
:readonly="formState.readOnly || isDeleted"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemTravelNoChargeQuantity')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].noChargeQuantity`
|
||||
"
|
||||
data-cy="travelNoChargeQuantity"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].noChargeQuantity`
|
||||
)
|
||||
"
|
||||
:rules="[
|
||||
form().decimalValid(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].noChargeQuantity`
|
||||
),
|
||||
form().required(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].noChargeQuantity`
|
||||
)
|
||||
]"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].noChargeQuantity`
|
||||
)
|
||||
"
|
||||
></gz-decimal>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'WorkOrderItemTravelTaxRateSaleID') &&
|
||||
!value.userIsRestrictedType
|
||||
"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-pick-list
|
||||
:aya-type="$ay.ayt().TaxCode"
|
||||
show-edit-icon
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].travels[activeItemIndex]
|
||||
.taxCodeSaleId
|
||||
"
|
||||
:readonly="formState.readOnly || isDeleted"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemTravelTaxRateSaleID')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].taxCodeSaleId`
|
||||
"
|
||||
data-cy="travelTaxCodeSaleId"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].taxCodeSaleId`
|
||||
)
|
||||
"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].taxCodeSaleId`
|
||||
)
|
||||
"
|
||||
@update:name="taxCodeChange"
|
||||
></gz-pick-list>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'TravelPriceOverride') &&
|
||||
!value.userIsRestrictedType
|
||||
"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-currency
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].travels[activeItemIndex]
|
||||
.priceOverride
|
||||
"
|
||||
can-clear
|
||||
:readonly="formState.readOnly || isDeleted"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('PriceOverride')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].priceOverride`
|
||||
"
|
||||
data-cy="travelpriceoverride"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].priceOverride`
|
||||
)
|
||||
"
|
||||
:rules="[
|
||||
form().decimalValid(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].priceOverride`
|
||||
)
|
||||
]"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].priceOverride`
|
||||
)
|
||||
"
|
||||
></gz-currency>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemTravelDetails')"
|
||||
cols="12"
|
||||
>
|
||||
<v-textarea
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].travels[activeItemIndex]
|
||||
.travelDetails
|
||||
"
|
||||
:readonly="formState.readOnly"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemTravelDetails')"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].travelDetails`
|
||||
)
|
||||
"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].travelDetails`
|
||||
"
|
||||
data-cy="traveltravelDetails"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].travels[${activeItemIndex}].travelDetails`
|
||||
)
|
||||
"
|
||||
auto-grow
|
||||
></v-textarea>
|
||||
</v-col>
|
||||
</template>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* XXXeslint-disable */
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
export default {
|
||||
created() {
|
||||
this.setDefaultView();
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeItemIndex: null,
|
||||
selectedRow: []
|
||||
};
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
default: null,
|
||||
type: Object
|
||||
},
|
||||
pvm: {
|
||||
default: null,
|
||||
type: Object
|
||||
},
|
||||
activeWoItemIndex: {
|
||||
default: null,
|
||||
type: Number
|
||||
},
|
||||
gotoIndex: {
|
||||
default: null,
|
||||
type: Number
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
activeWoItemIndex(val, oldVal) {
|
||||
if (val != oldVal) {
|
||||
this.setDefaultView();
|
||||
}
|
||||
},
|
||||
gotoIndex(val, oldVal) {
|
||||
if (val != oldVal) {
|
||||
let gotoIndex = val;
|
||||
if (val < 0) {
|
||||
//it's a create request
|
||||
gotoIndex = this.newItem();
|
||||
}
|
||||
this.selectedRow = [{ index: gotoIndex }];
|
||||
this.activeItemIndex = gotoIndex;
|
||||
this.$nextTick(() => {
|
||||
const el = this.$refs.traveltopform;
|
||||
if (el) {
|
||||
el.scrollIntoView({ behavior: "smooth" });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
userChange(newName) {
|
||||
this.value.items[this.activeWoItemIndex].travels[
|
||||
this.activeItemIndex
|
||||
].userViz = newName;
|
||||
},
|
||||
rateChange(newName) {
|
||||
this.value.items[this.activeWoItemIndex].travels[
|
||||
this.activeItemIndex
|
||||
].travelRateViz = newName;
|
||||
},
|
||||
taxCodeChange(newName) {
|
||||
this.value.items[this.activeWoItemIndex].travels[
|
||||
this.activeItemIndex
|
||||
].taxCodeViz = newName;
|
||||
},
|
||||
newItem() {
|
||||
let newIndex = this.value.items[this.activeWoItemIndex].travels.length;
|
||||
|
||||
this.value.items[this.activeWoItemIndex].travels.push({
|
||||
id: 0,
|
||||
concurrency: 0,
|
||||
userId: this.$store.getters.isScheduleableUser
|
||||
? this.$store.state.userId
|
||||
: null,
|
||||
travelStartDate: null,
|
||||
travelStopDate: null,
|
||||
travelRateId: null,
|
||||
travelDetails: null,
|
||||
travelRateQuantity: 0,
|
||||
noChargeQuantity: 0,
|
||||
taxCodeSaleId: null,
|
||||
price: 0,
|
||||
priceOverride: null,
|
||||
isDirty: true,
|
||||
quoteItemId: this.value.items[this.activeWoItemIndex].id,
|
||||
uid: Date.now(),
|
||||
userViz: this.$store.getters.isScheduleableUser
|
||||
? this.$store.state.userName
|
||||
: null,
|
||||
travelRateViz: null,
|
||||
taxCodeViz: null
|
||||
});
|
||||
this.$emit("change");
|
||||
this.selectedRow = [{ index: newIndex }];
|
||||
this.activeItemIndex = newIndex;
|
||||
return newIndex; //for create new on goto
|
||||
},
|
||||
unDeleteItem() {
|
||||
this.value.items[this.activeWoItemIndex].travels[
|
||||
this.activeItemIndex
|
||||
].deleted = false;
|
||||
this.setDefaultView();
|
||||
},
|
||||
deleteItem() {
|
||||
this.value.items[this.activeWoItemIndex].travels[
|
||||
this.activeItemIndex
|
||||
].deleted = true;
|
||||
this.setDefaultView();
|
||||
this.$emit("change");
|
||||
},
|
||||
deleteAllItem() {
|
||||
this.value.items[this.activeWoItemIndex].travels.forEach(
|
||||
z => (z.deleted = true)
|
||||
);
|
||||
this.setDefaultView();
|
||||
this.$emit("change");
|
||||
},
|
||||
setDefaultView: function() {
|
||||
//if only one record left then display it otherwise just let the datatable show what the user can click on
|
||||
if (this.value.items[this.activeWoItemIndex].travels.length == 1) {
|
||||
this.selectedRow = [{ index: 0 }];
|
||||
this.activeItemIndex = 0;
|
||||
} else {
|
||||
this.selectedRow = [];
|
||||
this.activeItemIndex = null; //select nothing in essence resetting a child selects and this one too clearing form
|
||||
}
|
||||
},
|
||||
handleRowClick: function(item) {
|
||||
this.activeItemIndex = item.index;
|
||||
this.selectedRow = [{ index: item.index }];
|
||||
},
|
||||
form() {
|
||||
return window.$gz.form;
|
||||
},
|
||||
fieldValueChanged(ref) {
|
||||
if (!this.formState.loading && !this.formState.readonly) {
|
||||
//flag this record dirty so it gets picked up by save
|
||||
this.value.items[this.activeWoItemIndex].travels[
|
||||
this.activeItemIndex
|
||||
].isDirty = true;
|
||||
window.$gz.form.fieldValueChanged(this.pvm, ref);
|
||||
//------- SPECIAL HANDLING OF CHANGES -----------
|
||||
const isNew =
|
||||
this.value.items[this.activeWoItemIndex].travels[this.activeItemIndex]
|
||||
.id == 0;
|
||||
|
||||
//Auto calculate dates / quantities / global defaults
|
||||
const dStart = this.value.items[this.activeWoItemIndex].travels[
|
||||
this.activeItemIndex
|
||||
].travelStartDate;
|
||||
const dStop = this.value.items[this.activeWoItemIndex].travels[
|
||||
this.activeItemIndex
|
||||
].travelStopDate;
|
||||
if (ref.includes("travelStartDate") && dStart != null) {
|
||||
this.handleStartDateChange(isNew, dStart, dStop);
|
||||
}
|
||||
if (ref.includes("travelStopDate") && dStop != null) {
|
||||
this.handleStopDateChange(isNew, dStart, dStop);
|
||||
}
|
||||
//------------------------------------------------------
|
||||
}
|
||||
},
|
||||
handleStartDateChange: function(isNew, dStart, dStop) {
|
||||
const globalMinutes =
|
||||
window.$gz.store.state.globalSettings.workOrderTravelDefaultMinutes;
|
||||
|
||||
if (isNew && dStop == null) {
|
||||
if (globalMinutes != 0) {
|
||||
//set stop date based on start date and global minutes
|
||||
this.value.items[this.activeWoItemIndex].travels[
|
||||
this.activeItemIndex
|
||||
].travelStopDate = window.$gz.locale.addMinutesToUTC8601String(
|
||||
dStart,
|
||||
globalMinutes
|
||||
);
|
||||
|
||||
this.value.items[this.activeWoItemIndex].travels[
|
||||
this.activeItemIndex
|
||||
].travelRateQuantity = globalMinutes;
|
||||
}
|
||||
} else {
|
||||
//Existing record or both dates filled, just update quantity
|
||||
if (dStop != null) {
|
||||
this.value.items[this.activeWoItemIndex].travels[
|
||||
this.activeItemIndex
|
||||
].travelRateQuantity = window.$gz.locale.diffHoursFromUTC8601String(
|
||||
dStart,
|
||||
dStop
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
handleStopDateChange: function(isNew, dStart, dStop) {
|
||||
const globalMinutes =
|
||||
window.$gz.store.state.globalSettings.workOrderTravelDefaultMinutes;
|
||||
|
||||
if (isNew && dStart == null) {
|
||||
if (globalMinutes != 0) {
|
||||
//set start date based on stop date and global minutes
|
||||
this.value.items[this.activeWoItemIndex].travels[
|
||||
this.activeItemIndex
|
||||
].travelStartDate = window.$gz.locale.addMinutesToUTC8601String(
|
||||
dStop,
|
||||
0 - globalMinutes
|
||||
);
|
||||
|
||||
this.value.items[this.activeWoItemIndex].travels[
|
||||
this.activeItemIndex
|
||||
].travelRateQuantity = globalMinutes;
|
||||
}
|
||||
} else {
|
||||
//Existing record or both dates filled, just update quantity
|
||||
if (dStart != null) {
|
||||
this.value.items[this.activeWoItemIndex].travels[
|
||||
this.activeItemIndex
|
||||
].travelRateQuantity = window.$gz.locale.diffHoursFromUTC8601String(
|
||||
dStart,
|
||||
dStop
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
itemRowClasses: function(item) {
|
||||
let ret = "";
|
||||
const isDeleted =
|
||||
this.value.items[this.activeWoItemIndex].travels[item.index].deleted ===
|
||||
true;
|
||||
|
||||
const hasError = this.form().childRowHasError(
|
||||
this,
|
||||
`Items[${this.activeWoItemIndex}].Travels[${item.index}].`
|
||||
);
|
||||
|
||||
if (isDeleted) {
|
||||
ret += this.form().tableRowDeletedClass();
|
||||
}
|
||||
if (hasError) {
|
||||
ret += this.form().tableRowErrorClass();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
//---
|
||||
},
|
||||
computed: {
|
||||
isDeleted: function() {
|
||||
if (
|
||||
this.value.items[this.activeWoItemIndex].travels[
|
||||
this.activeItemIndex
|
||||
] == null
|
||||
) {
|
||||
this.setDefaultView();
|
||||
return true;
|
||||
}
|
||||
return (
|
||||
this.value.items[this.activeWoItemIndex].travels[this.activeItemIndex]
|
||||
.deleted === true
|
||||
);
|
||||
},
|
||||
parentDeleted: function() {
|
||||
return this.value.items[this.activeWoItemIndex].deleted === true;
|
||||
},
|
||||
|
||||
headerList: function() {
|
||||
/*
|
||||
If the column is a text, left-align it
|
||||
If the column is a number or number + unit, (or date) right-align it (like excel)
|
||||
*/
|
||||
let headers = [];
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemTravelStartDate")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemTravelStartDate"),
|
||||
align: "right",
|
||||
value: "travelStartDate"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemTravelStopDate")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemTravelStopDate"),
|
||||
align: "right",
|
||||
value: "travelStopDate"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemTravelRateQuantity")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemTravelRateQuantity"),
|
||||
align: "right",
|
||||
value: "travelRateQuantity"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemTravelServiceRateID")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemTravelServiceRateID"),
|
||||
align: "left",
|
||||
value: "travelRateViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemTravelDetails")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemTravelDetails"),
|
||||
align: "left",
|
||||
value: "travelDetails"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemTravelUserID")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemTravelUserID"),
|
||||
align: "left",
|
||||
value: "userViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemTravelNoChargeQuantity")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemTravelNoChargeQuantity"),
|
||||
align: "right",
|
||||
value: "noChargeQuantity"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "TravelUnitOfMeasureViz")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("UnitOfMeasure"),
|
||||
align: "left",
|
||||
value: "unitOfMeasureViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "TravelCostViz") &&
|
||||
this.value.userCanViewLaborOrTravelRateCosts &&
|
||||
!this.value.userIsRestrictedType
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("Cost"),
|
||||
align: "right",
|
||||
value: "costViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "TravelListPriceViz") &&
|
||||
!this.value.userIsRestrictedType
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("ListPrice"),
|
||||
align: "right",
|
||||
value: "listPriceViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "TravelPriceOverride") &&
|
||||
!this.value.userIsRestrictedType
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("PriceOverride"),
|
||||
align: "right",
|
||||
value: "priceOverride"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "TravelPriceViz") &&
|
||||
!this.value.userIsRestrictedType
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("Price"),
|
||||
align: "right",
|
||||
value: "priceViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "WorkOrderItemTravelTaxRateSaleID") &&
|
||||
!this.value.userIsRestrictedType
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("Tax"),
|
||||
align: "left",
|
||||
value: "taxCodeViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "TravelNetViz") &&
|
||||
!this.value.userIsRestrictedType
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("NetPrice"),
|
||||
align: "right",
|
||||
value: "netViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "TravelTaxAViz") &&
|
||||
!this.value.userIsRestrictedType
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("TaxAAmt"),
|
||||
align: "right",
|
||||
value: "taxAViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "TravelTaxBViz") &&
|
||||
!this.value.userIsRestrictedType
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("TaxBAmt"),
|
||||
align: "right",
|
||||
value: "taxBViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "TravelLineTotalViz") &&
|
||||
!this.value.userIsRestrictedType
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("LineTotal"),
|
||||
align: "right",
|
||||
value: "lineTotalViz"
|
||||
});
|
||||
}
|
||||
return headers;
|
||||
},
|
||||
itemList: function() {
|
||||
return this.value.items[this.activeWoItemIndex].travels.map((x, i) => {
|
||||
return {
|
||||
index: i,
|
||||
id: x.id,
|
||||
travelStartDate: window.$gz.locale.utcDateToShortDateAndTimeLocalized(
|
||||
x.travelStartDate,
|
||||
this.pvm.timeZoneName,
|
||||
this.pvm.languageName,
|
||||
this.pvm.hour12
|
||||
),
|
||||
travelStopDate: window.$gz.locale.utcDateToShortDateAndTimeLocalized(
|
||||
x.travelStopDate,
|
||||
this.pvm.timeZoneName,
|
||||
this.pvm.languageName,
|
||||
this.pvm.hour12
|
||||
),
|
||||
|
||||
travelRateQuantity: window.$gz.locale.decimalLocalized(
|
||||
x.travelRateQuantity,
|
||||
this.pvm.languageName
|
||||
),
|
||||
travelRateViz: x.travelRateViz,
|
||||
userViz: x.userViz,
|
||||
noChargeQuantity: window.$gz.locale.decimalLocalized(
|
||||
x.noChargeQuantity,
|
||||
this.pvm.languageName
|
||||
),
|
||||
unitOfMeasureViz: x.unitOfMeasureViz,
|
||||
costViz: window.$gz.locale.currencyLocalized(
|
||||
x.costViz,
|
||||
this.pvm.languageName,
|
||||
this.pvm.currencyName
|
||||
),
|
||||
listPriceViz: window.$gz.locale.currencyLocalized(
|
||||
x.listPriceViz,
|
||||
this.pvm.languageName,
|
||||
this.pvm.currencyName
|
||||
),
|
||||
priceViz: window.$gz.locale.currencyLocalized(
|
||||
x.priceViz,
|
||||
this.pvm.languageName,
|
||||
this.pvm.currencyName
|
||||
),
|
||||
taxCodeViz: x.taxCodeViz,
|
||||
priceOverride: window.$gz.locale.currencyLocalized(
|
||||
x.priceOverride,
|
||||
this.pvm.languageName,
|
||||
this.pvm.currencyName
|
||||
),
|
||||
netViz: window.$gz.locale.currencyLocalized(
|
||||
x.netViz,
|
||||
this.pvm.languageName,
|
||||
this.pvm.currencyName
|
||||
),
|
||||
taxAViz: window.$gz.locale.currencyLocalized(
|
||||
x.taxAViz,
|
||||
this.pvm.languageName,
|
||||
this.pvm.currencyName
|
||||
),
|
||||
taxBViz: window.$gz.locale.currencyLocalized(
|
||||
x.taxBViz,
|
||||
this.pvm.languageName,
|
||||
this.pvm.currencyName
|
||||
),
|
||||
lineTotalViz: window.$gz.locale.currencyLocalized(
|
||||
x.lineTotalViz,
|
||||
this.pvm.languageName,
|
||||
this.pvm.currencyName
|
||||
),
|
||||
travelDetails: window.$gz.util.truncateString(
|
||||
x.travelDetails,
|
||||
this.pvm.maxTableNotesLength
|
||||
)
|
||||
};
|
||||
});
|
||||
},
|
||||
formState: function() {
|
||||
return this.pvm.formState;
|
||||
},
|
||||
formCustomTemplateKey: function() {
|
||||
return this.pvm.formCustomTemplateKey;
|
||||
},
|
||||
hasData: function() {
|
||||
return this.value.items[this.activeWoItemIndex].travels.length > 0;
|
||||
},
|
||||
hasSelection: function() {
|
||||
return this.activeItemIndex != null;
|
||||
},
|
||||
canAdd: function() {
|
||||
return this.pvm.rights.change;
|
||||
},
|
||||
canDelete: function() {
|
||||
return this.activeItemIndex != null && this.pvm.rights.change;
|
||||
},
|
||||
canDeleteAll: function() {
|
||||
return this.pvm.rights.change && !this.value.userIsRestrictedType;
|
||||
}
|
||||
|
||||
//----
|
||||
}
|
||||
};
|
||||
</script>
|
||||
850
ayanova/src/components/quote-item-units.vue
Normal file
850
ayanova/src/components/quote-item-units.vue
Normal file
@@ -0,0 +1,850 @@
|
||||
<template>
|
||||
<div v-if="value != null" class="mt-8">
|
||||
<v-row>
|
||||
<v-col cols="12">
|
||||
<v-menu offset-y max-width="600px">
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<div class="text-h6">
|
||||
<v-icon large :color="hasData ? 'primary' : null" class="mr-2"
|
||||
>$ayiFan</v-icon
|
||||
>
|
||||
{{ $ay.t("WorkOrderItemUnitList") }}
|
||||
<v-btn v-if="!parentDeleted" large icon v-bind="attrs" v-on="on">
|
||||
<v-icon small color="primary">$ayiEllipsisV</v-icon>
|
||||
</v-btn>
|
||||
</div>
|
||||
</template>
|
||||
<v-list>
|
||||
<v-list-item v-if="canAdd" @click="newItem">
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiPlus</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{ $ay.t("New") }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item v-if="canAdd" @click="showBulkUnitsDialog()">
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiFan</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{
|
||||
$ay.t("AddMultipleUnits")
|
||||
}}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item v-if="canDelete && isDeleted" @click="unDeleteItem">
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiTrashRestoreAlt</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{ $ay.t("Undelete") }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item v-if="canDelete && !isDeleted" @click="deleteItem">
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiTrashAlt</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{ $ay.t("SoftDelete") }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item v-if="canDeleteAll" @click="deleteAllItem">
|
||||
<v-list-item-icon>
|
||||
<v-icon>$ayiDumpster</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-title>{{
|
||||
$ay.t("SoftDeleteAll")
|
||||
}}</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</v-col>
|
||||
|
||||
<template v-if="hasData">
|
||||
<!-- ############################################################### -->
|
||||
<v-col cols="12" class="mb-10">
|
||||
<v-data-table
|
||||
:headers="headerList"
|
||||
:items="itemList"
|
||||
item-key="index"
|
||||
v-model="selectedRow"
|
||||
class="elevation-1"
|
||||
disable-pagination
|
||||
disable-filtering
|
||||
disable-sort
|
||||
hide-default-footer
|
||||
data-cy="unitsTable"
|
||||
dense
|
||||
:item-class="itemRowClasses"
|
||||
@click:row="handleRowClick"
|
||||
:show-select="$vuetify.breakpoint.xs"
|
||||
single-select
|
||||
>
|
||||
</v-data-table>
|
||||
</v-col>
|
||||
</template>
|
||||
<template v-if="hasData && hasSelection">
|
||||
<div ref="unittopform"></div>
|
||||
<v-btn
|
||||
v-if="canDelete && isDeleted"
|
||||
large
|
||||
@click="unDeleteItem"
|
||||
color="primary"
|
||||
>{{ $ay.t("Undelete")
|
||||
}}<v-icon right large>$ayiTrashRestoreAlt</v-icon></v-btn
|
||||
>
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderItemUnit')"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-pick-list
|
||||
:aya-type="$ay.ayt().Unit"
|
||||
:variant="'customerid:' + value.customerId"
|
||||
:show-edit-icon="!value.userIsRestrictedType"
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].units[activeItemIndex].unitId
|
||||
"
|
||||
:readonly="
|
||||
formState.readOnly || isDeleted || value.userIsRestrictedType
|
||||
"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('Unit')"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].units[${activeItemIndex}].unitId`
|
||||
"
|
||||
data-cy="units.unitId"
|
||||
:rules="[
|
||||
form().required(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].units[${activeItemIndex}].unitId`
|
||||
)
|
||||
]"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].units[${activeItemIndex}].unitId`
|
||||
)
|
||||
"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].units[${activeItemIndex}].unitId`
|
||||
)
|
||||
"
|
||||
@update:name="unitChange"
|
||||
></gz-pick-list>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'UnitWarrantyInfo') &&
|
||||
!value.userIsRestrictedType
|
||||
"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<v-card>
|
||||
<v-card-title>{{ $ay.t("UnitWarrantyInfo") }}</v-card-title>
|
||||
<v-card-text
|
||||
v-html="
|
||||
value.items[activeWoItemIndex].units[activeItemIndex]
|
||||
.warrantyViz
|
||||
"
|
||||
>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn color="primary" text @click="getWarrantyInfo">{{
|
||||
$ay.t("Search")
|
||||
}}</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'WorkOrderItemUnitNotes') &&
|
||||
!value.userIsRestrictedType
|
||||
"
|
||||
cols="12"
|
||||
>
|
||||
<v-textarea
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].units[activeItemIndex].notes
|
||||
"
|
||||
:readonly="formState.readOnly"
|
||||
:disabled="isDeleted"
|
||||
:label="$ay.t('WorkOrderItemUnitNotes')"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].units[${activeItemIndex}].notes`
|
||||
)
|
||||
"
|
||||
:ref="`Items[${activeWoItemIndex}].units[${activeItemIndex}].notes`"
|
||||
data-cy="unitUnitNotes"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].units[${activeItemIndex}].notes`
|
||||
)
|
||||
"
|
||||
auto-grow
|
||||
></v-textarea>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'WorkOrderItemUnitTags') &&
|
||||
!value.userIsRestrictedType
|
||||
"
|
||||
cols="12"
|
||||
>
|
||||
<gz-tag-picker
|
||||
v-model="value.items[activeWoItemIndex].units[activeItemIndex].tags"
|
||||
:readonly="formState.readOnly"
|
||||
data-cy="unitTags"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].units[${activeItemIndex}].tags`
|
||||
)
|
||||
"
|
||||
:ref="`Items[${activeWoItemIndex}].units[${activeItemIndex}].tags`"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].units[${activeItemIndex}].tags`
|
||||
)
|
||||
"
|
||||
></gz-tag-picker>
|
||||
</v-col>
|
||||
|
||||
<v-col v-if="!value.userIsRestrictedType" cols="12">
|
||||
<gz-custom-fields
|
||||
v-model="
|
||||
value.items[activeWoItemIndex].units[activeItemIndex].customFields
|
||||
"
|
||||
:form-key="formCustomTemplateKey"
|
||||
:readonly="formState.readOnly"
|
||||
:parent-v-m="this"
|
||||
key-start-with="WorkOrderItemUnitCustom"
|
||||
:ref="
|
||||
`Items[${activeWoItemIndex}].units[${activeItemIndex}].customFields`
|
||||
"
|
||||
data-cy="unitCustomFields"
|
||||
:error-messages="
|
||||
form().serverErrors(
|
||||
this,
|
||||
`Items[${activeWoItemIndex}].units[${activeItemIndex}].customFields`
|
||||
)
|
||||
"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].units[${activeItemIndex}].customFields`
|
||||
)
|
||||
"
|
||||
></gz-custom-fields>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'WorkOrderItemUnitWiki') &&
|
||||
!value.userIsRestrictedType
|
||||
"
|
||||
cols="12"
|
||||
>
|
||||
<gz-wiki
|
||||
:aya-type="$ay.ayt().WorkOrderItem"
|
||||
:aya-id="value.id"
|
||||
:ref="`Items[${activeWoItemIndex}].units[${activeItemIndex}].wiki`"
|
||||
v-model="value.items[activeWoItemIndex].units[activeItemIndex].wiki"
|
||||
:readonly="formState.readOnly"
|
||||
@input="
|
||||
fieldValueChanged(
|
||||
`Items[${activeWoItemIndex}].units[${activeItemIndex}].wiki`
|
||||
)
|
||||
"
|
||||
></gz-wiki
|
||||
></v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'WorkOrderItemUnitAttachments') &&
|
||||
value.id &&
|
||||
!value.userIsRestrictedType
|
||||
"
|
||||
cols="12"
|
||||
>
|
||||
<gz-attachments
|
||||
:readonly="formState.readOnly"
|
||||
:aya-type="$ay.ayt().WorkOrderItemUnit"
|
||||
:aya-id="value.items[activeWoItemIndex].units[activeItemIndex].id"
|
||||
></gz-attachments
|
||||
></v-col>
|
||||
</template>
|
||||
</v-row>
|
||||
<!-- ################################################################################-->
|
||||
<!-- ########################## BULK ADD UNITS FORM ###############################-->
|
||||
<!-- ################################################################################-->
|
||||
<template>
|
||||
<v-row justify="center">
|
||||
<v-dialog persistent max-width="600px" v-model="bulkUnitsDialog">
|
||||
<v-card>
|
||||
<v-card-title>{{ $ay.t("AddMultipleUnits") }}</v-card-title>
|
||||
<v-card-text>
|
||||
<gz-tag-picker v-model="selectedBulkUnitTags"></gz-tag-picker>
|
||||
<gz-pick-list
|
||||
:aya-type="$ay.ayt().Customer"
|
||||
:show-edit-icon="false"
|
||||
v-model="selectedBulkUnitCustomer"
|
||||
:label="$ay.t('Customer')"
|
||||
:can-clear="true"
|
||||
></gz-pick-list>
|
||||
|
||||
<v-data-table
|
||||
dense
|
||||
v-model="selectedBulkUnits"
|
||||
:headers="bulkUnitTableHeaders"
|
||||
:items="availableBulkUnits"
|
||||
class="my-10"
|
||||
:disable-filtering="true"
|
||||
hide-default-footer
|
||||
:no-data-text="$ay.t('NoData')"
|
||||
show-select
|
||||
item-key="unitId"
|
||||
>
|
||||
</v-data-table>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-btn text @click="bulkUnitsDialog = false" color="primary">{{
|
||||
$ay.t("Cancel")
|
||||
}}</v-btn>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn
|
||||
:disabled="selectedBulkUnitTags.length == 0"
|
||||
color="primary"
|
||||
text
|
||||
@click="bulkUnitsSearch()"
|
||||
>{{ $ay.t("Search") }}</v-btn
|
||||
>
|
||||
<v-btn
|
||||
:disabled="selectedBulkUnits.length == 0"
|
||||
color="primary"
|
||||
text
|
||||
@click="addSelectedBulkUnits()"
|
||||
>{{ $ay.t("Add") }}</v-btn
|
||||
>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</v-row>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* XXXeslint-disable */
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
export default {
|
||||
created() {
|
||||
this.setDefaultView();
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeItemIndex: null,
|
||||
selectedRow: [],
|
||||
bulkUnitsDialog: false,
|
||||
selectedBulkUnitCustomer: this.value.customerId,
|
||||
availableBulkUnits: [],
|
||||
selectedBulkUnits: [],
|
||||
selectedBulkUnitTags: [],
|
||||
bulkUnitTableHeaders: []
|
||||
};
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
default: null,
|
||||
type: Object
|
||||
},
|
||||
pvm: {
|
||||
default: null,
|
||||
type: Object
|
||||
},
|
||||
activeWoItemIndex: {
|
||||
default: null,
|
||||
type: Number
|
||||
},
|
||||
gotoIndex: {
|
||||
default: null,
|
||||
type: Number
|
||||
},
|
||||
addNew: {
|
||||
default: null,
|
||||
type: Number
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
activeWoItemIndex(val, oldVal) {
|
||||
if (val != oldVal) {
|
||||
this.setDefaultView();
|
||||
}
|
||||
},
|
||||
gotoIndex(val, oldVal) {
|
||||
if (val != oldVal) {
|
||||
let gotoIndex = val;
|
||||
if (val < 0) {
|
||||
//it's a create request
|
||||
gotoIndex = this.newItem();
|
||||
}
|
||||
this.selectedRow = [{ index: gotoIndex }];
|
||||
this.activeItemIndex = gotoIndex;
|
||||
this.$nextTick(() => {
|
||||
const el = this.$refs.unittopform;
|
||||
if (el) {
|
||||
el.scrollIntoView({ behavior: "smooth" });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async updateContractIfApplicable() {
|
||||
const id = this.value.items[this.activeWoItemIndex].units[
|
||||
this.activeItemIndex
|
||||
].unitId;
|
||||
if (!id || id == 0) {
|
||||
return;
|
||||
}
|
||||
let res = await window.$gz.api.get(`unit/active-contract/${id}`);
|
||||
if (res.error) {
|
||||
window.$gz.eventBus.$emit(
|
||||
"notify-warning",
|
||||
window.$gz.errorHandler.errorToString(res, this)
|
||||
);
|
||||
} else {
|
||||
if (res.data.id == 0) {
|
||||
//no contract, just bail
|
||||
return;
|
||||
}
|
||||
//has contract, if it differs from main work order contract then offer to set it
|
||||
if (res.data.id == this.value.contractId) {
|
||||
//same contract, just bail
|
||||
//yes the date could not be different but we're not going to pick that nit, they can just unset and set if it matters
|
||||
return;
|
||||
}
|
||||
//Prompt user to use new contract
|
||||
const prompt = this.$ay
|
||||
.t("ApplyUnitContract")
|
||||
.replace("{0}", res.data.name);
|
||||
|
||||
let dialogResult = await window.$gz.dialog.confirmGenericPreTranslated(
|
||||
prompt,
|
||||
"question"
|
||||
);
|
||||
if (dialogResult == false) {
|
||||
return;
|
||||
} else {
|
||||
this.value.contractId = res.data.id;
|
||||
this.value.isDirty = true;
|
||||
this.pvm.formState.dirty = true;
|
||||
this.$emit("change");
|
||||
}
|
||||
}
|
||||
},
|
||||
async getWarrantyInfo() {
|
||||
this.warrantyInfo = null;
|
||||
|
||||
const id = this.value.items[this.activeWoItemIndex].units[
|
||||
this.activeItemIndex
|
||||
].unitId;
|
||||
if (!id || id == 0) {
|
||||
return;
|
||||
}
|
||||
let res = await window.$gz.api.get(`unit/service-warranty-info/${id}`);
|
||||
if (res.error) {
|
||||
window.$gz.eventBus.$emit(
|
||||
"notify-warning",
|
||||
window.$gz.errorHandler.errorToString(res, this)
|
||||
);
|
||||
} else {
|
||||
/* {
|
||||
"recentWorkOrders":[{"serial":10,"id":10,"serviceDate":"2021-01-19T22:00:00Z"},{"serial":8,"id":8,"serviceDate":"2021-04-08T22:00:00Z"},{"serial":7,"id":7,"serviceDate":"2021-04-18T20:00:00Z"}],
|
||||
"purchaseDate":"2019-03-12T09:37:52.930923Z",
|
||||
"purchasedFromVendor":null,
|
||||
"purchaseFromVendorId":null,
|
||||
"purchaseReceiptNumber":"139736",
|
||||
"lifeTimeWarranty":false,
|
||||
"warrantyExpiryDate":"2019-04-12T09:37:52.930923Z",
|
||||
"warrantyTerms":"Shipping parts and service"}
|
||||
|
||||
"UnitPurchasedDate": "Purchased Date",
|
||||
"UnitPurchaseFromID": "Purchased From",
|
||||
"UnitReceipt": "Receipt Number",
|
||||
*/
|
||||
const r = res.data;
|
||||
|
||||
let WarrantyInfo = `${this.$ay.t("Warranty")}: `;
|
||||
let WarrantyExpiryInfo = "-";
|
||||
if (r.lifeTimeWarranty) {
|
||||
WarrantyExpiryInfo = this.$ay.t("UnitModelLifeTimeWarranty");
|
||||
} else {
|
||||
if (r.warrantyExpiryDate) {
|
||||
WarrantyExpiryInfo = `${this.$ay.t(
|
||||
"WarrantyExpires"
|
||||
)}: ${window.$gz.locale.utcDateToShortDateAndTimeLocalized(
|
||||
r.warrantyExpiryDate,
|
||||
this.pvm.timeZoneName,
|
||||
this.pvm.languageName,
|
||||
this.pvm.hour12
|
||||
)}`;
|
||||
}
|
||||
}
|
||||
WarrantyInfo += WarrantyExpiryInfo;
|
||||
|
||||
let PurchasedFrom = "-";
|
||||
if (r.purchaseFromVendorId) {
|
||||
PurchasedFrom = `<a href="/vendors/${r.purchaseFromVendorId}"> ${r.purchasedFromVendor}</a>`;
|
||||
}
|
||||
let PurchasedDate = "-";
|
||||
if (r.purchaseDate) {
|
||||
PurchasedDate = window.$gz.locale.utcDateToShortDateAndTimeLocalized(
|
||||
r.purchaseDate,
|
||||
this.pvm.timeZoneName,
|
||||
this.pvm.languageName,
|
||||
this.pvm.hour12
|
||||
);
|
||||
}
|
||||
let PurchaseInfo = `${this.$ay.t(
|
||||
"UnitPurchaseFromID"
|
||||
)}: ${PurchasedFrom}<br/>${this.$ay.t(
|
||||
"UnitPurchasedDate"
|
||||
)}: ${PurchasedDate}<br/>${this.$ay.t(
|
||||
"UnitReceipt"
|
||||
)}: ${r.purchaseReceiptNumber ?? "-"}`;
|
||||
|
||||
let RecentWorkOrderList = "";
|
||||
if (r.recentWorkOrders.length > 0) {
|
||||
RecentWorkOrderList += "<br/>";
|
||||
r.recentWorkOrders.forEach(x => {
|
||||
RecentWorkOrderList += `<a href="/svc-workorders/${x.id}"> ${
|
||||
x.serial
|
||||
}<span class='ml-5'>${window.$gz.locale.utcDateToShortDateAndTimeLocalized(
|
||||
x.serviceDate,
|
||||
this.pvm.timeZoneName,
|
||||
this.pvm.languageName,
|
||||
this.pvm.hour12
|
||||
)}</span></a><br/>`;
|
||||
});
|
||||
} else {
|
||||
RecentWorkOrderList = "-";
|
||||
}
|
||||
|
||||
let RecentWorkOrderInfo = `${this.$ay.t(
|
||||
"RecentWorkOrders"
|
||||
)}:${RecentWorkOrderList}`;
|
||||
|
||||
let d = `<div>${WarrantyInfo}<br/>${PurchaseInfo}<br/>${RecentWorkOrderInfo}</div>`;
|
||||
|
||||
this.value.items[this.activeWoItemIndex].units[
|
||||
this.activeItemIndex
|
||||
].warrantyViz = d;
|
||||
}
|
||||
},
|
||||
showBulkUnitsDialog() {
|
||||
if (this.bulkUnitTableHeaders.length == 0) {
|
||||
//init bulk table headers
|
||||
this.bulkUnitTableHeaders = [
|
||||
{ text: this.$ay.t("Customer"), value: "customerName" },
|
||||
{ text: this.$ay.t("Unit"), value: "unitSerial" }
|
||||
];
|
||||
}
|
||||
this.bulkUnitsDialog = true;
|
||||
},
|
||||
async bulkUnitsSearch() {
|
||||
this.selectedBulkUnits.splice(0);
|
||||
this.availableBulkUnits.splice(0);
|
||||
|
||||
let res = await window.$gz.api.post(`unit/bulk-add-selection-list`, {
|
||||
tags: this.selectedBulkUnitTags,
|
||||
restrictToCustomerId: this.selectedBulkUnitCustomer
|
||||
});
|
||||
if (res.error) {
|
||||
window.$gz.eventBus.$emit(
|
||||
"notify-warning",
|
||||
window.$gz.errorHandler.errorToString(res, this)
|
||||
);
|
||||
} else {
|
||||
this.availableBulkUnits = res.data;
|
||||
}
|
||||
},
|
||||
addSelectedBulkUnits() {
|
||||
if (this.selectedBulkUnits.length > 0) {
|
||||
let newIndex = this.value.items[this.activeWoItemIndex].units.length;
|
||||
this.selectedBulkUnits.forEach(z => {
|
||||
newIndex++;
|
||||
this.value.items[this.activeWoItemIndex].units.push({
|
||||
id: 0,
|
||||
concurrency: 0,
|
||||
wiki: null,
|
||||
customFields: "{}",
|
||||
tags: [],
|
||||
notes: null,
|
||||
unitId: z.unitId, //zero to break rule on new
|
||||
isDirty: true,
|
||||
quoteItemId: this.value.items[this.activeWoItemIndex].id,
|
||||
uid: Date.now(),
|
||||
unitViz: z.unitSerial,
|
||||
warrantyViz: null
|
||||
});
|
||||
});
|
||||
this.$emit("change");
|
||||
this.selectedRow = [{ index: newIndex }];
|
||||
this.activeItemIndex = newIndex;
|
||||
}
|
||||
this.bulkUnitsDialog = false;
|
||||
},
|
||||
async unitChange(newName) {
|
||||
this.value.items[this.activeWoItemIndex].units[
|
||||
this.activeItemIndex
|
||||
].unitViz = newName;
|
||||
this.value.items[this.activeWoItemIndex].units[
|
||||
this.activeItemIndex
|
||||
].warrantyViz = null;
|
||||
await this.updateContractIfApplicable();
|
||||
},
|
||||
newItem() {
|
||||
let newIndex = this.value.items[this.activeWoItemIndex].units.length;
|
||||
// {
|
||||
// "0": {
|
||||
// "id": 53,
|
||||
// "concurrency": 9586762,
|
||||
// "notes": "Aut modi molestias molestiae ipsa id.",
|
||||
// "wiki": null,
|
||||
// "customFields": null,
|
||||
// "tags": [],
|
||||
// "unitId": 4,
|
||||
// "unitViz": "83429560",
|
||||
// "quoteItemId": 22
|
||||
// }
|
||||
// }
|
||||
|
||||
this.value.items[this.activeWoItemIndex].units.push({
|
||||
id: 0,
|
||||
concurrency: 0,
|
||||
wiki: null,
|
||||
customFields: "{}",
|
||||
tags: [],
|
||||
notes: null,
|
||||
unitId: 0, //zero to break rule on new
|
||||
isDirty: true,
|
||||
quoteItemId: this.value.items[this.activeWoItemIndex].id,
|
||||
uid: Date.now(),
|
||||
unitViz: null,
|
||||
warrantyViz: null
|
||||
});
|
||||
|
||||
this.$emit("change");
|
||||
this.selectedRow = [{ index: newIndex }];
|
||||
this.activeItemIndex = newIndex;
|
||||
//trigger rule breaking / validation
|
||||
this.$nextTick(() => {
|
||||
this.value.items[this.activeWoItemIndex].units[
|
||||
this.activeItemIndex
|
||||
].unitId = null;
|
||||
this.fieldValueChanged(
|
||||
`Items[${this.activeWoItemIndex}].units[${this.activeItemIndex}].unitId`
|
||||
);
|
||||
});
|
||||
|
||||
return newIndex; //for create new on goto
|
||||
},
|
||||
unDeleteItem() {
|
||||
this.value.items[this.activeWoItemIndex].units[
|
||||
this.activeItemIndex
|
||||
].deleted = false;
|
||||
this.setDefaultView();
|
||||
},
|
||||
deleteItem() {
|
||||
this.value.items[this.activeWoItemIndex].units[
|
||||
this.activeItemIndex
|
||||
].deleted = true;
|
||||
this.setDefaultView();
|
||||
this.$emit("change");
|
||||
},
|
||||
deleteAllItem() {
|
||||
this.value.items[this.activeWoItemIndex].units.forEach(
|
||||
z => (z.deleted = true)
|
||||
);
|
||||
this.setDefaultView();
|
||||
this.$emit("change");
|
||||
},
|
||||
setDefaultView: function() {
|
||||
//if only one record left then display it otherwise just let the datatable show what the user can click on
|
||||
if (this.value.items[this.activeWoItemIndex].units.length == 1) {
|
||||
this.selectedRow = [{ index: 0 }];
|
||||
this.activeItemIndex = 0;
|
||||
} else {
|
||||
this.selectedRow = [];
|
||||
this.activeItemIndex = null; //select nothing in essence resetting a child selects and this one too clearing form
|
||||
}
|
||||
},
|
||||
handleRowClick: function(item) {
|
||||
this.activeItemIndex = item.index;
|
||||
this.selectedRow = [{ index: item.index }];
|
||||
},
|
||||
form() {
|
||||
return window.$gz.form;
|
||||
},
|
||||
fieldValueChanged(ref) {
|
||||
if (!this.formState.loading && !this.formState.readonly) {
|
||||
//flag this record dirty so it gets picked up by save
|
||||
this.value.items[this.activeWoItemIndex].units[
|
||||
this.activeItemIndex
|
||||
].isDirty = true;
|
||||
window.$gz.form.fieldValueChanged(this.pvm, ref);
|
||||
|
||||
// //set viz if applicable
|
||||
// if(ref==""){
|
||||
// let selectedPartWarehouse = vm.$refs.partWarehouseId.getFullSelectionValue();
|
||||
// }
|
||||
}
|
||||
},
|
||||
itemRowClasses: function(item) {
|
||||
let ret = "";
|
||||
const isDeleted =
|
||||
this.value.items[this.activeWoItemIndex].units[item.index].deleted ===
|
||||
true;
|
||||
|
||||
const hasError = this.form().childRowHasError(
|
||||
this,
|
||||
`Items[${this.activeWoItemIndex}].Units[${item.index}].`
|
||||
);
|
||||
|
||||
if (isDeleted) {
|
||||
ret += this.form().tableRowDeletedClass();
|
||||
}
|
||||
if (hasError) {
|
||||
ret += this.form().tableRowErrorClass();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isDeleted: function() {
|
||||
if (
|
||||
this.value.items[this.activeWoItemIndex].units[this.activeItemIndex] ==
|
||||
null
|
||||
) {
|
||||
this.setDefaultView();
|
||||
return true;
|
||||
}
|
||||
return (
|
||||
this.value.items[this.activeWoItemIndex].units[this.activeItemIndex]
|
||||
.deleted === true
|
||||
);
|
||||
},
|
||||
parentDeleted: function() {
|
||||
return this.value.items[this.activeWoItemIndex].deleted === true;
|
||||
},
|
||||
|
||||
headerList: function() {
|
||||
/*
|
||||
If the column is a text, left-align it
|
||||
If the column is a number or number + unit, (or date) right-align it (like excel)
|
||||
*/
|
||||
let headers = [];
|
||||
|
||||
if (this.form().showMe(this, "WorkOrderItemUnit")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("Unit"),
|
||||
align: "left",
|
||||
value: "unitViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "UnitModelModelNumber")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("UnitModelModelNumber"),
|
||||
align: "left",
|
||||
value: "unitModelModelNumberViz"
|
||||
});
|
||||
}
|
||||
if (this.form().showMe(this, "UnitModelVendorID")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("UnitModelVendorID"),
|
||||
align: "left",
|
||||
value: "unitModelVendorViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "UnitModelName")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("UnitModelName"),
|
||||
align: "left",
|
||||
value: "unitModelNameViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (this.form().showMe(this, "UnitDescription")) {
|
||||
headers.push({
|
||||
text: this.$ay.t("UnitDescription"),
|
||||
align: "left",
|
||||
value: "unitDescriptionViz"
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
this.form().showMe(this, "WorkOrderItemUnitNotes") &&
|
||||
!this.value.userIsRestrictedType
|
||||
) {
|
||||
headers.push({
|
||||
text: this.$ay.t("WorkOrderItemUnitNotes"),
|
||||
align: "left",
|
||||
value: "notes"
|
||||
});
|
||||
}
|
||||
|
||||
return headers;
|
||||
},
|
||||
itemList: function() {
|
||||
return this.value.items[this.activeWoItemIndex].units.map((x, i) => {
|
||||
return {
|
||||
index: i,
|
||||
id: x.id,
|
||||
unitViz: x.unitViz,
|
||||
unitModelModelNumberViz: x.unitModelModelNumberViz,
|
||||
unitModelVendorViz: x.unitModelVendorViz,
|
||||
unitModelNameViz: x.unitModelNameViz,
|
||||
unitDescriptionViz: x.unitDescriptionViz,
|
||||
notes: window.$gz.util.truncateString(
|
||||
x.notes,
|
||||
this.pvm.maxTableNotesLength
|
||||
)
|
||||
};
|
||||
});
|
||||
},
|
||||
formState: function() {
|
||||
return this.pvm.formState;
|
||||
},
|
||||
formCustomTemplateKey: function() {
|
||||
return this.pvm.formCustomTemplateKey;
|
||||
},
|
||||
hasData: function() {
|
||||
return this.value.items[this.activeWoItemIndex].units.length > 0;
|
||||
},
|
||||
hasSelection: function() {
|
||||
return this.activeItemIndex != null;
|
||||
},
|
||||
canAdd: function() {
|
||||
return this.pvm.rights.change && !this.value.userIsRestrictedType;
|
||||
},
|
||||
canDelete: function() {
|
||||
return (
|
||||
this.activeItemIndex != null &&
|
||||
this.canDeleteAll &&
|
||||
!this.value.userIsRestrictedType
|
||||
);
|
||||
},
|
||||
canDeleteAll: function() {
|
||||
return this.pvm.rights.change && !this.value.userIsRestrictedType;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -888,7 +888,7 @@ export default {
|
||||
);
|
||||
|
||||
this.pvm.washWorkOrderItem(wi);
|
||||
wi.workOrderId = this.value.id;
|
||||
wi.quoteId = this.value.id;
|
||||
wi.sequence = newIndex + 1;
|
||||
this.value.items.push(wi);
|
||||
this.$emit("change");
|
||||
@@ -931,7 +931,7 @@ export default {
|
||||
wiki: null,
|
||||
customFields: "{}",
|
||||
tags: [],
|
||||
workOrderId: this.value.id,
|
||||
quoteId: this.value.id,
|
||||
techNotes: null,
|
||||
workorderItemStatusId: null,
|
||||
workorderItemPriorityId: null,
|
||||
|
||||
299
ayanova/src/components/quote-state.vue
Normal file
299
ayanova/src/components/quote-state.vue
Normal file
@@ -0,0 +1,299 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="mb-n2 ml-10">
|
||||
<span class="text-caption">{{ $ay.t("QuoteQuoteStatusType") }}</span>
|
||||
</div>
|
||||
|
||||
<template>
|
||||
<div class="mb-6 mb-sm-0">
|
||||
<v-btn icon class="ml-n1 mr-2" @click="openDialog = true">
|
||||
<v-icon>{{ openIcon() }}</v-icon>
|
||||
</v-btn>
|
||||
|
||||
<span class="text-h6" @click="openDialog = true">{{
|
||||
pvm.currentState.name
|
||||
}}</span>
|
||||
<v-icon :color="pvm.currentState.color" class="ml-4">$ayiFlag</v-icon>
|
||||
<v-icon color="primary" v-if="pvm.currentState.locked" class="ml-4"
|
||||
>$ayiLock</v-icon
|
||||
>
|
||||
<v-icon color="primary" v-if="pvm.currentState.completed" class="ml-4"
|
||||
>$ayiCheckCircle</v-icon
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<v-row justify="center">
|
||||
<v-dialog v-model="openDialog" max-width="600px">
|
||||
<v-card>
|
||||
<v-card-title>
|
||||
<span class="text-h5">{{ $ay.t("QuoteQuoteStatusType") }}</span>
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
<template v-if="$vuetify.breakpoint.smAndUp">
|
||||
<!-- WIDE VIEW -->
|
||||
<div v-for="item in stateDisplayList" :key="item.id">
|
||||
<span>{{ item.timeStamp }}</span>
|
||||
<span class="ml-3">{{ item.user }}</span>
|
||||
<span class="font-weight-bold ml-3">{{ item.name }}</span>
|
||||
<v-icon small :color="item.color" class="ml-4">$ayiFlag</v-icon>
|
||||
<v-icon small color="primary" v-if="item.locked" class="ml-4"
|
||||
>$ayiLock</v-icon
|
||||
>
|
||||
<v-icon small color="primary" v-if="item.completed" class="ml-4"
|
||||
>$ayiCheckCircle</v-icon
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<!-- NARROW VIEW -->
|
||||
<div v-for="item in stateDisplayList" :key="item.id">
|
||||
<span>{{ item.timeStamp }} </span>
|
||||
<span>{{ item.user }}</span>
|
||||
<div class="mb-2">
|
||||
<span class="font-weight-bold">{{ item.name }}</span>
|
||||
<v-icon small :color="item.color" class="ml-4"
|
||||
>$ayiFlag</v-icon
|
||||
>
|
||||
<v-icon small color="primary" v-if="item.locked" class="ml-4"
|
||||
>$ayiLock</v-icon
|
||||
>
|
||||
<v-icon
|
||||
small
|
||||
color="primary"
|
||||
v-if="item.completed"
|
||||
class="ml-4"
|
||||
>$ayiCheckCircle</v-icon
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- append-outer-icon="$ayiPlus"
|
||||
@click:append-outer="addState()" -->
|
||||
<template v-if="canAdd">
|
||||
<div class="mt-8">
|
||||
<v-autocomplete
|
||||
v-model="selectedStatus"
|
||||
:items="pvm.selectLists.allowedquotestatus"
|
||||
item-text="name"
|
||||
item-value="id"
|
||||
dense
|
||||
:label="$ay.t('NewStatus')"
|
||||
prepend-icon="$ayiEdit"
|
||||
@click:prepend="handleEditStateClick()"
|
||||
>
|
||||
<template v-slot:item="data">
|
||||
<v-list-item-avatar>
|
||||
<v-icon :color="data.item.color">$ayiFlag</v-icon>
|
||||
</v-list-item-avatar>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title
|
||||
><span class="text-subtitle-2">{{
|
||||
data.item.name
|
||||
}}</span
|
||||
><v-icon
|
||||
small
|
||||
color="disabled"
|
||||
class="ml-2"
|
||||
v-if="data.item.locked"
|
||||
>$ayiLock</v-icon
|
||||
>
|
||||
<v-icon
|
||||
color="disabled"
|
||||
class="ml-1"
|
||||
small
|
||||
v-if="data.item.completed"
|
||||
>$ayiCheckCircle</v-icon
|
||||
></v-list-item-title
|
||||
>
|
||||
|
||||
<v-list-item-subtitle>
|
||||
{{ data.item.notes }}</v-list-item-subtitle
|
||||
>
|
||||
</v-list-item-content>
|
||||
<v-list-item-action> </v-list-item-action>
|
||||
</template>
|
||||
</v-autocomplete>
|
||||
</div>
|
||||
</template>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn color="blue darken-1" text @click="cancelDialog()">{{
|
||||
$ay.t("Cancel")
|
||||
}}</v-btn>
|
||||
<v-btn
|
||||
color="blue darken-1"
|
||||
:disabled="selectedStatus == null"
|
||||
text
|
||||
@click="save()"
|
||||
>{{ $ay.t("OK") }}</v-btn
|
||||
>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* XXXeslint-disable */
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
selectedStatus: null,
|
||||
openDialog: false
|
||||
};
|
||||
},
|
||||
|
||||
props: {
|
||||
value: {
|
||||
default: null,
|
||||
type: Object
|
||||
},
|
||||
pvm: {
|
||||
default: null,
|
||||
type: Object
|
||||
},
|
||||
allStates: {
|
||||
default: null,
|
||||
type: Array
|
||||
},
|
||||
allowedStates: {
|
||||
default: null,
|
||||
type: Array
|
||||
},
|
||||
formKey: { type: String, default: "" }, //used to grab template from store
|
||||
readonly: Boolean,
|
||||
disabled: Boolean
|
||||
},
|
||||
|
||||
methods: {
|
||||
addState() {
|
||||
if (this.selectedStatus != null) {
|
||||
//first remove any other non saved states in collection, no need to send them to the server if there was multiple state changes since last save
|
||||
this.value.states = this.value.states.filter(
|
||||
z => z.concurrency != null
|
||||
);
|
||||
|
||||
//is it a different state?
|
||||
if (this.selectedStatus == this.pvm.currentState.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
//push in new state
|
||||
this.value.states.push({
|
||||
quoteId: this.value.id,
|
||||
quoteStatusId: this.selectedStatus,
|
||||
userId: window.$gz.store.state.userId,
|
||||
userViz: window.$gz.store.state.userName,
|
||||
created: window.$gz.locale.nowUTC8601String()
|
||||
});
|
||||
|
||||
this.selectedStatus = null;
|
||||
this.pvm.formState.dirty = true;
|
||||
}
|
||||
},
|
||||
getStateForDisplay(state) {
|
||||
let ret = {
|
||||
id: Date.now,
|
||||
name: "??",
|
||||
color: "#ffffff",
|
||||
locked: false,
|
||||
completed: false,
|
||||
timeStamp: "??",
|
||||
user: "??"
|
||||
};
|
||||
const s = this.allStates.find(z => z.id == state.quoteStatusId);
|
||||
if (s == null) {
|
||||
return ret;
|
||||
}
|
||||
//make for display
|
||||
ret.id = state.id;
|
||||
ret.name = s.name;
|
||||
ret.color = s.color;
|
||||
ret.locked = s.locked;
|
||||
ret.completed = s.completed;
|
||||
ret.user = state.userViz;
|
||||
ret.timeStamp = window.$gz.locale.utcDateToShortDateAndTimeLocalized(
|
||||
state.created,
|
||||
this.pvm.timeZoneName,
|
||||
this.pvm.languageName,
|
||||
this.pvm.hour12
|
||||
);
|
||||
return ret;
|
||||
},
|
||||
form() {
|
||||
return window.$gz.form;
|
||||
},
|
||||
openIcon: function() {
|
||||
if (this.canAdd) {
|
||||
return "$ayiEdit";
|
||||
}
|
||||
return "$ayiHistory";
|
||||
},
|
||||
handleEditStateClick: function() {
|
||||
window.$gz.eventBus.$emit("openobject", {
|
||||
type: window.$gz.type.QuoteStatus,
|
||||
id: this.selectedStatus
|
||||
});
|
||||
},
|
||||
save() {
|
||||
this.addState();
|
||||
this.openDialog = false;
|
||||
},
|
||||
cancelDialog() {
|
||||
this.selectedStatus = null;
|
||||
this.openDialog = false;
|
||||
},
|
||||
fieldValueChanged(ref) {
|
||||
if (!this.pvm.formState.loading && !this.pvm.formState.readonly) {
|
||||
window.$gz.form.fieldValueChanged(this.pvm, ref);
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
hasState() {
|
||||
return this.value.states != null && this.value.states.length > 0;
|
||||
},
|
||||
stateDisplayList() {
|
||||
let ret = [];
|
||||
this.value.states.forEach(z => {
|
||||
ret.push(this.getStateForDisplay(z));
|
||||
});
|
||||
return ret;
|
||||
},
|
||||
canAdd: function() {
|
||||
//first check most obvious disqualifying properties
|
||||
if (!this.pvm.rights.change) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//not currently locked, user has rights to do it so allow it
|
||||
if (!this.value.isLockedAtServer) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//locked, confirm if user can change it
|
||||
//if any role then no problem
|
||||
|
||||
//ok, only thing left to check is if the current user can unlock this
|
||||
//get remove roles required for current state
|
||||
let cs = this.pvm.currentState;
|
||||
if (cs.removeRoles == null || cs.removeRoles == 0) {
|
||||
//no state set yet
|
||||
return true;
|
||||
}
|
||||
|
||||
//ok, need to check the role here against current user roles to see if this is valid
|
||||
if (window.$gz.role.hasRole(cs.removeRoles)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -88,7 +88,7 @@ export default {
|
||||
let wi = this.$route.params.copyItem;
|
||||
if (wi) {
|
||||
this.washWorkOrderItem(wi);
|
||||
wi.workOrderId = vm.obj.id;
|
||||
wi.quoteId = vm.obj.id;
|
||||
wi.sequence = vm.obj.items.length + 1;
|
||||
vm.obj.items.push(wi);
|
||||
setDirty = true;
|
||||
@@ -104,7 +104,7 @@ export default {
|
||||
this.obj.serial = 0;
|
||||
this.obj.isDirty = true;
|
||||
vm.obj.items.forEach(z => {
|
||||
z.workOrderId = 0;
|
||||
z.quoteId = 0;
|
||||
this.washWorkOrderItem(z);
|
||||
});
|
||||
setDirty = true;
|
||||
@@ -228,8 +228,8 @@ export default {
|
||||
hour12: window.$gz.locale.getHour12(),
|
||||
// resetSelections: false,
|
||||
selectLists: {
|
||||
wostatus: [],
|
||||
allowedwostatus: [],
|
||||
quotestatus: [],
|
||||
allowedquotestatus: [],
|
||||
woItemPriorities: [],
|
||||
woItemStatus: [],
|
||||
woItemTaskCompletionTypes: [],
|
||||
@@ -288,8 +288,8 @@ export default {
|
||||
//find it in the status collection
|
||||
//and return here
|
||||
const laststate = this.obj.states[this.obj.states.length - 1];
|
||||
const found = this.selectLists.wostatus.find(
|
||||
z => z.id == laststate.workOrderStatusId
|
||||
const found = this.selectLists.quotestatus.find(
|
||||
z => z.id == laststate.quoteStatusId
|
||||
);
|
||||
if (found) {
|
||||
return found;
|
||||
@@ -625,19 +625,19 @@ export default {
|
||||
|
||||
wi.expenses.forEach(x => {
|
||||
x.id = 0;
|
||||
x.workOrderItemId = 0;
|
||||
x.quoteItemId = 0;
|
||||
x.concurrency = undefined;
|
||||
x.isDirty = true;
|
||||
});
|
||||
wi.labors.forEach(x => {
|
||||
x.id = 0;
|
||||
x.workOrderItemId = 0;
|
||||
x.quoteItemId = 0;
|
||||
x.concurrency = undefined;
|
||||
x.isDirty = true;
|
||||
});
|
||||
wi.loans.forEach(x => {
|
||||
x.id = 0;
|
||||
x.workOrderItemId = 0;
|
||||
x.quoteItemId = 0;
|
||||
x.concurrency = undefined;
|
||||
x.isDirty = true;
|
||||
x.cost = 0;
|
||||
@@ -645,7 +645,7 @@ export default {
|
||||
});
|
||||
wi.parts.forEach(x => {
|
||||
x.id = 0;
|
||||
x.workOrderItemId = 0;
|
||||
x.quoteItemId = 0;
|
||||
x.concurrency = undefined;
|
||||
x.isDirty = true;
|
||||
x.cost = 0;
|
||||
@@ -654,31 +654,31 @@ export default {
|
||||
|
||||
wi.scheduledUsers.forEach(x => {
|
||||
x.id = 0;
|
||||
x.workOrderItemId = 0;
|
||||
x.quoteItemId = 0;
|
||||
x.concurrency = undefined;
|
||||
x.isDirty = true;
|
||||
});
|
||||
wi.tasks.forEach(x => {
|
||||
x.id = 0;
|
||||
x.workOrderItemId = 0;
|
||||
x.quoteItemId = 0;
|
||||
x.concurrency = undefined;
|
||||
x.isDirty = true;
|
||||
});
|
||||
wi.travels.forEach(x => {
|
||||
x.id = 0;
|
||||
x.workOrderItemId = 0;
|
||||
x.quoteItemId = 0;
|
||||
x.concurrency = undefined;
|
||||
x.isDirty = true;
|
||||
});
|
||||
wi.units.forEach(x => {
|
||||
x.id = 0;
|
||||
x.workOrderItemId = 0;
|
||||
x.quoteItemId = 0;
|
||||
x.concurrency = undefined;
|
||||
x.isDirty = true;
|
||||
});
|
||||
wi.outsideServices.forEach(x => {
|
||||
x.id = 0;
|
||||
x.workOrderItemId = 0;
|
||||
x.quoteItemId = 0;
|
||||
x.concurrency = undefined;
|
||||
x.isDirty = true;
|
||||
});
|
||||
@@ -732,8 +732,8 @@ async function saveHeader(vm) {
|
||||
vm.obj.id = res.data.id;
|
||||
vm.obj.serial = res.data.serial;
|
||||
//walk all unsaved direct children and set the workorder id so they can save
|
||||
vm.obj.states.forEach(z => (z.workOrderId = vm.obj.id));
|
||||
vm.obj.items.forEach(z => (z.workOrderId = vm.obj.id));
|
||||
vm.obj.states.forEach(z => (z.quoteId = vm.obj.id));
|
||||
vm.obj.items.forEach(z => (z.quoteId = vm.obj.id));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1870,7 +1870,7 @@ async function fetchTranslatedText(vm) {
|
||||
"WorkOrderInternalReferenceNumber",
|
||||
"WorkOrderOnsite",
|
||||
"NewStatus",
|
||||
"WorkOrderStatus",
|
||||
"QuoteQuoteStatusType",
|
||||
"WorkOrderCustom1",
|
||||
"WorkOrderCustom2",
|
||||
"WorkOrderCustom3",
|
||||
@@ -2087,8 +2087,8 @@ async function populateSelectionLists(vm) {
|
||||
vm.formState.serverError = res.error;
|
||||
window.$gz.form.setErrorBoxErrors(vm);
|
||||
} else {
|
||||
vm.selectLists.wostatus = res.data.all;
|
||||
vm.selectLists.allowedwostatus = res.data.allowed;
|
||||
vm.selectLists.quotestatus = res.data.all;
|
||||
vm.selectLists.allowedquotestatus = res.data.allowed;
|
||||
}
|
||||
|
||||
res = await window.$gz.api.get("work-order-item-status/list");
|
||||
|
||||
Reference in New Issue
Block a user