This commit is contained in:
2021-05-10 15:17:11 +00:00
parent ab9b953d9b
commit 021af706cf
4 changed files with 544 additions and 2 deletions

View File

@@ -307,7 +307,6 @@ todo: many biz objects are not using new PUT methodology
CURRENTLY DOING: CURRENTLY DOING:
todo: start/stop date biz rules precedence on form at back
todo: workorder item expense next collection (easing into it) todo: workorder item expense next collection (easing into it)
@@ -335,6 +334,9 @@ OVERALL
##################################################################### #####################################################################
=================== WORKORDER TODO / ON HOLD ======================== =================== WORKORDER TODO / ON HOLD ========================
todo: make sure all rules are mirrored at both ends (like date precedence etc)
TODO: Test address / units select alternate when have units working TODO: Test address / units select alternate when have units working
TODO: Sequence field sb hidden by default, most won't want it I'm guessing TODO: Sequence field sb hidden by default, most won't want it I'm guessing
really need to pin down some default form customization for wo really need to pin down some default form customization for wo

View File

@@ -0,0 +1,518 @@
<template>
<div v-if="value != null">
<v-row>
<v-col cols="12">
<v-menu offset-y>
<template v-slot:activator="{ on, attrs }">
<div class="text-subtitle-1">
<v-icon color="primary">$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="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="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>
</v-menu>
</v-col>
<template v-if="showTable">
<!-- ################################ 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="activeItemIndex != null">
<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"
: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"
: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"
: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="true"
v-model="
value.items[activeWoItemIndex].scheduledUsers[activeItemIndex]
.userId
"
:readonly="formState.readOnly || isDeleted"
: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"
:show-edit-icon="true"
v-model="
value.items[activeWoItemIndex].scheduledUsers[activeItemIndex]
.serviceRateId
"
:readonly="formState.readOnly || isDeleted"
: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
}
},
watch: {
activeWoItemIndex(val, oldVal) {
if (val != oldVal) {
this.setDefaultView();
}
}
},
methods: {
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: null,
estimatedQuantity: 0,
startDate: null,
stopDate: null,
serviceRateId: null,
isDirty: true,
workOrderItemId: this.value.items[this.activeWoItemIndex].id,
uid: Date.now() //used for error tracking / display
});
this.$emit("change");
this.selectedRow = [{ index: newIndex }];
this.activeItemIndex = newIndex;
},
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");
},
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);
// //set viz if applicable
// if(ref==""){
// let selectedPartWarehouse = vm.$refs.partWarehouseId.getFullSelectionValue();
// }
}
},
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;
},
showTable: function() {
return this.value.items[this.activeWoItemIndex].scheduledUsers.length > 1;
},
canAdd: function() {
return this.pvm.rights.change && this.pvm.subRights.scheduledUsers.create;
},
canDelete: function() {
return (
this.activeItemIndex != null &&
this.pvm.rights.change &&
this.pvm.subRights.scheduledUsers.delete
);
}
}
};
</script>

View File

@@ -120,6 +120,13 @@
`Items[${activeWoItemIndex}].scheduledUsers[${activeItemIndex}].stopDate` `Items[${activeWoItemIndex}].scheduledUsers[${activeItemIndex}].stopDate`
" "
data-cy="stopDate" data-cy="stopDate"
:rules="[
form().datePrecedence(
this,
`Items[${activeWoItemIndex}].scheduledUsers[${activeItemIndex}].startDate`,
`Items[${activeWoItemIndex}].scheduledUsers[${activeItemIndex}].stopDate`
)
]"
:error-messages=" :error-messages="
form().serverErrors( form().serverErrors(
this, this,

View File

@@ -361,6 +361,19 @@
@change="$emit('change')" @change="$emit('change')"
/> />
</v-col> </v-col>
<v-col cols="12">
<GzWoItemScheduledUsers
v-if="
pvm.subRights.scheduledUsers.visible &&
form().showMe(this, 'WorkOrderItemScheduledUserList')
"
v-model="value"
:pvm="pvm"
:active-wo-item-index="activeItemIndex"
data-cy="woItemScheduledUsers"
@change="$emit('change')"
/>
</v-col>
</template> </template>
</v-row> </v-row>
</div> </div>
@@ -370,10 +383,12 @@
/* XXXeslint-disable */ /* XXXeslint-disable */
//////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////
import GzWoItemScheduledUsers from "../components/work-order-item-scheduled-users.vue"; import GzWoItemScheduledUsers from "../components/work-order-item-scheduled-users.vue";
import GzWoItemExpenses from "../components/work-order-item-expenses.vue";
export default { export default {
components: { components: {
GzWoItemScheduledUsers GzWoItemScheduledUsers,
GzWoItemExpenses
}, },
created() { created() {
this.setDefaultView(); this.setDefaultView();