Files
raven-client/ayanova/src/components/work-order-items.vue
2022-01-24 22:58:10 +00:00

1430 lines
48 KiB
Vue

<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-h3">
<v-icon x-large :color="hasData ? 'primary' : null" class="mr-2"
>$ayiWrench</v-icon
>
{{ $ay.t("WorkOrderItemList") }}
<v-btn large icon v-bind="attrs" data-cy="woItemHeader" v-on="on">
<v-icon color="primary">$ayiEllipsisV</v-icon>
</v-btn>
</div>
</template>
<v-list>
<v-list-item v-if="canAdd" data-cy="woItemNew" @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="hasData && hasSelection && canAdd"
@click="copyItemDialog = true"
>
<v-list-item-icon>
<v-icon>$ayiCopy</v-icon>
</v-list-item-icon>
<v-list-item-title>{{
$ay.t("CopyToWorkOrder")
}}</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-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>
<template v-if="hasData && pvm.rights.change">
<v-divider></v-divider>
<v-list-item
data-cy="woItemRealizeSuggestedParts"
@click="realizeSuggestedParts"
>
<v-list-item-title>{{
$ay.t("WorkOrderItemPartRealizeSuggested")
}}</v-list-item-title>
</v-list-item>
</template>
<template v-if="hasData && hasSelection && pvm.rights.change">
<v-divider></v-divider>
<v-subheader>{{ $ay.t("Add") }}</v-subheader>
<v-list-item
v-if="canAddUnit"
data-cy="woItemAddUnit"
@click="newSubItem($ay.ayt().WorkOrderItemUnit)"
>
<v-list-item-icon>
<v-icon>$ayiFan</v-icon>
</v-list-item-icon>
<v-list-item-title>{{
$ay.t("WorkOrderItemUnit")
}}</v-list-item-title>
</v-list-item>
<v-list-item
v-if="canAddScheduledUser"
data-cy="woItemAddScheduledUser"
@click="newSubItem($ay.ayt().WorkOrderItemScheduledUser)"
>
<v-list-item-icon>
<v-icon>$ayiUserClock</v-icon>
</v-list-item-icon>
<v-list-item-title>{{
$ay.t("WorkOrderItemScheduledUser")
}}</v-list-item-title>
</v-list-item>
<v-list-item
v-if="canAddTask"
data-cy="woItemAddTask"
@click="newSubItem($ay.ayt().WorkOrderItemTask)"
>
<v-list-item-icon>
<v-icon>$ayiTasks</v-icon>
</v-list-item-icon>
<v-list-item-title>{{
$ay.t("WorkOrderItemTask")
}}</v-list-item-title>
</v-list-item>
<v-list-item
v-if="canAddPart"
data-cy="woItemAddPart"
@click="newSubItem($ay.ayt().WorkOrderItemPart)"
>
<v-list-item-icon>
<v-icon>$ayiBoxes</v-icon>
</v-list-item-icon>
<v-list-item-title>{{
$ay.t("WorkOrderItemPart")
}}</v-list-item-title>
</v-list-item>
<v-list-item
v-if="canAddLabor"
data-cy="woItemAddLabor"
@click="newSubItem($ay.ayt().WorkOrderItemLabor)"
>
<v-list-item-icon>
<v-icon>$ayiHammer</v-icon>
</v-list-item-icon>
<v-list-item-title>{{
$ay.t("WorkOrderItemLabor")
}}</v-list-item-title>
</v-list-item>
<v-list-item
v-if="canAddTravel"
data-cy="woItemAddTravel"
@click="newSubItem($ay.ayt().WorkOrderItemTravel)"
>
<v-list-item-icon>
<v-icon>$ayiTruckMonster</v-icon>
</v-list-item-icon>
<v-list-item-title>{{
$ay.t("WorkOrderItemTravel")
}}</v-list-item-title>
</v-list-item>
<v-list-item
v-if="canAddExpense"
data-cy="woItemAddExpense"
@click="newSubItem($ay.ayt().WorkOrderItemExpense)"
>
<v-list-item-icon>
<v-icon>$ayiMoneyBillWave</v-icon>
</v-list-item-icon>
<v-list-item-title>{{
$ay.t("WorkOrderItemExpense")
}}</v-list-item-title>
</v-list-item>
<v-list-item
v-if="canAddLoan"
data-cy="woItemAddLoan"
@click="newSubItem($ay.ayt().WorkOrderItemLoan)"
>
<v-list-item-icon>
<v-icon>$ayiPlug</v-icon>
</v-list-item-icon>
<v-list-item-title>{{
$ay.t("WorkOrderItemLoan")
}}</v-list-item-title>
</v-list-item>
<v-list-item
v-if="canAddOutsideService"
data-cy="woItemAddOutsideService"
@click="newSubItem($ay.ayt().WorkOrderItemOutsideService)"
>
<v-list-item-icon>
<v-icon>$ayiLuggageCart</v-icon>
</v-list-item-icon>
<v-list-item-title>{{
$ay.t("WorkOrderItemOutsideService")
}}</v-list-item-title>
</v-list-item>
</template>
</v-list>
</v-menu>
</v-col>
<template v-if="hasData">
<!-- ################################ WORK ORDER ITEMS TABLE ############################### -->
<v-col cols="12" class="mb-10">
<v-data-table
v-model="selectedRow"
:headers="headerList"
:items="itemList"
item-key="index"
class="elevation-1"
disable-pagination
disable-filtering
disable-sort
hide-default-footer
data-cy="itemsTable"
dense
:item-class="itemRowClasses"
:show-select="$vuetify.breakpoint.xs"
single-select
@click:row="handleRowClick"
>
<template v-slot:[`item.status`]="{ item }">
<template v-if="item.status.id != null">
<v-icon class="mr-3" :color="item.status.color"
>$ayiCircle</v-icon
>{{ item.status.name }}
</template>
</template>
<template v-slot:[`item.priority`]="{ item }">
<template v-if="item.priority.id != null">
<v-icon class="mr-3" :color="item.priority.color"
>$ayiFireAlt</v-icon
>{{ item.priority.name }}
</template>
</template>
<template v-slot:[`item.warranty`]="{ item }">
<v-simple-checkbox
v-model="item.warranty"
disabled
></v-simple-checkbox>
</template>
</v-data-table>
</v-col>
</template>
<template v-if="hasData && hasSelection">
<v-btn
v-if="canDelete && isDeleted"
large
color="primary"
@click="unDeleteItem"
>{{ $ay.t("Undelete")
}}<v-icon right large>$ayiTrashRestoreAlt</v-icon></v-btn
>
<div ref="topform"></div>
<v-col
v-if="value.items[activeItemIndex].fromCSRId != null"
cols="12"
sm="6"
lg="4"
xl="3"
>
<v-btn text @click="openCSR()">
<v-icon>$ayiConciergeBell</v-icon>
<span class="text-h6 accent--text" @click="openCSR()"
>{{ $ay.t("CustomerServiceRequest") }}
</span></v-btn
>
</v-col>
<v-col cols="12">
<v-textarea
:ref="`items[${activeItemIndex}].notes`"
v-model="value.items[activeItemIndex].notes"
:readonly="formState.readOnly || value.userIsRestrictedType"
:disabled="isDeleted"
:label="$ay.t('WorkOrderItemSummary')"
:error-messages="
form().serverErrors(this, `items[${activeItemIndex}].notes`)
"
:rules="[form().required(this, `items[${activeItemIndex}].notes`)]"
data-cy="Items.Notes"
auto-grow
@input="fieldValueChanged(`items[${activeItemIndex}].notes`)"
></v-textarea>
</v-col>
<v-col
v-if="
form().showMe(this, 'WorkOrderItemSequence') &&
!value.userIsRestrictedType
"
cols="12"
sm="6"
lg="4"
xl="3"
>
<v-text-field
:ref="`items[${activeItemIndex}].sequence`"
v-model="value.items[activeItemIndex].sequence"
:readonly="formState.readOnly || value.userIsRestrictedType"
:disabled="isDeleted"
:label="$ay.t('Sequence')"
:rules="[
form().integerValid(this, `items[${activeItemIndex}].sequence`)
]"
:error-messages="
form().serverErrors(this, `items[${activeItemIndex}].sequence`)
"
type="number"
@input="fieldValueChanged(`items[${activeItemIndex}].sequence`)"
></v-text-field>
</v-col>
<v-col v-if="form().showMe(this, 'WorkOrderItemTechNotes')" cols="12">
<v-textarea
:ref="`items[${activeItemIndex}].techNotes`"
v-model="value.items[activeItemIndex].techNotes"
:readonly="formState.readOnly || value.userIsRestrictedType"
:disabled="isDeleted"
:label="$ay.t('WorkOrderItemTechNotes')"
:error-messages="
form().serverErrors(this, `items[${activeItemIndex}].techNotes`)
"
data-cy="items.techNotes"
auto-grow
@input="fieldValueChanged(`items[${activeItemIndex}].techNotes`)"
></v-textarea>
</v-col>
<v-col
v-if="
form().showMe(this, 'WorkOrderItemRequestDate') &&
!value.userIsRestrictedType
"
cols="12"
sm="6"
lg="4"
xl="3"
>
<gz-date-time-picker
:ref="`items[${activeItemIndex}].requestDate`"
v-model="value.items[activeItemIndex].requestDate"
:label="$ay.t('WorkOrderItemRequestDate')"
:readonly="formState.readOnly"
:disabled="isDeleted"
data-cy="requestDate"
:error-messages="
form().serverErrors(this, `items[${activeItemIndex}].requestDate`)
"
@input="fieldValueChanged('requestDate')"
></gz-date-time-picker>
</v-col>
<v-col
v-if="
form().showMe(this, 'WorkOrderItemStatusId') &&
!value.userIsRestrictedType
"
cols="12"
sm="6"
lg="4"
xl="3"
>
<v-autocomplete
:ref="`items[${activeItemIndex}].workOrderItemStatusId`"
v-model="value.items[activeItemIndex].workOrderItemStatusId"
:readonly="formState.readOnly"
:disabled="isDeleted"
:items="selectableStatusList"
item-text="name"
item-value="id"
:label="$ay.t('WorkOrderItemWorkOrderStatusID')"
:error-messages="
form().serverErrors(
this,
`items[${activeItemIndex}].workOrderItemStatusId`
)
"
data-cy="workOrderItemStatusId"
prepend-icon="$ayiEdit"
@input="fieldValueChanged('workOrderItemStatusId')"
@click:prepend="handleEditItemStatusClick()"
>
<template v-slot:selection="{ item }">
<v-icon class="mr-3" :color="item.color">$ayiCircle</v-icon
>{{ item.name }}
</template>
<template v-slot:item="{ item }">
<v-list-item-avatar>
<v-icon :color="item.color">$ayiCircle</v-icon>
</v-list-item-avatar>
<v-list-item-content>
<v-list-item-title
><span
:class="
item.active
? ''
: 'disabled--text text-decoration-line-through'
"
>{{ item.name }}</span
></v-list-item-title
>
<v-list-item-subtitle> {{ item.notes }}</v-list-item-subtitle>
</v-list-item-content>
</template>
</v-autocomplete>
</v-col>
<v-col
v-if="
form().showMe(this, 'WorkOrderItemPriorityID') &&
!value.userIsRestrictedType
"
cols="12"
sm="6"
lg="4"
xl="3"
>
<v-autocomplete
:ref="`items[${activeItemIndex}].workOrderItemPriorityId`"
v-model="value.items[activeItemIndex].workOrderItemPriorityId"
:readonly="formState.readOnly"
:disabled="isDeleted"
:items="selectablePriorityList"
item-text="name"
item-value="id"
:label="$ay.t('WorkOrderItemPriorityID')"
:error-messages="
form().serverErrors(
this,
`items[${activeItemIndex}].workOrderItemPriorityId`
)
"
data-cy="workOrderItemPriorityId"
prepend-icon="$ayiEdit"
@input="fieldValueChanged('workOrderItemPriorityId')"
@click:prepend="handleEditItemPriorityClick()"
>
<template v-slot:selection="{ item }">
<v-icon class="mr-3" :color="item.color">$ayiFireAlt</v-icon
>{{ item.name }}
</template>
<template v-slot:item="{ item }">
<v-list-item-avatar>
<v-icon :color="item.color">$ayiFireAlt</v-icon>
</v-list-item-avatar>
<v-list-item-content>
<v-list-item-title
><span
:class="
item.active
? ''
: 'disabled--text text-decoration-line-through'
"
>{{ item.name }}</span
></v-list-item-title
>
</v-list-item-content>
</template>
</v-autocomplete>
</v-col>
<v-col
v-if="
form().showMe(this, 'WarrantyService') &&
!value.userIsRestrictedType
"
cols="12"
sm="6"
lg="4"
xl="3"
>
<v-checkbox
:ref="`items[${activeItemIndex}].warrantyService`"
v-model="value.items[activeItemIndex].warrantyService"
:readonly="formState.readOnly"
:disabled="isDeleted"
:label="$ay.t('WorkOrderItemWarrantyService')"
data-cy="warrantyService"
:error-messages="
form().serverErrors(
this,
`items[${activeItemIndex}].warrantyService`
)
"
@change="fieldValueChanged('warrantyService')"
></v-checkbox>
</v-col>
<v-col
v-if="
form().showMe(this, 'WorkOrderItemTags') &&
!value.userIsRestrictedType
"
cols="12"
>
<gz-tag-picker
:ref="`items[${activeItemIndex}].tags`"
v-model="value.items[activeItemIndex].tags"
:readonly="formState.readOnly"
data-cy="tags"
:error-messages="
form().serverErrors(this, `items[${activeItemIndex}].tags`)
"
@input="fieldValueChanged('tags')"
></gz-tag-picker>
</v-col>
<v-col v-if="!value.userIsRestrictedType" cols="12">
<gz-custom-fields
:ref="`items[${activeItemIndex}].customFields`"
v-model="value.items[activeItemIndex].customFields"
:form-key="formCustomTemplateKey"
:readonly="formState.readOnly"
:parent-v-m="this"
key-start-with="WorkOrderItemCustom"
data-cy="customFields"
:error-messages="
form().serverErrors(
this,
`items[${activeItemIndex}].customFields`
)
"
@input="fieldValueChanged('customFields')"
></gz-custom-fields>
</v-col>
<v-col
v-if="
form().showMe(this, 'WorkOrderItemWiki') &&
!value.userIsRestrictedType
"
cols="12"
>
<gz-wiki
:ref="`items[${activeItemIndex}].wiki`"
v-model="value.items[activeItemIndex].wiki"
:aya-type="$ay.ayt().WorkOrderItem"
:aya-id="value.id"
:readonly="formState.readOnly"
@input="fieldValueChanged('wiki')"
></gz-wiki
></v-col>
<v-col
v-if="
form().showMe(this, 'WorkOrderItemAttachments') &&
value.id &&
!value.userIsRestrictedType
"
cols="12"
>
<gz-attachments
:readonly="formState.readOnly"
:aya-type="$ay.ayt().WorkOrderItem"
:aya-id="value.items[activeItemIndex].id"
></gz-attachments
></v-col>
<!-- ############################################################################
GRANDCHILDREN
############################################################################ -->
<v-col v-show="showUnits" cols="12">
<GzWoItemUnits
v-model="value"
:pvm="pvm"
:active-wo-item-index="activeItemIndex"
:goto-index="gotoUnitIndex"
data-cy="woItemUnits"
@change="$emit('change')"
/>
</v-col>
<v-col v-show="showScheduledUsers" cols="12">
<GzWoItemScheduledUsers
v-model="value"
:pvm="pvm"
:active-wo-item-index="activeItemIndex"
:goto-index="gotoScheduledUserIndex"
data-cy="woItemScheduledUsers"
@change="$emit('change')"
/>
</v-col>
<v-col v-show="showTasks" cols="12">
<GzWoItemTasks
v-model="value"
:pvm="pvm"
:active-wo-item-index="activeItemIndex"
:goto-index="gotoTaskIndex"
data-cy="woItemTasks"
@change="$emit('change')"
/>
</v-col>
<v-col v-show="showParts" cols="12">
<GzWoItemParts
v-model="value"
:pvm="pvm"
:active-wo-item-index="activeItemIndex"
:goto-index="gotoPartIndex"
data-cy="woItemParts"
@change="$emit('change')"
/>
</v-col>
<v-col v-if="showPartRequests" cols="12">
<GzWoItemPartRequests
v-model="value"
:pvm="pvm"
:active-wo-item-index="activeItemIndex"
:goto-index="gotoPartRequestIndex"
data-cy="woItemPartRequests"
@change="$emit('change')"
/>
</v-col>
<v-col v-show="showLabors" cols="12">
<GzWoItemLabors
v-model="value"
:pvm="pvm"
:active-wo-item-index="activeItemIndex"
:goto-index="gotoLaborIndex"
data-cy="woItemLabors"
@change="$emit('change')"
/>
</v-col>
<v-col v-show="showTravels" cols="12">
<GzWoItemTravels
v-model="value"
:pvm="pvm"
:active-wo-item-index="activeItemIndex"
:goto-index="gotoTravelIndex"
data-cy="woItemTravels"
@change="$emit('change')"
/>
</v-col>
<v-col v-show="showExpenses" cols="12">
<GzWoItemExpenses
v-model="value"
:pvm="pvm"
:active-wo-item-index="activeItemIndex"
:goto-index="gotoExpenseIndex"
data-cy="woItemExpenses"
@change="$emit('change')"
/>
</v-col>
<v-col v-show="showLoans" cols="12">
<GzWoItemLoans
v-model="value"
:pvm="pvm"
:active-wo-item-index="activeItemIndex"
:goto-index="gotoLoanIndex"
data-cy="woItemLoans"
@change="$emit('change')"
/>
</v-col>
<v-col v-show="showOutsideServices" cols="12">
<GzWoItemOutsideServices
v-model="value"
:pvm="pvm"
:active-wo-item-index="activeItemIndex"
:goto-index="gotoOutsideServiceIndex"
data-cy="woItemOutsideServices"
@change="$emit('change')"
/>
</v-col>
</template>
</v-row>
<!-- ################################################################################-->
<!-- ########################## COPY WOITEM DIALOG ###############################-->
<!-- ################################################################################-->
<template>
<v-row justify="center">
<v-dialog v-model="copyItemDialog" max-width="600px">
<v-card>
<v-card-title>
<span class="text-h5">{{ $ay.t("CopyToWorkOrder") }}</span>
</v-card-title>
<v-card-text>
<v-text-field
v-model="copyItemWoNumber"
:label="$ay.t('WorkOrder')"
autofocus
required
type="number"
></v-text-field>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
color="blue darken-1"
text
@click="copyItemDialog = false"
>{{ $ay.t("Cancel") }}</v-btn
>
<v-btn
color="blue darken-1"
text
:disabled="!copyItemWoNumber"
@click="copyItemToWorkOrder()"
>{{ $ay.t("OK") }}</v-btn
>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
</div>
</template>
<script>
import GzWoItemUnits from "../components/work-order-item-units.vue";
import GzWoItemScheduledUsers from "../components/work-order-item-scheduled-users.vue";
import GzWoItemLabors from "../components/work-order-item-labors.vue";
import GzWoItemTravels from "../components/work-order-item-travels.vue";
import GzWoItemExpenses from "../components/work-order-item-expenses.vue";
import GzWoItemTasks from "../components/work-order-item-tasks.vue";
import GzWoItemParts from "../components/work-order-item-parts.vue";
import GzWoItemPartRequests from "../components/work-order-item-part-requests.vue";
import GzWoItemLoans from "../components/work-order-item-loans.vue";
import GzWoItemOutsideServices from "../components/work-order-item-outside-services.vue";
export default {
components: {
GzWoItemUnits,
GzWoItemScheduledUsers,
GzWoItemExpenses,
GzWoItemLabors,
GzWoItemTravels,
GzWoItemTasks,
GzWoItemParts,
GzWoItemPartRequests,
GzWoItemLoans,
GzWoItemOutsideServices
},
props: {
value: {
default: null,
type: Object
},
pvm: {
default: null,
type: Object
},
goto: {
default: null,
type: Object
}
},
data() {
return {
activeItemIndex: null,
selectedRow: [],
gotoOutsideServiceIndex: null,
gotoExpenseIndex: null,
gotoLaborIndex: null,
gotoLoanIndex: null,
gotoPartIndex: null,
gotoPartRequestIndex: null,
gotoTaskIndex: null,
gotoScheduledUserIndex: null,
gotoTravelIndex: null,
gotoUnitIndex: null,
copyItemDialog: false,
copyItemWoNumber: null
};
},
computed: {
isDeleted: function() {
if (this.value.items[this.activeItemIndex] == null) {
this.setDefaultView();
return true;
}
return this.value.items[this.activeItemIndex].deleted === true;
},
headerList: function() {
const headers = [];
if (this.form().showMe(this, "WorkOrderItemSequence")) {
headers.push({
text: this.$ay.t("Sequence"),
align: "left",
value: "sequence"
});
}
headers.push({
text: this.$ay.t("WorkOrderItemSummary"), //mandatory not hidden
align: "left",
value: "notes"
});
if (
this.form().showMe(this, "WorkOrderItemStatusId") &&
!this.value.userIsRestrictedType
) {
headers.push({
text: this.$ay.t("WorkOrderItemWorkOrderStatusID"),
align: "left",
value: "status"
});
}
if (
this.form().showMe(this, "WorkOrderItemRequestDate") &&
!this.value.userIsRestrictedType
) {
headers.push({
text: this.$ay.t("WorkOrderItemRequestDate"),
align: "right",
value: "requestDate"
});
}
if (
this.form().showMe(this, "WorkOrderItemPriorityID") &&
!this.value.userIsRestrictedType
) {
headers.push({
text: this.$ay.t("WorkOrderItemPriorityID"),
align: "left",
value: "priority"
});
}
if (
this.form().showMe(this, "WarrantyService") &&
!this.value.userIsRestrictedType
) {
headers.push({
text: this.$ay.t("WorkOrderItemWarrantyService"),
align: "center",
value: "warranty"
});
}
if (
this.form().showMe(this, "WorkOrderItemTags") &&
!this.value.userIsRestrictedType
) {
headers.push({
text: this.$ay.t("Tags"),
align: "left",
value: "tags"
});
}
return headers;
},
itemList: function() {
return this.value.items
.map((x, i) => {
const stat = statusViz(x.workOrderItemStatusId, this);
const prior = priorityViz(x.workOrderItemPriorityId, this);
return {
index: i,
id: x.id,
sequence: x.sequence,
notes: x.notes,
status: stat,
requestDate: window.$gz.locale.utcDateToShortDateAndTimeLocalized(
x.requestDate,
this.pvm.timeZoneName,
this.pvm.languageName,
this.pvm.hour12
),
priority: prior,
warranty: x.warrantyService,
tags: x.tags
};
})
.sort((a, b) => a.sequence - b.sequence);
},
selectableStatusList: function() {
const selectedId = this.value.items[this.activeItemIndex]
.workOrderItemStatusId;
return this.pvm.selectLists.woItemStatus.filter(s => {
return s.active == true || s.id == selectedId;
});
},
selectablePriorityList: function() {
const selectedId = this.value.items[this.activeItemIndex]
.workOrderItemPriorityId;
return this.pvm.selectLists.woItemPriorities.filter(s => {
return s.active == true || s.id == selectedId;
});
},
formState: function() {
return this.pvm.formState;
},
formCustomTemplateKey: function() {
return this.pvm.formCustomTemplateKey;
},
hasData: function() {
return this.value.items.length > 0;
},
hasSelection: function() {
return this.activeItemIndex != null;
},
canAdd: function() {
return (
!this.pvm.formState.readOnly &&
!this.value.userIsRestrictedType &&
this.pvm.rights.change
);
},
canDelete: function() {
return (
this.activeItemIndex != null &&
this.canDeleteAll &&
!this.value.userIsRestrictedType
);
},
canDeleteAll: function() {
return (
!this.pvm.formState.readOnly &&
this.pvm.rights.change &&
this.hasData &&
!this.value.userIsRestrictedType
);
},
canAddUnit: function() {
return (
this.form().showMe(this, "WorkOrderItemUnitList") &&
!this.value.userIsRestrictedType
);
},
showUnits: function() {
return (
this.form().showMe(this, "WorkOrderItemUnitList") &&
this.value.items[this.activeItemIndex].units.length > 0 &&
!this.value.userIsSubContractorRestricted
);
},
canAddScheduledUser: function() {
return (
this.form().showMe(this, "WorkOrderItemScheduledUserList") &&
!this.value.userIsRestrictedType
);
},
showScheduledUsers: function() {
return (
this.form().showMe(this, "WorkOrderItemScheduledUserList") &&
this.value.items[this.activeItemIndex].scheduledUsers.length > 0
);
},
canAddTask: function() {
return (
this.form().showMe(this, "WorkOrderItemTasks") &&
!this.value.userIsRestrictedType
);
},
showTasks: function() {
return (
this.form().showMe(this, "WorkOrderItemTasks") &&
this.value.items[this.activeItemIndex].tasks.length > 0
);
},
canAddPart: function() {
return (
this.form().showMe(this, "WorkOrderItemPartList") &&
!this.value.userIsRestrictedType
);
},
showParts: function() {
return (
this.form().showMe(this, "WorkOrderItemPartList") &&
this.value.items[this.activeItemIndex].parts.length > 0 &&
!this.value.userIsSubContractorRestricted
);
},
showPartRequests: function() {
return (
this.pvm.useInventory &&
this.value.items[this.activeItemIndex].partRequests.length > 0 &&
this.form().showMe(this, "WorkOrderItemPartRequestList") &&
!this.value.userIsSubContractorRestricted
);
},
canAddLabor: function() {
return this.form().showMe(this, "WorkOrderItemLaborList");
},
showLabors: function() {
return (
this.form().showMe(this, "WorkOrderItemLaborList") &&
this.value.items[this.activeItemIndex].labors.length > 0
);
},
canAddTravel: function() {
return this.form().showMe(this, "WorkOrderItemTravelList");
},
showTravels: function() {
return (
this.form().showMe(this, "WorkOrderItemTravelList") &&
this.value.items[this.activeItemIndex].travels.length > 0
);
},
canAddExpense: function() {
return (
this.form().showMe(this, "WorkOrderItemExpenseList") &&
!this.value.userIsSubContractorFull &&
!this.value.userIsSubContractorRestricted
);
},
showExpenses: function() {
return (
this.form().showMe(this, "WorkOrderItemExpenseList") &&
this.value.items[this.activeItemIndex].expenses.length > 0 &&
!this.value.userIsSubContractorFull &&
!this.value.userIsSubContractorRestricted
);
},
canAddLoan: function() {
return (
this.form().showMe(this, "WorkOrderItemLoanList") &&
!this.value.userIsRestrictedType
);
},
showLoans: function() {
return (
this.form().showMe(this, "WorkOrderItemLoanList") &&
this.value.items[this.activeItemIndex].loans.length > 0 &&
!this.value.userIsSubContractorRestricted
);
},
canAddOutsideService: function() {
return (
this.form().showMe(this, "WorkOrderItemOutsideServiceList") &&
!this.value.userIsRestrictedType
);
},
showOutsideServices: function() {
return (
this.form().showMe(this, "WorkOrderItemOutsideServiceList") &&
this.value.items[this.activeItemIndex].outsideServices.length > 0 &&
!this.value.userIsRestrictedType
);
}
},
watch: {
goto(val, oldVal) {
if (val != oldVal) {
const navto = { woitemindex: null, childindex: null };
//find the item in question then trigger the nav
let keepgoing = true;
this.value.items.forEach((z, itemindex) => {
if (keepgoing) {
switch (val.type) {
case window.$gz.type.WorkOrderItem:
if (z.id == val.id) {
navto.woitemindex = itemindex;
keepgoing = false;
}
break;
case window.$gz.type.WorkOrderItemOutsideService:
z.outsideServices.forEach((x, childindex) => {
if (x.id == val.id) {
navto.woitemindex = itemindex;
navto.childindex = childindex;
keepgoing = false;
}
});
break;
case window.$gz.type.WorkOrderItemExpense:
z.expenses.forEach((x, childindex) => {
if (x.id == val.id) {
navto.woitemindex = itemindex;
navto.childindex = childindex;
keepgoing = false;
}
});
break;
case window.$gz.type.WorkOrderItemLabor:
z.labors.forEach((x, childindex) => {
if (x.id == val.id) {
navto.woitemindex = itemindex;
navto.childindex = childindex;
keepgoing = false;
}
});
break;
case window.$gz.type.WorkOrderItemLoan:
z.loans.forEach((x, childindex) => {
if (x.id == val.id) {
navto.woitemindex = itemindex;
navto.childindex = childindex;
keepgoing = false;
}
});
break;
case window.$gz.type.WorkOrderItemPart:
z.parts.forEach((x, childindex) => {
if (x.id == val.id) {
navto.woitemindex = itemindex;
navto.childindex = childindex;
keepgoing = false;
}
});
break;
case window.$gz.type.WorkOrderItemPartRequest:
z.partRequests.forEach((x, childindex) => {
if (x.id == val.id) {
navto.woitemindex = itemindex;
navto.childindex = childindex;
keepgoing = false;
}
});
break;
case window.$gz.type.WorkOrderItemScheduledUser:
z.scheduledUsers.forEach((x, childindex) => {
if (x.id == val.id) {
navto.woitemindex = itemindex;
navto.childindex = childindex;
keepgoing = false;
}
});
break;
case window.$gz.type.WorkOrderItemTask:
z.tasks.forEach((x, childindex) => {
if (x.id == val.id) {
navto.woitemindex = itemindex;
navto.childindex = childindex;
keepgoing = false;
}
});
break;
case window.$gz.type.WorkOrderItemTravel:
z.travels.forEach((x, childindex) => {
if (x.id == val.id) {
navto.woitemindex = itemindex;
navto.childindex = childindex;
keepgoing = false;
}
});
break;
case window.$gz.type.WorkOrderItemUnit:
z.units.forEach((x, childindex) => {
if (x.id == val.id) {
navto.woitemindex = itemindex;
navto.childindex = childindex;
keepgoing = false;
}
});
break;
}
}
});
if (navto.woitemindex != null) {
this.selectedRow = [{ index: navto.woitemindex }];
this.activeItemIndex = navto.woitemindex;
this.$nextTick(() => {
const el = this.$refs.topform;
if (el) {
el.scrollIntoView({ behavior: "smooth" });
}
});
if (navto.childindex != null) {
this.$nextTick(() => {
switch (val.type) {
case window.$gz.type.WorkOrderItemOutsideService:
this.gotoOutsideServiceIndex = navto.childindex;
break;
case window.$gz.type.WorkOrderItemExpense:
this.gotoExpenseIndex = navto.childindex;
break;
case window.$gz.type.WorkOrderItemLabor:
this.gotoLaborIndex = navto.childindex;
break;
case window.$gz.type.WorkOrderItemLoan:
this.gotoLoanIndex = navto.childindex;
break;
case window.$gz.type.WorkOrderItemPart:
this.gotoPartIndex = navto.childindex;
break;
case window.$gz.type.WorkOrderItemPartRequest:
this.gotoPartRequestIndex = navto.childindex;
break;
case window.$gz.type.WorkOrderItemTask:
this.gotoTaskIndex = navto.childindex;
break;
case window.$gz.type.WorkOrderItemScheduledUser:
this.gotoScheduledUserIndex = navto.childindex;
break;
case window.$gz.type.WorkOrderItemTravel:
this.gotoTravelIndex = navto.childindex;
break;
case window.$gz.type.WorkOrderItemUnit:
this.gotoUnitIndex = navto.childindex;
break;
}
});
}
}
}
}
},
created() {
this.setDefaultView();
},
methods: {
openCSR: function() {
window.$gz.eventBus.$emit("openobject", {
type: window.$gz.type.CustomerServiceRequest,
id: this.value.items[this.activeItemIndex].fromCSRId
});
},
async copyItemToWorkOrder() {
if (!this.copyItemWoNumber) {
return;
}
//Self copy to current workorder??
if (this.copyItemWoNumber == this.value.serial) {
const newIndex = this.value.items.length;
const wi = JSON.parse(
JSON.stringify(this.value.items[this.activeItemIndex])
);
this.pvm.washWorkOrderItem(wi);
wi.workOrderId = this.value.id;
wi.sequence = newIndex + 1;
this.value.items.push(wi);
this.$emit("change");
this.selectedRow = [{ index: newIndex }];
this.activeItemIndex = newIndex;
} else {
if (this.pvm.formState.dirty) {
if ((await window.$gz.dialog.confirmLeaveUnsaved()) !== true) {
return;
}
}
//get id from number then push open
const res = await window.$gz.api.get(
"workorder/id-from-number/" + this.copyItemWoNumber
);
if (res.error) {
window.$gz.eventBus.$emit(
"notify-warning",
window.$gz.errorHandler.errorToString(res, this)
);
return;
}
this.$router.push({
name: "workorder-edit",
params: {
recordid: res.data,
copyItem: this.value.items[this.activeItemIndex]
}
});
}
this.copyItemDialog = false;
},
newItem() {
const newIndex = this.value.items.length;
this.value.items.push({
id: 0,
concurrency: 0,
notes: undefined, //to trigger validation on new
wiki: null,
customFields: "{}",
tags: [],
workOrderId: this.value.id,
fromCSRId: null,
techNotes: null,
workOrderItemStatusId: null,
workOrderItemPriorityId: null,
requestDate: null,
warrantyService: false,
sequence: newIndex + 1, //indexes are zero based but sequences are visible to user so 1 based
isDirty: true,
expenses: [],
labors: [],
loans: [],
parts: [],
partRequests: [],
scheduledUsers: [],
tasks: [],
travels: [],
units: [],
outsideServices: [],
uid: Date.now() //used for error tracking / display
});
this.$emit("change");
this.selectedRow = [{ index: newIndex }];
this.activeItemIndex = newIndex;
//trigger rule breaking / validation
this.$nextTick(() => {
this.value.items[this.activeItemIndex].notes = null;
this.fieldValueChanged(`items[${this.activeItemIndex}].notes`);
});
},
newSubItem(atype) {
//new Id value to use (by convention goto negative will trigger create and then goto instead of simple goto)
const newId = -Math.abs(Date.now());
switch (atype) {
case window.$gz.type.WorkOrderItemOutsideService:
this.gotoOutsideServiceIndex = newId;
break;
case window.$gz.type.WorkOrderItemExpense:
this.gotoExpenseIndex = newId;
break;
case window.$gz.type.WorkOrderItemLabor:
this.gotoLaborIndex = newId;
break;
case window.$gz.type.WorkOrderItemLoan:
this.gotoLoanIndex = newId;
break;
case window.$gz.type.WorkOrderItemPart:
this.gotoPartIndex = newId;
break;
case window.$gz.type.WorkOrderItemTask:
this.gotoTaskIndex = newId;
break;
case window.$gz.type.WorkOrderItemScheduledUser:
this.gotoScheduledUserIndex = newId;
break;
case window.$gz.type.WorkOrderItemTravel:
this.gotoTravelIndex = newId;
break;
case window.$gz.type.WorkOrderItemUnit:
this.gotoUnitIndex = newId;
break;
}
},
unDeleteItem() {
this.value.items[this.activeItemIndex].deleted = false;
this.setDefaultView();
},
deleteItem() {
this.value.items[this.activeItemIndex].deleted = true;
this.setDefaultView();
this.$emit("change");
},
deleteAllItem() {
this.value.items.forEach(z => (z.deleted = true));
this.setDefaultView();
this.$emit("change");
},
realizeSuggestedParts() {
this.value.items.forEach(z => {
z.parts.forEach(part => {
if (part.quantity == 0 && part.suggestedQuantity > 0) {
part.quantity = part.suggestedQuantity;
part.isDirty = true;
}
});
});
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 && this.value.items && this.value.items.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 }];
},
handleEditItemStatusClick: function() {
window.$gz.eventBus.$emit("openobject", {
type: window.$gz.type.WorkOrderItemStatus,
id: this.value.items[this.activeItemIndex].workOrderItemStatusId
});
},
handleEditItemPriorityClick: function() {
window.$gz.eventBus.$emit("openobject", {
type: window.$gz.type.WorkOrderItemPriority,
id: this.value.items[this.activeItemIndex].workOrderItemPriorityId
});
},
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.activeItemIndex].isDirty = true;
window.$gz.form.fieldValueChanged(this.pvm, ref);
}
},
itemRowClasses: function(item) {
let ret = "";
const isDeleted = this.value.items[item.index].deleted === true;
const hasError = this.form().childRowHasError(
this,
`Items[${item.index}].`
);
if (isDeleted) {
ret += this.form().tableRowDeletedClass();
}
if (hasError) {
ret += this.form().tableRowErrorClass();
}
return ret;
}
}
};
//////////////////////
//
//
function statusViz(id, vm) {
if (id == null) {
return { name: null, color: null };
}
return vm.pvm.selectLists.woItemStatus.find(s => s.id == id);
}
//////////////////////
//
//
function priorityViz(id, vm) {
if (id == null) {
return { name: null, color: null };
}
return vm.pvm.selectLists.woItemPriorities.find(s => s.id == id);
}
</script>