PM Dawn
This commit is contained in:
@@ -515,6 +515,7 @@ CURRENTLY DOING: PM stuff:
|
||||
Pore over quote and PM and look for workorder remnants, particularly biz actions and rules
|
||||
Add back end rules as necessary for quotes and PM's
|
||||
Sanity checks for PM settings will be a must here
|
||||
test help links
|
||||
Child->grandchild data lists for quotes and pm's like workorders
|
||||
release
|
||||
profit$
|
||||
|
||||
@@ -330,16 +330,6 @@ function initNavPanel() {
|
||||
});
|
||||
}
|
||||
|
||||
// //WORKORDER TEMPLATES LIST
|
||||
//this will be an item inside the workorders NEW menu or grid or wherever but it's not top level worthy
|
||||
//there used to be an array for 3rd level shit but that's whack yo! ;)
|
||||
// subSub.push({
|
||||
// title: "WorkOrderServiceTemplate",
|
||||
// icon: "fa - stamp",
|
||||
// route: "/svc-workorder-templates",
|
||||
// key: key++
|
||||
// });
|
||||
|
||||
//QUOTE LIST
|
||||
if (window.$gz.role.canOpen(window.$gz.type.Quote)) {
|
||||
sub.push({
|
||||
@@ -355,7 +345,7 @@ function initNavPanel() {
|
||||
sub.push({
|
||||
title: "PMList",
|
||||
icon: "$ayiBusinessTime",
|
||||
route: "/svc-pm-list",
|
||||
route: "/svc-pms",
|
||||
key: key++
|
||||
});
|
||||
}
|
||||
|
||||
@@ -145,6 +145,52 @@ export default {
|
||||
});
|
||||
break;
|
||||
|
||||
//### PM AND RELATIVES ###
|
||||
case ayatype.PMItem:
|
||||
case ayatype.PMItemExpense:
|
||||
case ayatype.PMItemLabor:
|
||||
case ayatype.PMItemLoan:
|
||||
case ayatype.PMItemOutsideService:
|
||||
case ayatype.PMItemPart:
|
||||
case ayatype.PMItemPartRequest:
|
||||
case ayatype.PMItemScheduledUser:
|
||||
case ayatype.PMItemTask:
|
||||
case ayatype.PMItemTravel:
|
||||
case ayatype.PMItemUnit:
|
||||
(async () => {
|
||||
try {
|
||||
let res = await window.$gz.api.get(
|
||||
`search/ancestor/${tid.type}/${tid.id}`
|
||||
);
|
||||
|
||||
if (res.error) {
|
||||
throw new Error(
|
||||
window.$gz.errorHandler.errorToString(res, vm)
|
||||
);
|
||||
}
|
||||
if (res.data.id && res.data.id != 0) {
|
||||
this.handleOpenObjectClick(vm, {
|
||||
type: ayatype.PM,
|
||||
id: res.data.id,
|
||||
gotype: tid.type,
|
||||
goid: tid.id
|
||||
});
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
//throw new Error(e);
|
||||
throw new Error(window.$gz.errorHandler.errorToString(e, vm));
|
||||
}
|
||||
})();
|
||||
|
||||
break;
|
||||
case ayatype.PM:
|
||||
vm.$router.push({
|
||||
name: "pm-edit",
|
||||
params: { recordid: tid.id, gotype: tid.gotype, goid: tid.goid }
|
||||
});
|
||||
break;
|
||||
|
||||
case ayatype.Memo:
|
||||
vm.$router.push({
|
||||
name: "memo-edit",
|
||||
|
||||
666
ayanova/src/components/pm-header.vue
Normal file
666
ayanova/src/components/pm-header.vue
Normal file
@@ -0,0 +1,666 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-row>
|
||||
<v-col
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
v-if="value.serial != 0 && canEditSerial"
|
||||
>
|
||||
<v-text-field
|
||||
v-model="value.serial"
|
||||
:readonly="formState.readOnly"
|
||||
:label="$ay.t('PMSerialNumber')"
|
||||
ref="serial"
|
||||
data-cy="serial"
|
||||
:rules="[
|
||||
form().integerValid(this, 'serial'),
|
||||
form().required(this, 'serial')
|
||||
]"
|
||||
:error-messages="form().serverErrors(this, 'serial')"
|
||||
@input="fieldValueChanged('serial')"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6" lg="4" xl="3">
|
||||
<gz-pick-list
|
||||
:aya-type="$ay.ayt().Customer"
|
||||
:show-edit-icon="!value.userIsRestrictedType"
|
||||
v-model="value.customerId"
|
||||
:readonly="formState.readOnly || value.userIsRestrictedType"
|
||||
:label="$ay.t('Customer')"
|
||||
:can-clear="false"
|
||||
ref="customerId"
|
||||
data-cy="customerId"
|
||||
:rules="[form().required(this, 'customerId')]"
|
||||
:error-messages="form().serverErrors(this, 'customerId')"
|
||||
@input="fieldValueChanged('customerId')"
|
||||
></gz-pick-list>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'Address') && !value.userIsSubContractorRestricted
|
||||
"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<GzWoAddress
|
||||
v-model="value"
|
||||
:form-key="formCustomTemplateKey"
|
||||
:readonly="formState.readOnly || value.userIsRestrictedType"
|
||||
:pvm="pvm"
|
||||
data-cy="woAddress"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6" lg="4" xl="3">
|
||||
<v-checkbox
|
||||
v-model="value.active"
|
||||
:readonly="formState.readOnly"
|
||||
:label="$ay.t('Active')"
|
||||
ref="active"
|
||||
data-cy="active"
|
||||
:error-messages="form().serverErrors(this, 'active')"
|
||||
@change="fieldValueChanged('active')"
|
||||
></v-checkbox>
|
||||
</v-col>
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'WorkOrderSummary') &&
|
||||
!(
|
||||
value.userIsSubContractorFull ||
|
||||
value.userIsSubContractorRestricted
|
||||
)
|
||||
"
|
||||
cols="12"
|
||||
>
|
||||
<v-textarea
|
||||
v-model="value.notes"
|
||||
:readonly="formState.readOnly || value.userIsTechRestricted"
|
||||
:label="$ay.t('WorkOrderSummary')"
|
||||
:error-messages="form().serverErrors(this, 'notes')"
|
||||
ref="notes"
|
||||
data-cy="notes"
|
||||
@input="fieldValueChanged('notes')"
|
||||
auto-grow
|
||||
></v-textarea>
|
||||
</v-col>
|
||||
|
||||
<!-- <v-col
|
||||
v-if="
|
||||
form().showMe(this, 'PMPMRequestDate') &&
|
||||
!(
|
||||
value.userIsSubContractorFull ||
|
||||
value.userIsSubContractorRestricted
|
||||
)
|
||||
"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-date-time-picker
|
||||
:label="$ay.t('PMPMRequestDate')"
|
||||
v-model="value.requested"
|
||||
:readonly="formState.readOnly || value.userIsTechRestricted"
|
||||
ref="requested"
|
||||
data-cy="requested"
|
||||
:error-messages="form().serverErrors(this, 'requested')"
|
||||
@input="fieldValueChanged('requested')"
|
||||
></gz-date-time-picker>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'PMValidUntilDate') &&
|
||||
!(
|
||||
value.userIsSubContractorFull ||
|
||||
value.userIsSubContractorRestricted
|
||||
)
|
||||
"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-date-time-picker
|
||||
:label="$ay.t('PMValidUntilDate')"
|
||||
v-model="value.validUntil"
|
||||
:readonly="formState.readOnly || value.userIsTechRestricted"
|
||||
ref="validUntil"
|
||||
data-cy="validUntil"
|
||||
:error-messages="form().serverErrors(this, 'validUntil')"
|
||||
@input="fieldValueChanged('validUntil')"
|
||||
></gz-date-time-picker>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'PMDateSubmitted') &&
|
||||
!(
|
||||
value.userIsSubContractorFull ||
|
||||
value.userIsSubContractorRestricted
|
||||
)
|
||||
"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-date-time-picker
|
||||
:label="$ay.t('PMDateSubmitted')"
|
||||
v-model="value.submitted"
|
||||
:readonly="formState.readOnly || value.userIsTechRestricted"
|
||||
ref="submitted"
|
||||
data-cy="submitted"
|
||||
:error-messages="form().serverErrors(this, 'submitted')"
|
||||
@input="fieldValueChanged('submitted')"
|
||||
></gz-date-time-picker>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'PMDateApproved') &&
|
||||
!(
|
||||
value.userIsSubContractorFull ||
|
||||
value.userIsSubContractorRestricted
|
||||
)
|
||||
"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-date-time-picker
|
||||
:label="$ay.t('PMDateApproved')"
|
||||
v-model="value.approved"
|
||||
:readonly="formState.readOnly || value.userIsTechRestricted"
|
||||
ref="approved"
|
||||
data-cy="approved"
|
||||
:error-messages="form().serverErrors(this, 'approved')"
|
||||
@input="fieldValueChanged('approved')"
|
||||
></gz-date-time-picker>
|
||||
</v-col> -->
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'Contract') &&
|
||||
!(
|
||||
value.userIsSubContractorFull ||
|
||||
value.userIsSubContractorRestricted
|
||||
)
|
||||
"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-pick-list
|
||||
:aya-type="$ay.ayt().Contract"
|
||||
:show-edit-icon="!value.userIsRestrictedType"
|
||||
v-model="value.contractId"
|
||||
:readonly="formState.readOnly || value.userIsTechRestricted"
|
||||
:label="$ay.t('Contract')"
|
||||
ref="contractId"
|
||||
data-cy="contractId"
|
||||
:error-messages="form().serverErrors(this, 'contractId')"
|
||||
@input="fieldValueChanged('contractId')"
|
||||
></gz-pick-list>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'Project') &&
|
||||
!(
|
||||
value.userIsSubContractorFull ||
|
||||
value.userIsSubContractorRestricted
|
||||
)
|
||||
"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<gz-pick-list
|
||||
:aya-type="$ay.ayt().Project"
|
||||
:show-edit-icon="!value.userIsRestrictedType"
|
||||
v-model="value.projectId"
|
||||
:readonly="formState.readOnly || value.userIsTechRestricted"
|
||||
:label="$ay.t('Project')"
|
||||
ref="projectId"
|
||||
data-cy="projectId"
|
||||
:error-messages="form().serverErrors(this, 'projectId')"
|
||||
@input="fieldValueChanged('projectId')"
|
||||
></gz-pick-list>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="form().showMe(this, 'WorkOrderCustomerContactName')"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<v-text-field
|
||||
v-model="value.customerContactName"
|
||||
:readonly="
|
||||
formState.readOnly ||
|
||||
value.userIsTechRestricted ||
|
||||
value.userIsSubContractorFull ||
|
||||
value.userIsSubContractorRestricted
|
||||
"
|
||||
:label="$ay.t('WorkOrderCustomerContactName')"
|
||||
ref="customerContactName"
|
||||
data-cy="customerContactName"
|
||||
:error-messages="form().serverErrors(this, 'customerContactName')"
|
||||
@input="fieldValueChanged('customerContactName')"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'WorkOrderCustomerReferenceNumber') &&
|
||||
!(
|
||||
value.userIsSubContractorFull ||
|
||||
value.userIsSubContractorRestricted
|
||||
)
|
||||
"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<v-text-field
|
||||
v-model="value.customerReferenceNumber"
|
||||
:readonly="formState.readOnly || value.userIsTechRestricted"
|
||||
:label="$ay.t('WorkOrderCustomerReferenceNumber')"
|
||||
ref="customerReferenceNumber"
|
||||
data-cy="customerReferenceNumber"
|
||||
:error-messages="form().serverErrors(this, 'customerReferenceNumber')"
|
||||
@input="fieldValueChanged('customerReferenceNumber')"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'WorkOrderInternalReferenceNumber') &&
|
||||
!(
|
||||
value.userIsSubContractorFull ||
|
||||
value.userIsSubContractorRestricted
|
||||
)
|
||||
"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<v-text-field
|
||||
v-model="value.internalReferenceNumber"
|
||||
:readonly="formState.readOnly || value.userIsTechRestricted"
|
||||
:label="$ay.t('WorkOrderInternalReferenceNumber')"
|
||||
ref="internalReferenceNumber"
|
||||
data-cy="internalReferenceNumber"
|
||||
:error-messages="form().serverErrors(this, 'internalReferenceNumber')"
|
||||
@input="fieldValueChanged('internalReferenceNumber')"
|
||||
></v-text-field>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'WorkOrderOnsite') &&
|
||||
!(
|
||||
value.userIsSubContractorFull ||
|
||||
value.userIsSubContractorRestricted
|
||||
)
|
||||
"
|
||||
cols="12"
|
||||
sm="6"
|
||||
lg="4"
|
||||
xl="3"
|
||||
>
|
||||
<v-checkbox
|
||||
v-model="value.onsite"
|
||||
:readonly="formState.readOnly || value.userIsTechRestricted"
|
||||
:label="$ay.t('WorkOrderOnsite')"
|
||||
ref="onsite"
|
||||
data-cy="onsite"
|
||||
:error-messages="form().serverErrors(this, 'onsite')"
|
||||
@change="fieldValueChanged('onsite')"
|
||||
></v-checkbox>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'Tags') &&
|
||||
!(
|
||||
value.userIsSubContractorFull ||
|
||||
value.userIsSubContractorRestricted
|
||||
)
|
||||
"
|
||||
cols="12"
|
||||
>
|
||||
<gz-tag-picker
|
||||
v-model="value.tags"
|
||||
:readonly="formState.readOnly || value.userIsTechRestricted"
|
||||
ref="tags"
|
||||
data-cy="tags"
|
||||
:error-messages="form().serverErrors(this, 'tags')"
|
||||
@input="fieldValueChanged('tags')"
|
||||
></gz-tag-picker>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
!(
|
||||
value.userIsSubContractorFull || value.userIsSubContractorRestricted
|
||||
)
|
||||
"
|
||||
cols="12"
|
||||
>
|
||||
<gz-custom-fields
|
||||
v-model="value.customFields"
|
||||
:form-key="formCustomTemplateKey"
|
||||
:readonly="formState.readOnly || value.userIsTechRestricted"
|
||||
:parent-v-m="this"
|
||||
key-start-with="WorkOrderCustom"
|
||||
ref="customFields"
|
||||
data-cy="customFields"
|
||||
:error-messages="form().serverErrors(this, 'customFields')"
|
||||
@input="fieldValueChanged('customFields')"
|
||||
></gz-custom-fields>
|
||||
</v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'Wiki') &&
|
||||
!(
|
||||
value.userIsSubContractorFull ||
|
||||
value.userIsSubContractorRestricted
|
||||
)
|
||||
"
|
||||
cols="12"
|
||||
>
|
||||
<gz-wiki
|
||||
:aya-type="pvm.ayaType"
|
||||
:aya-id="value.id"
|
||||
ref="wiki"
|
||||
v-model="value.wiki"
|
||||
:readonly="formState.readOnly || value.userIsTechRestricted"
|
||||
@input="fieldValueChanged('wiki')"
|
||||
></gz-wiki
|
||||
></v-col>
|
||||
|
||||
<v-col
|
||||
v-if="
|
||||
form().showMe(this, 'Attachments') &&
|
||||
value.id &&
|
||||
!(
|
||||
value.userIsSubContractorFull ||
|
||||
value.userIsSubContractorRestricted
|
||||
)
|
||||
"
|
||||
cols="12"
|
||||
>
|
||||
<gz-attachments
|
||||
:readonly="formState.readOnly || value.userIsTechRestricted"
|
||||
:aya-type="pvm.ayaType"
|
||||
:aya-id="value.id"
|
||||
></gz-attachments
|
||||
></v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* XXXeslint-disable */
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
import GzWoAddress from "./work-order-address.vue";
|
||||
export default {
|
||||
components: {
|
||||
GzWoAddress
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
canEditSerial: window.$gz.role.hasRole([
|
||||
window.$gz.role.AUTHORIZATION_ROLES.BizAdminFull
|
||||
])
|
||||
};
|
||||
},
|
||||
|
||||
props: {
|
||||
value: {
|
||||
default: null,
|
||||
type: Object
|
||||
},
|
||||
pvm: {
|
||||
default: null,
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
form() {
|
||||
return window.$gz.form;
|
||||
},
|
||||
async fieldValueChanged(ref) {
|
||||
if (!this.formState.loading && !this.formState.readonly) {
|
||||
//flag this record dirty so it gets picked up by save
|
||||
this.value.isDirty = true;
|
||||
window.$gz.form.fieldValueChanged(this.pvm, ref);
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
formState: function() {
|
||||
return this.pvm.formState;
|
||||
},
|
||||
formCustomTemplateKey: function() {
|
||||
return this.pvm.formCustomTemplateKey;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
l.Add(new FormField { TKey = "PMPreparedByID", FieldKey = "PMPreparedByID" });
|
||||
l.Add(new FormField { TKey = "PMIntroduction", FieldKey = "PMIntroduction" });
|
||||
l.Add(new FormField { TKey = "PMPMRequestDate", FieldKey = "PMPMRequestDate" });
|
||||
l.Add(new FormField { TKey = "PMValidUntilDate", FieldKey = "PMValidUntilDate" });
|
||||
l.Add(new FormField { TKey = "PMDateSubmitted", FieldKey = "PMDateSubmitted" });
|
||||
l.Add(new FormField { TKey = "PMDateApproved", FieldKey = "PMDateApproved" });
|
||||
l.Add(new FormField { TKey = "CopyWiki", FieldKey = "CopyWiki" });
|
||||
l.Add(new FormField { TKey = "CopyAttachments", FieldKey = "CopyAttachments" });
|
||||
|
||||
Example workorder
|
||||
{
|
||||
id: 10,
|
||||
concurrency: 7728489,
|
||||
serial: 10,
|
||||
notes: "Quae officia placeat aliquid ducimus consequatur quia.",
|
||||
wiki: null,
|
||||
customFields: null,
|
||||
tags: ["green", "zone6"],
|
||||
customerId: 12,
|
||||
projectId: null,
|
||||
internalReferenceNumber: "irf-3339",
|
||||
customerReferenceNumber: "crf-1889",
|
||||
customerContactName: "contact name here",
|
||||
fromPMId: null,
|
||||
fromPMId: null,
|
||||
fromCSRId: null,
|
||||
serviceDate: "2021-05-29T21:25:31.421011Z",
|
||||
completeByDate: "2021-06-03T21:25:31.421011Z",
|
||||
invoiceNumber: null,
|
||||
customerSignature: null,
|
||||
customerSignatureName: null,
|
||||
customerSignatureCaptured: "0001-01-01T00:00:00Z",
|
||||
postAddress: null,
|
||||
postCity: null,
|
||||
postRegion: null,
|
||||
postCountry: null,
|
||||
postCode: null,
|
||||
address: null,
|
||||
city: null,
|
||||
region: null,
|
||||
country: null,
|
||||
latitude: null,
|
||||
longitude: null,
|
||||
items: [
|
||||
{
|
||||
id: 21,
|
||||
concurrency: 7728489,
|
||||
notes: "itemnotes",
|
||||
wiki: null,
|
||||
customFields: null,
|
||||
tags: [],
|
||||
pmId: 10,
|
||||
techNotes: "technotes",
|
||||
workorderItemStatusId: null,
|
||||
workorderItemPriorityId: null,
|
||||
requestDate: "2021-05-29T21:25:31.421011Z",
|
||||
warrantyService: false,
|
||||
isDirty: false,
|
||||
expenses: [],
|
||||
labors: [],
|
||||
loans: [],
|
||||
parts: [],
|
||||
partRequests: [],
|
||||
scheduledUsers: [
|
||||
{
|
||||
id: 41,
|
||||
concurrency: 7728489,
|
||||
userId: 15,
|
||||
estimatedQuantity: 1.0,
|
||||
startDate: null,
|
||||
stopDate: null,
|
||||
serviceRateId: null,
|
||||
isDirty: false,
|
||||
pmItemId: 21
|
||||
},
|
||||
{
|
||||
id: 42,
|
||||
concurrency: 7728489,
|
||||
userId: 22,
|
||||
estimatedQuantity: 2.0,
|
||||
startDate: null,
|
||||
stopDate: null,
|
||||
serviceRateId: null,
|
||||
isDirty: false,
|
||||
pmItemId: 21
|
||||
}
|
||||
],
|
||||
tasks: [],
|
||||
travels: [],
|
||||
units: [],
|
||||
outsideServices: []
|
||||
},
|
||||
{
|
||||
id: 22,
|
||||
concurrency: 7728489,
|
||||
notes: "itemnotes",
|
||||
wiki: null,
|
||||
customFields: null,
|
||||
tags: [],
|
||||
pmId: 10,
|
||||
techNotes: "technotes",
|
||||
workorderItemStatusId: null,
|
||||
workorderItemPriorityId: null,
|
||||
requestDate: "2021-05-29T21:25:31.421011Z",
|
||||
warrantyService: false,
|
||||
isDirty: false,
|
||||
expenses: [],
|
||||
labors: [],
|
||||
loans: [],
|
||||
parts: [],
|
||||
partRequests: [],
|
||||
scheduledUsers: [
|
||||
{
|
||||
id: 43,
|
||||
concurrency: 7728489,
|
||||
userId: 24,
|
||||
estimatedQuantity: 1.0,
|
||||
startDate: null,
|
||||
stopDate: null,
|
||||
serviceRateId: null,
|
||||
isDirty: false,
|
||||
pmItemId: 22
|
||||
},
|
||||
{
|
||||
id: 44,
|
||||
concurrency: 7728489,
|
||||
userId: 40,
|
||||
estimatedQuantity: 2.0,
|
||||
startDate: null,
|
||||
stopDate: null,
|
||||
serviceRateId: null,
|
||||
isDirty: false,
|
||||
pmItemId: 22
|
||||
}
|
||||
],
|
||||
tasks: [],
|
||||
travels: [],
|
||||
units: [],
|
||||
outsideServices: []
|
||||
}
|
||||
],
|
||||
states: [
|
||||
{
|
||||
id: 37,
|
||||
concurrency: 7728489,
|
||||
pmId: 10,
|
||||
workOrderStatusId: 2,
|
||||
created: "2021-05-29T21:30:31.421011Z",
|
||||
userId: 37,
|
||||
isDirty: false,
|
||||
workOrderStatus: null
|
||||
},
|
||||
{
|
||||
id: 38,
|
||||
concurrency: 7728489,
|
||||
pmId: 10,
|
||||
workOrderStatusId: 3,
|
||||
created: "2021-05-29T22:25:31.421011Z",
|
||||
userId: 10,
|
||||
isDirty: false,
|
||||
workOrderStatus: null
|
||||
},
|
||||
{
|
||||
id: 39,
|
||||
concurrency: 7728489,
|
||||
pmId: 10,
|
||||
workOrderStatusId: 1,
|
||||
created: "2021-05-29T22:30:31.421011Z",
|
||||
userId: 31,
|
||||
isDirty: false,
|
||||
workOrderStatus: null
|
||||
},
|
||||
{
|
||||
id: 40,
|
||||
concurrency: 7728489,
|
||||
pmId: 10,
|
||||
workOrderStatusId: 3,
|
||||
created: "2021-05-29T23:25:31.421011Z",
|
||||
userId: 2,
|
||||
isDirty: false,
|
||||
workOrderStatus: null
|
||||
},
|
||||
{
|
||||
id: 41,
|
||||
concurrency: 7728489,
|
||||
pmId: 10,
|
||||
workOrderStatusId: 9,
|
||||
created: "2021-04-06T00:10:44.636Z",
|
||||
userId: 1,
|
||||
isDirty: false,
|
||||
workOrderStatus: null
|
||||
}
|
||||
],
|
||||
isDirty: false,
|
||||
isLockedAtServer: false
|
||||
};
|
||||
|
||||
|
||||
*/
|
||||
</script>
|
||||
798
ayanova/src/components/pm-item-expenses.vue
Normal file
798
ayanova/src/components/pm-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,
|
||||
pmItemId: 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/pm-item-labors.vue
Normal file
997
ayanova/src/components/pm-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,
|
||||
pmItemId: 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/pm-item-loans.vue
Normal file
885
ayanova/src/components/pm-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,
|
||||
pmItemId: 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/pm-item-outside-services.vue
Normal file
1098
ayanova/src/components/pm-item-outside-services.vue
Normal file
File diff suppressed because it is too large
Load Diff
1129
ayanova/src/components/pm-item-parts.vue
Normal file
1129
ayanova/src/components/pm-item-parts.vue
Normal file
File diff suppressed because it is too large
Load Diff
710
ayanova/src/components/pm-item-scheduled-users.vue
Normal file
710
ayanova/src/components/pm-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,
|
||||
pmItemId: 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,
|
||||
pmItemId: 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/pm-item-tasks.vue
Normal file
644
ayanova/src/components/pm-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,
|
||||
pmItemId: 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,
|
||||
pmItemId: 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/pm-item-travels.vue
Normal file
976
ayanova/src/components/pm-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,
|
||||
pmItemId: 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/pm-item-units.vue
Normal file
850
ayanova/src/components/pm-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,
|
||||
pmItemId: 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",
|
||||
// "pmItemId": 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,
|
||||
pmItemId: 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>
|
||||
1249
ayanova/src/components/pm-items.vue
Normal file
1249
ayanova/src/components/pm-items.vue
Normal file
File diff suppressed because it is too large
Load Diff
@@ -392,14 +392,6 @@ export default new Router({
|
||||
)
|
||||
},
|
||||
|
||||
{
|
||||
path: "/svc-workorder-templates",
|
||||
name: "svc-workorder-templates",
|
||||
component: () =>
|
||||
import(
|
||||
/* webpackChunkName: "svc" */ "./views/svc-workorder-templates.vue"
|
||||
)
|
||||
},
|
||||
{
|
||||
path: "/svc-quotes",
|
||||
name: "svc-quotes",
|
||||
@@ -429,16 +421,16 @@ export default new Router({
|
||||
},
|
||||
|
||||
{
|
||||
path: "/svc-pm-list",
|
||||
name: "svc-pm-list",
|
||||
path: "/svc-pms",
|
||||
name: "svc-pms",
|
||||
component: () =>
|
||||
import(/* webpackChunkName: "svc" */ "./views/svc-pm-list.vue")
|
||||
import(/* webpackChunkName: "svc" */ "./views/svc-pms.vue")
|
||||
},
|
||||
{
|
||||
path: "/svc-pm-templates",
|
||||
name: "svc-pm-templates",
|
||||
path: "/svc-pms/:recordid",
|
||||
name: "pm-edit",
|
||||
component: () =>
|
||||
import(/* webpackChunkName: "svc" */ "./views/svc-pm-templates.vue")
|
||||
import(/* webpackChunkName: "svc" */ "./views/svc-pm.vue")
|
||||
},
|
||||
{
|
||||
path: "/svc-units",
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
<template>
|
||||
<UnderConstruction data-cy="underconstruction" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import UnderConstruction from "../components/underconstruction.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
UnderConstruction
|
||||
},
|
||||
beforeCreate() {
|
||||
window.$gz.eventBus.$emit("menu-change", {
|
||||
isMain: true,
|
||||
icon: "$ayiBusinessTime",
|
||||
title: "PMList",
|
||||
helpUrl: "svc-pm-list"
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,21 +0,0 @@
|
||||
<template>
|
||||
<UnderConstruction data-cy="underconstruction" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import UnderConstruction from "../components/underconstruction.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
UnderConstruction
|
||||
},
|
||||
beforeCreate() {
|
||||
window.$gz.eventBus.$emit("menu-change", {
|
||||
isMain: true,
|
||||
icon: "$ayiStamp",
|
||||
title: "PMTemplate",
|
||||
helpUrl: "svc-pm-templates"
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
2102
ayanova/src/views/svc-pm.vue
Normal file
2102
ayanova/src/views/svc-pm.vue
Normal file
File diff suppressed because it is too large
Load Diff
295
ayanova/src/views/svc-pms.vue
Normal file
295
ayanova/src/views/svc-pms.vue
Normal file
@@ -0,0 +1,295 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-row justify="center">
|
||||
<v-dialog
|
||||
@keydown.esc="openDialog = false"
|
||||
@keydown.enter="openPM()"
|
||||
v-model="openDialog"
|
||||
persistent
|
||||
max-width="600px"
|
||||
>
|
||||
<v-card>
|
||||
<v-card-title>
|
||||
<span class="text-h5">{{ $ay.t("Open") }}</span>
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
<v-text-field
|
||||
v-model="openPMNumber"
|
||||
:label="$ay.t('PM')"
|
||||
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="openDialog = false">{{
|
||||
$ay.t("Cancel")
|
||||
}}</v-btn>
|
||||
<v-btn
|
||||
color="blue darken-1"
|
||||
text
|
||||
@click="openPM()"
|
||||
:disabled="!openPMNumber"
|
||||
>{{ $ay.t("OK") }}</v-btn
|
||||
>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</v-row>
|
||||
<gz-report-selector ref="reportSelector"></gz-report-selector>
|
||||
<gz-extensions
|
||||
:aya-type="aType"
|
||||
:selected-items="selectedItems"
|
||||
ref="extensions"
|
||||
>
|
||||
</gz-extensions>
|
||||
|
||||
<gz-data-table
|
||||
ref="gzdatatable"
|
||||
form-key="pm-list"
|
||||
data-list-key="PMDataList"
|
||||
:show-select="rights.read"
|
||||
:reload="reload"
|
||||
@selection-change="handleSelected"
|
||||
data-cy="pmsTable"
|
||||
:client-criteria="clientCriteria"
|
||||
:pre-filter-mode="preFilterMode"
|
||||
@clear-pre-filter="clearPreFilter"
|
||||
>
|
||||
</gz-data-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const FORM_KEY = "pm-list";
|
||||
export default {
|
||||
async created() {
|
||||
this.rights = window.$gz.role.getRights(window.$gz.type.PM);
|
||||
window.$gz.eventBus.$on("menu-click", clickHandler);
|
||||
await fetchTranslatedText();
|
||||
|
||||
//------ Show all ----
|
||||
//OPTIONAL "Show All" FILTER
|
||||
this.objectId = window.$gz.util.stringToIntOrNull(
|
||||
this.$route.params.objectId
|
||||
);
|
||||
this.aForType = window.$gz.util.stringToIntOrNull(this.$route.params.aType);
|
||||
|
||||
if (this.objectId && this.objectId != 0 && this.aForType) {
|
||||
//OBJECTID,AYATYPE
|
||||
this.clientCriteria = `${this.objectId},${this.aForType}`;
|
||||
|
||||
this.preFilterMode = {
|
||||
icon: window.$gz.util.iconForType(this.aForType),
|
||||
id: this.objectId,
|
||||
ayatype: this.aForType,
|
||||
viz: this.$route.params.name,
|
||||
clearable: true
|
||||
};
|
||||
}
|
||||
//------ /show all ----
|
||||
|
||||
generateMenu(this);
|
||||
},
|
||||
beforeDestroy() {
|
||||
window.$gz.eventBus.$off("menu-click", clickHandler);
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
rights: window.$gz.role.defaultRightsObject(),
|
||||
aType: window.$gz.type.PM,
|
||||
selectedItems: [],
|
||||
reload: false,
|
||||
openDialog: false,
|
||||
openPMNumber: null,
|
||||
clientCriteria: undefined,
|
||||
preFilterMode: null,
|
||||
objectId: null,
|
||||
aForType: null,
|
||||
name: null
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleSelected(selected) {
|
||||
this.selectedItems = selected;
|
||||
},
|
||||
clearPreFilter() {
|
||||
this.clientCriteria = null;
|
||||
this.preFilterMode = null;
|
||||
this.reload = !this.reload;
|
||||
},
|
||||
|
||||
async openPM() {
|
||||
if (!this.openPMNumber) {
|
||||
return;
|
||||
}
|
||||
//get id from number then push open
|
||||
let res = await window.$gz.api.get(
|
||||
"pm/id-from-number/" + this.openPMNumber
|
||||
);
|
||||
if (res.error) {
|
||||
window.$gz.eventBus.$emit(
|
||||
"notify-warning",
|
||||
window.$gz.errorHandler.errorToString(res, this)
|
||||
);
|
||||
return;
|
||||
// throw new Error(window.$gz.errorHandler.errorToString(res, this));
|
||||
}
|
||||
|
||||
this.$router.push({
|
||||
name: "pm-edit",
|
||||
params: { recordid: res.data }
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////
|
||||
//
|
||||
//
|
||||
async function clickHandler(menuItem) {
|
||||
if (!menuItem) {
|
||||
return;
|
||||
}
|
||||
let m = window.$gz.menu.parseMenuItem(menuItem);
|
||||
if (m.owner == FORM_KEY && !m.disabled) {
|
||||
switch (m.key) {
|
||||
case "new":
|
||||
m.vm.$router.push({
|
||||
name: "pm-edit",
|
||||
params: { recordid: 0 }
|
||||
});
|
||||
break;
|
||||
case "extensions":
|
||||
let res = await m.vm.$refs.extensions.open(
|
||||
m.vm.$refs.gzdatatable.getDataListSelection(window.$gz.type.PM)
|
||||
);
|
||||
if (res && res.refresh == true) {
|
||||
m.vm.reload = !m.vm.reload;
|
||||
}
|
||||
break;
|
||||
case "report":
|
||||
if (m.id != null) {
|
||||
//last report selected is in m.id
|
||||
m.vm.$router.push({
|
||||
name: "ay-report",
|
||||
params: { recordid: m.id, ayatype: window.$gz.type.PM }
|
||||
});
|
||||
} else {
|
||||
//general report selector chosen
|
||||
|
||||
let res = await m.vm.$refs.reportSelector.open(
|
||||
m.vm.$refs.gzdatatable.getDataListSelection(window.$gz.type.PM)
|
||||
);
|
||||
|
||||
//if null for no selection
|
||||
//just bail out
|
||||
if (res == null) {
|
||||
return;
|
||||
}
|
||||
//persist last report selected
|
||||
window.$gz.form.setLastReport(FORM_KEY, res);
|
||||
|
||||
//Now open the report viewer...
|
||||
m.vm.$router.push({
|
||||
name: "ay-report",
|
||||
params: { recordid: res.id, ayatype: window.$gz.type.PM }
|
||||
});
|
||||
}
|
||||
break;
|
||||
case "PMItemList":
|
||||
m.vm.$router.push({
|
||||
name: "svc-pm-items"
|
||||
});
|
||||
break;
|
||||
case "open":
|
||||
m.vm.openDialog = true;
|
||||
break;
|
||||
default:
|
||||
window.$gz.eventBus.$emit(
|
||||
"notify-warning",
|
||||
FORM_KEY + "::context click: [" + m.key + "]"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
//
|
||||
//
|
||||
function generateMenu(vm) {
|
||||
let menuOptions = {
|
||||
isMain: true,
|
||||
icon: "$ayiBusinessTime",
|
||||
title: "PMList",
|
||||
helpUrl: "svc-pms",
|
||||
menuItems: [],
|
||||
formData: {
|
||||
ayaType: window.$gz.type.PM
|
||||
}
|
||||
};
|
||||
|
||||
if (vm.rights.change) {
|
||||
menuOptions.menuItems.push({
|
||||
title: "New",
|
||||
icon: "$ayiPlus",
|
||||
surface: true,
|
||||
key: FORM_KEY + ":new",
|
||||
vm: vm
|
||||
});
|
||||
}
|
||||
|
||||
//REPORTS
|
||||
//Report not Print, print is a further option
|
||||
menuOptions.menuItems.push({
|
||||
title: "Report",
|
||||
icon: "$ayiFileAlt",
|
||||
key: FORM_KEY + ":report",
|
||||
vm: vm
|
||||
});
|
||||
|
||||
//get last report selected
|
||||
let lastReport = window.$gz.form.getLastReport(FORM_KEY);
|
||||
if (lastReport != null) {
|
||||
menuOptions.menuItems.push({
|
||||
title: lastReport.name,
|
||||
icon: "$ayiFileAlt",
|
||||
key: FORM_KEY + ":report:" + lastReport.id,
|
||||
vm: vm
|
||||
});
|
||||
}
|
||||
|
||||
menuOptions.menuItems.push({
|
||||
title: "Extensions",
|
||||
icon: "$ayiPuzzlePiece",
|
||||
key: FORM_KEY + ":extensions",
|
||||
vm: vm
|
||||
});
|
||||
menuOptions.menuItems.push({
|
||||
title: "Open",
|
||||
icon: "$ayiTools",
|
||||
key: FORM_KEY + ":open",
|
||||
vm: vm
|
||||
});
|
||||
menuOptions.menuItems.push({ divider: true, inset: false });
|
||||
|
||||
menuOptions.menuItems.push({
|
||||
title: "PMItemList",
|
||||
icon: "$ayiWrench",
|
||||
key: FORM_KEY + ":PMItemList",
|
||||
vm: vm
|
||||
});
|
||||
|
||||
menuOptions.menuItems.push({ divider: true, inset: false });
|
||||
|
||||
window.$gz.eventBus.$emit("menu-change", menuOptions);
|
||||
}
|
||||
//////////////////////////////////////////////////////////
|
||||
//
|
||||
// Ensures UI translated text is available
|
||||
//
|
||||
async function fetchTranslatedText() {
|
||||
await window.$gz.translation.cacheTranslations(["PM"]);
|
||||
}
|
||||
</script>
|
||||
@@ -1,21 +0,0 @@
|
||||
<template>
|
||||
<UnderConstruction data-cy="underconstruction" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import UnderConstruction from "../components/underconstruction.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
UnderConstruction
|
||||
},
|
||||
beforeCreate() {
|
||||
window.$gz.eventBus.$emit("menu-change", {
|
||||
isMain: true,
|
||||
icon: "$ayiStamp",
|
||||
title: "WorkOrderQuoteTemplate",
|
||||
helpUrl: "svc-quote-templates"
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1947,7 +1947,6 @@ async function fetchTranslatedText(vm) {
|
||||
"WorkOrderCustomerReferenceNumber",
|
||||
"WorkOrderInternalReferenceNumber",
|
||||
"WorkOrderOnsite",
|
||||
"NewStatus",
|
||||
"QuoteQuoteStatusType",
|
||||
"WorkOrderCustom1",
|
||||
"WorkOrderCustom2",
|
||||
@@ -2150,8 +2149,6 @@ async function fetchTranslatedText(vm) {
|
||||
"RecentWorkOrders",
|
||||
"WorkOrderGenerateUnit",
|
||||
"ApplyUnitContract",
|
||||
"WorkOrderFromQuoteID",
|
||||
"WorkOrderFromPMID",
|
||||
"CustomerServiceRequest"
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
<template>
|
||||
<UnderConstruction data-cy="underconstruction" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import UnderConstruction from "../components/underconstruction.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
UnderConstruction
|
||||
},
|
||||
beforeCreate() {
|
||||
window.$gz.eventBus.$emit("menu-change", {
|
||||
isMain: true,
|
||||
icon: "$ayiStamp",
|
||||
title: "WorkOrderServiceTemplate",
|
||||
helpUrl: "svc-workorder-templates"
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -2138,7 +2138,6 @@ async function fetchTranslatedText(vm) {
|
||||
"WorkOrderCustomerReferenceNumber",
|
||||
"WorkOrderInternalReferenceNumber",
|
||||
"WorkOrderOnsite",
|
||||
"NewStatus",
|
||||
"WorkOrderStatus",
|
||||
"WorkOrderCustom1",
|
||||
"WorkOrderCustom2",
|
||||
|
||||
Reference in New Issue
Block a user