Files
sockeye-client/src/views/biz-subscription.vue

1481 lines
47 KiB
Vue

<template>
<div>
<gz-report-selector ref="reportSelector"></gz-report-selector>
<div v-if="formState.ready">
<gz-error :error-box-message="formState.errorBoxMessage"></gz-error>
<v-form ref="form">
<v-row dense>
<v-col cols="12" sm="6" lg="4" xl="3">
<gz-pick-list
ref="customerId"
v-model="obj.customerId"
:aya-type="sockTypes().Customer"
show-edit-icon
:readonly="formState.readOnly"
:label="$sock.t('Customer')"
:error-messages="form().serverErrors(this, 'customerId')"
:rules="[form().required(this, 'customerId')]"
@input="fieldValueChanged('customerId')"
@update:name="customerChanged"
></gz-pick-list>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-select
ref="pGroup"
v-model="obj.pGroup"
dense
:items="selectLists.pGroups"
item-text="name"
item-value="id"
:readonly="formState.readOnly"
:label="$sock.t('ProductGroup')"
data-cy="pGroup"
:rules="[form().integerValid(this, 'pGroup')]"
:error-messages="form().serverErrors(this, 'pGroup')"
@input="fieldValueChanged('pGroup')"
></v-select>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-text-field
ref="subsite"
v-model="obj.subsite"
dense
:readonly="formState.readOnly"
:label="$sock.t('SubSite')"
:error-messages="form().serverErrors(this, 'subsite')"
data-cy="subsite"
@input="fieldValueChanged('subsite')"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-text-field
ref="regTo"
v-model="obj.regTo"
dense
:readonly="formState.readOnly"
:label="$sock.t('LicenseRegTo')"
:rules="[form().required(this, 'regTo')]"
:error-messages="form().serverErrors(this, 'regTo')"
data-cy="regTo"
@input="fieldValueChanged('regTo')"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<gz-email
ref="fetchEmail"
v-model="obj.fetchEmail"
:readonly="formState.readOnly"
:label="$sock.t('LicenseFetchEmail')"
data-cy="fetchEmail"
:error-messages="form().serverErrors(this, 'fetchEmail')"
@input="fieldValueChanged('fetchEmail')"
></gz-email>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-text-field
ref="dbId"
v-model="obj.dbId"
dense
:readonly="formState.readOnly"
:label="$sock.t('DatabaseID')"
:rules="[form().required(this, 'dbId')]"
:error-messages="form().serverErrors(this, 'dbId')"
data-cy="dbId"
@input="fieldValueChanged('dbId')"
></v-text-field>
</v-col>
<!-- ################################ SUBSCRIPTION ITEMS LIST ############################### -->
<v-col cols="12" class="mb-6">
<v-data-table
:headers="headerList"
:items="itemList"
item-key="index"
class="elevation-1"
disable-pagination
disable-filtering
disable-sort
hide-default-footer
data-cy="itemsTable"
dense
:item-class="itemsRowClasses"
:no-data-text="$sock.t('NoData')"
>
<!-- <template v-slot:[`item.productViz`]="{ item }">
<div class="subtitle-1" @click="openItem(item)">
<a href="javascript:"> {{ item.productViz }}</a>
</div>
</template> -->
<template v-slot:top>
<v-col cols="12">
<v-menu v-if="rights.change" offset-y>
<template v-slot:activator="{ on, attrs }">
<span class="text-subtitle-2">
{{ $sock.t("SubscriptionItemList") }}</span
><v-btn large icon v-bind="attrs" v-on="on">
<v-icon small color="primary">$sockiEllipsisV</v-icon>
</v-btn>
</template>
<v-list>
<v-list-item @click="newItem">
<v-list-item-icon>
<v-icon>$sockiPlus</v-icon>
</v-list-item-icon>
<v-list-item-title>{{
$sock.t("New")
}}</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
<span v-else class="text-h6">
{{ $sock.t("SubscriptionItemList") }}</span
>
</v-col>
</template>
<template v-slot:[`item.renewal`]="{ item }">
<v-simple-checkbox
v-model="item.renewal"
disabled
></v-simple-checkbox>
</template>
<template v-slot:[`item.active`]="{ item }">
<v-simple-checkbox
v-model="item.active"
disabled
></v-simple-checkbox>
</template>
<template v-slot:[`item.actions`]="{ item }">
<v-btn icon @click="editItem(item)">
<v-icon :class="itemsRowClasses(item)">
$sockiEdit
</v-icon>
</v-btn>
</template>
</v-data-table>
</v-col>
<!-- --------------------------------- -->
<v-col v-if="form().showMe(this, 'Notes')" cols="12">
<v-textarea
ref="notes"
v-model="obj.notes"
dense
:readonly="formState.readOnly"
:label="$sock.t('ContractNotes')"
:error-messages="form().serverErrors(this, 'notes')"
data-cy="notes"
auto-grow
@input="fieldValueChanged('notes')"
></v-textarea>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-checkbox
ref="active"
v-model="obj.active"
dense
:readonly="formState.readOnly"
:label="$sock.t('Active')"
data-cy="active"
:error-messages="form().serverErrors(this, 'active')"
@change="fieldValueChanged('active')"
></v-checkbox>
</v-col>
<!-- --------------------------------- -->
<v-col v-if="form().showMe(this, 'Tags')" cols="12">
<gz-tag-picker
ref="tags"
v-model="obj.tags"
:readonly="formState.readOnly"
data-cy="tags"
:error-messages="form().serverErrors(this, 'tags')"
@input="fieldValueChanged('tags')"
></gz-tag-picker>
</v-col>
<v-col v-if="form().showMe(this, 'Attachments') && obj.id" cols="12">
<gz-attachments
:readonly="formState.readOnly"
:aya-type="sockType"
:aya-id="obj.id"
></gz-attachments
></v-col>
</v-row>
</v-form>
</div>
<v-overlay :value="!formState.ready || formState.loading">
<v-progress-circular indeterminate :size="64" />
</v-overlay>
<!-- #########################################################################################-->
<!-- ########################## SUBSCRIPTION ITEM EDIT FORM ###############################-->
<!-- #########################################################################################-->
<template v-if="obj.items.length">
<v-row dense justify="center">
<v-dialog v-model="editItemDialog">
<v-card>
<v-card-title> </v-card-title>
<v-card-text>
<v-row dense>
<v-col cols="12" sm="6" lg="4" xl="3">
<gz-pick-list
ref="Items.ProductId"
v-model="obj.items[editItemIndex].productId"
:aya-type="sockTypes().Product"
:allow-no-selection="false"
show-edit-icon
:readonly="formState.readOnly"
:label="$sock.t('Product')"
data-cy="Items.ProductId"
:rules="[form().required(this, 'Items.ProductId')]"
:error-messages="
form().serverErrors(
this,
`Items[${editItemIndex}].productId`
)
"
@input="
fieldValueChanged(`Items[${editItemIndex}].productId`)
"
></gz-pick-list>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<gz-decimal
ref="Items.Quantity"
v-model="obj.items[editItemIndex].quantity"
:readonly="formState.readOnly"
:label="$sock.t('PurchaseQuantity')"
data-cy="Items.quantity"
:error-messages="
form().serverErrors(
this,
`Items[${editItemIndex}].quantity`
)
"
:rules="[
form().decimalValid(this, 'Items.quantity'),
form().required(this, 'Items.quantity')
]"
@input="
fieldValueChanged(`Items[${editItemIndex}].quantity`)
"
></gz-decimal>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-row no-gutters>
<v-col cols="1">
<v-menu offset-y>
<template v-slot:activator="{ on, attrs }">
<v-btn icon v-bind="attrs" v-on="on">
<v-icon small>$sockiPlus</v-icon>
</v-btn>
</template>
<v-list>
<!-- <v-list-item @click="subExpireAddOneWeek">
<v-list-item-icon>
<v-icon>$sockiPlus</v-icon>
</v-list-item-icon>
<v-list-item-title>One week</v-list-item-title>
</v-list-item> -->
<v-list-item @click="subExpireAddOneMonth">
<v-list-item-icon>
<v-icon>$sockiPlus</v-icon>
</v-list-item-icon>
<v-list-item-title
>One month + 7d</v-list-item-title
>
</v-list-item>
<v-list-item @click="subExpireAddOneYear">
<v-list-item-icon>
<v-icon>$sockiPlus</v-icon>
</v-list-item-icon>
<v-list-item-title>One year + 7d</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</v-col>
<v-col>
<gz-date-time-picker
ref="Items.expireDate"
v-model="obj.items[editItemIndex].expireDate"
:label="$sock.t('PurchaseExpireDate')"
:readonly="formState.readOnly"
:error-messages="
form().serverErrors(
this,
`Items[${editItemIndex}].expireDate`
)
"
:rules="[form().required(this, 'Items.expireDate')]"
@input="
fieldValueChanged(
`Items[${editItemIndex}].expireDate`
)
"
></gz-date-time-picker>
</v-col>
</v-row>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-checkbox
ref="renewal"
v-model="obj.items[editItemIndex].renewal"
dense
:readonly="formState.readOnly"
:label="$sock.t('Renewal')"
:error-messages="
form().serverErrors(
this,
`Items[${editItemIndex}].renewal`
)
"
@change="
fieldValueChanged(`Items[${editItemIndex}].renewal`)
"
></v-checkbox>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<gz-date-time-picker
ref="Items.originalOrderDate"
v-model="obj.items[editItemIndex].originalOrderDate"
:label="$sock.t('OriginalOrderDate')"
:readonly="formState.readOnly"
:error-messages="
form().serverErrors(
this,
`Items[${editItemIndex}].originalOrderDate`
)
"
:rules="[form().required(this, 'Items.originalOrderDate')]"
@input="
fieldValueChanged(
`Items[${editItemIndex}].originalOrderDate`
)
"
></gz-date-time-picker>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-text-field
ref="Items.originalOrderNumber"
v-model="obj.items[editItemIndex].originalOrderNumber"
dense
:label="$sock.t('OriginalOrderNumber')"
:readonly="formState.readOnly"
:error-messages="
form().serverErrors(
this,
`Items[${editItemIndex}].originalOrderNumber`
)
"
:rules="[
form().required(this, 'Items.originalOrderNumber')
]"
@input="
fieldValueChanged(
`Items[${editItemIndex}].originalOrderNumber`
)
"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" lg="4" xl="3">
<v-checkbox
ref="active"
v-model="obj.items[editItemIndex].active"
dense
:readonly="formState.readOnly"
:label="$sock.t('Active')"
:error-messages="
form().serverErrors(
this,
`Items[${editItemIndex}].active`
)
"
@change="
fieldValueChanged(`Items[${editItemIndex}].active`)
"
></v-checkbox>
</v-col>
</v-row>
</v-card-text>
<v-card-actions>
<template v-if="!$vuetify.breakpoint.xs">
<v-btn
color="red darken-1"
text
@click="deleteItem(obj.items[editItemIndex])"
>{{ $sock.t("Delete") }}</v-btn
>
<v-spacer></v-spacer>
<v-btn
color="blue darken-1"
text
@click="editItemDialog = false"
>{{ $sock.t("Close") }}</v-btn
>
<v-btn
color="blue darken-1"
text
class="ml-4"
@click="duplicateItem(obj.items[editItemIndex])"
>{{ $sock.t("Duplicate") }}</v-btn
>
<v-btn
color="blue darken-1"
text
class="ml-4"
@click="newItem()"
>{{ $sock.t("New") }}</v-btn
>
<v-btn
color="blue darken-1"
text
class="ml-4"
@click="submit()"
>{{ $sock.t("Save") }}</v-btn
>
</template>
<template v-else>
<!-- MOBILE FORMAT -->
<v-row dense>
<v-btn
class="mt-4"
block
text
color="blue darken-1"
@click="submit()"
>{{ $sock.t("Save") }}</v-btn
>
<v-btn
class="mt-4"
block
text
color="blue darken-1"
@click="duplicateItem(obj.items[editItemIndex])"
>{{ $sock.t("Duplicate") }}</v-btn
>
<v-btn
class="mt-4"
block
text
color="blue darken-1"
@click="newItem()"
>{{ $sock.t("New") }}</v-btn
>
<v-btn
class="mt-4"
block
text
color="blue darken-1"
@click="editItemDialog = false"
>{{ $sock.t("Close") }}</v-btn
>
<v-btn
class="mt-8 mb-6"
block
text
color="red darken-1"
@click="deleteItem(obj.items[editItemIndex])"
>{{ $sock.t("Delete") }}</v-btn
>
</v-row>
</template>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</template>
</div>
</template>
<script>
const FORM_KEY = "subscription-edit";
const API_BASE_URL = "subscription/";
const FORM_CUSTOM_TEMPLATE_KEY = "Subscription";
export default {
data() {
return {
formCustomTemplateKey: FORM_CUSTOM_TEMPLATE_KEY,
editItemDialog: false,
editItemIndex: 0,
obj: {
id: 0,
concurrency: 0,
customerId: null,
pGroup: null,
active: true,
subsite: "main",
regTo: null,
fetchEmail: null,
dbId: null,
items: [],
notes: null,
tags: []
},
formState: {
ready: false,
dirty: false,
valid: true,
readOnly: false,
loading: true,
errorBoxMessage: null,
appError: null,
serverError: {}
},
rights: window.$gz.role.defaultRightsObject(),
sockType: window.$gz.type.Subscription,
selectLists: {
pGroups: []
}
};
},
computed: {
headerList: function() {
const headers = [];
headers.push({
text: this.$sock.t("ProductName"),
align: "left",
value: "productViz"
});
headers.push({
text: this.$sock.t("PurchaseQuantity"),
align: "right",
value: "quantity"
});
headers.push({
text: this.$sock.t("Renewal"),
align: "center",
value: "renewal"
});
headers.push({
text: this.$sock.t("PurchaseExpireDate"),
align: "right",
value: "expireDate"
});
headers.push({
text: this.$sock.t("Active"),
align: "center",
value: "active"
});
if (!this.formState.readOnly) {
headers.push({ text: "", value: "actions" });
}
return headers;
},
itemList: function() {
return this.obj.items.map((x, i) => {
return {
index: i,
id: x.id,
quantity: window.$gz.locale.decimalLocalized(
x.quantity,
this.languageName
),
expireDate: window.$gz.locale.utcDateToShortDateAndTimeLocalized(
x.expireDate,
this.timeZoneName,
this.languageName,
this.hour12
),
active: x.active,
renewal: x.renewal,
productViz: x.productViz
};
});
}
},
watch: {
formState: {
handler: function(val) {
if (this.formState.loading) {
return;
}
if (val.dirty && val.valid && !val.readOnly) {
window.$gz.eventBus.$emit("menu-enable-item", FORM_KEY + ":save");
} else {
window.$gz.eventBus.$emit("menu-disable-item", FORM_KEY + ":save");
}
if (!val.dirty && val.valid && !val.readOnly) {
window.$gz.eventBus.$emit(
"menu-enable-item",
FORM_KEY + ":duplicate"
);
window.$gz.eventBus.$emit("menu-enable-item", FORM_KEY + ":license");
window.$gz.eventBus.$emit("menu-enable-item", FORM_KEY + ":new");
} else {
window.$gz.eventBus.$emit(
"menu-disable-item",
FORM_KEY + ":duplicate"
);
window.$gz.eventBus.$emit("menu-disable-item", FORM_KEY + ":license");
window.$gz.eventBus.$emit("menu-disable-item", FORM_KEY + ":new");
}
},
deep: true
}
},
async created() {
const vm = this;
try {
await initForm(vm);
vm.rights = window.$gz.role.getRights(window.$gz.type.Subscription);
vm.formState.readOnly = !vm.rights.change;
window.$gz.eventBus.$on("menu-click", clickHandler);
//---------------------------------
let setDirty = false;
//id 0 means create or duplicate to new
if (vm.$route.params.recordid != 0) {
//is there already an obj from a prior operation?
if (this.$route.params.obj) {
//yes, no need to fetch it
this.obj = this.$route.params.obj;
} else {
await vm.getDataFromApi(vm.$route.params.recordid);
}
} else {
//Might be a duplicate and contain another record
if (this.$route.params.obj) {
this.obj = this.$route.params.obj;
this.obj.concurrency = undefined;
this.obj.id = 0;
this.obj.name = `${this.obj.name} - ${window.$gz.translation.get(
"Copy"
)}`;
setDirty = true;
}
}
window.$gz.form.setFormState({
vm: vm,
loading: false,
dirty: setDirty,
valid: true
});
//----------------------------
generateMenu(vm);
} catch (error) {
window.$gz.errorHandler.handleFormError(error, vm);
} finally {
vm.formState.ready = true;
}
},
async beforeRouteLeave(to, from, next) {
if (!this.formState.dirty || JUST_DELETED) {
next();
return;
}
if ((await window.$gz.dialog.confirmLeaveUnsaved()) === true) {
next();
} else {
next(false);
}
},
beforeDestroy() {
window.$gz.eventBus.$off("menu-click", clickHandler);
},
methods: {
editItem: function(item) {
this.editItemIndex = item.index;
this.editItemDialog = true;
},
newItem: function() {
this.obj.items.push({
id: 0,
subscriptionId: 0,
productId: null,
quantity: 1,
expireDate: null, //deliberate to ensure a date gets set properly as some items are monthly and some yearly can't just assume a date here
originalOrderDate: window.$gz.locale.nowUTC8601String(),
originalOrderNumber: null,
active: true,
renewal: false
});
this.editItemIndex = this.obj.items.length - 1;
this.editItemDialog = true;
this.formState.dirty = true;
},
duplicateItem: function(src) {
this.obj.items.push({
id: 0,
subscriptionId: 0,
productId: null,
quantity: 1,
expireDate: src.expireDate,
originalOrderDate: src.originalOrderDate,
originalOrderNumber: src.originalOrderNumber,
active: true,
renewal: false
});
this.editItemIndex = this.obj.items.length - 1;
this.editItemDialog = true;
this.formState.dirty = true;
},
deleteItem: function() {
this.editItemDialog = false;
this.obj.items.splice(this.editItemIndex, 1);
this.editItemIndex = 0;
this.formState.dirty = true;
},
itemsRowClasses: function(item) {
const path = `Items[${item.index}].`;
if (this.form().childRowHasError(this, path)) {
return "font-weight-black font-italic error--text";
}
},
subExpireAddOneWeek: function() {
this.obj.items[this.editItemIndex].expireDate = addToDate(
this.obj.items[this.editItemIndex].expireDate,
{
days: 7
}
);
},
subExpireAddOneMonth: function() {
this.obj.items[this.editItemIndex].expireDate = addToDate(
this.obj.items[this.editItemIndex].expireDate,
{
months: 1,
days: 7
}
);
},
subExpireAddOneYear: function() {
this.obj.items[this.editItemIndex].expireDate = addToDate(
this.obj.items[this.editItemIndex].expireDate,
{
years: 1,
days: 7
}
);
// const now = window.$gz.locale.nowUTC8601String(this.timeZoneName);
// this.obj.items[
// this.editItemIndex
// ].expireDate = window.$gz.locale.addDurationToUTC8601String(now, {
// years: 1
// });
},
async customerChanged() {
const id = this.obj.customerId;
if (!id || id == 0) {
return;
}
const res = await window.$gz.api.get(`customer/${id}`);
if (res.error) {
window.$gz.eventBus.$emit(
"notify-warning",
window.$gz.errorHandler.errorToString(res, this)
);
} else {
//Use customer record to update stuff here
this.obj.fetchEmail = res.data.emailAddress;
this.obj.regTo = res.data.name;
this.obj.dbId = res.data.dbId;
}
},
canSave: function() {
return this.formState.valid && this.formState.dirty;
},
canDuplicate: function() {
return this.formState.valid && !this.formState.dirty;
},
sockTypes: function() {
return window.$gz.type;
},
form() {
return window.$gz.form;
},
fieldValueChanged(ref) {
if (
this.formState.ready &&
!this.formState.loading &&
!this.formState.readOnly
) {
window.$gz.form.fieldValueChanged(this, ref);
}
},
async getDataFromApi(recordId) {
const vm = this;
window.$gz.form.setFormState({
vm: vm,
loading: true
});
if (!recordId) {
throw new Error(FORM_KEY + "::getDataFromApi -> Missing recordID!");
}
try {
window.$gz.form.deleteAllErrorBoxErrors(vm);
const res = await window.$gz.api.get(API_BASE_URL + recordId);
if (res.error) {
if (res.error.code == "2010") {
window.$gz.form.handleObjectNotFound(vm);
}
vm.formState.serverError = res.error;
window.$gz.form.setErrorBoxErrors(vm);
} else {
vm.obj = res.data;
generateMenu(vm);
window.$gz.form.setFormState({
vm: vm,
dirty: false,
valid: true,
loading: false
});
}
} catch (error) {
window.$gz.errorHandler.handleFormError(error, vm);
} finally {
window.$gz.form.setFormState({
vm: vm,
loading: false
});
}
},
async submit() {
const vm = this;
if (vm.canSave == false) {
return;
}
try {
window.$gz.form.setFormState({
vm: vm,
loading: true
});
window.$gz.form.deleteAllErrorBoxErrors(vm);
const res = await window.$gz.api.upsert(API_BASE_URL, vm.obj);
if (res.error) {
vm.formState.serverError = res.error;
window.$gz.form.setErrorBoxErrors(vm);
} else {
//POST or PUT which is a little different than other objects
//so if it's new then need to navigate to it to update url with id
if (vm.$route.params.recordid != 0) {
//update of existing record
vm.obj = res.data;
} else {
this.$router.replace({
name: "subscription-edit",
params: {
recordid: res.data.id,
obj: res.data
}
});
}
window.$gz.form.setFormState({
vm: vm,
dirty: false,
valid: true
});
}
//{
// if (res.data.id) {
// //POST
// vm.obj = res.data;
// this.$router.replace({
// name: "subscription-edit",
// params: {
// recordid: res.data.id,
// obj: res.data
// }
// });
// } else {
// //PUT
// vm.obj.concurrency = res.data.concurrency;
// }
// window.$gz.form.setFormState({
// vm: vm,
// dirty: false,
// valid: true
// });
// }
} catch (ex) {
window.$gz.errorHandler.handleFormError(ex, vm);
} finally {
window.$gz.form.setFormState({
vm: vm,
loading: false
});
}
},
async remove() {
try {
const dialogResult = await window.$gz.dialog.confirmDelete();
if (dialogResult != true) {
return;
}
window.$gz.form.setFormState({
vm: this,
loading: true
});
if (this.$route.params.recordid == 0) {
JUST_DELETED = true;
this.$router.go(-1);
} else {
window.$gz.form.deleteAllErrorBoxErrors(this);
const res = await window.$gz.api.remove(
API_BASE_URL + this.$route.params.recordid
);
if (res.error) {
this.formState.serverError = res.error;
window.$gz.form.setErrorBoxErrors(this);
} else {
JUST_DELETED = true;
this.$router.go(-1);
}
}
} catch (error) {
window.$gz.errorHandler.handleFormError(error, this);
} finally {
window.$gz.form.setFormState({
vm: this,
loading: false
});
}
},
duplicate() {
this.$router.push({
name: "subscription-edit",
params: {
recordid: 0,
obj: this.obj
}
});
}
}
};
/////////////////////////////
//
//
async function clickHandler(menuItem) {
if (!menuItem) {
return;
}
const m = window.$gz.menu.parseMenuItem(menuItem);
if (m.owner == FORM_KEY && !m.disabled) {
switch (m.key) {
case "save":
m.vm.submit();
break;
case "delete":
m.vm.remove();
break;
case "new":
m.vm.$router.push({
name: "subscription-edit",
params: { recordid: 0 }
});
break;
case "duplicate":
m.vm.duplicate();
break;
case "report":
{
const res = await m.vm.$refs.reportSelector.open(
{
AType: window.$gz.type.Subscription,
selectedRowIds: [m.vm.obj.id]
},
m.id
);
if (res == null) {
return;
}
window.$gz.form.setLastReportMenuItem(FORM_KEY, res, m.vm);
}
break;
case "LicenseList":
{
let cName = "Customer";
const selected = m.vm.$refs.customerId.getFullSelectionValue();
if (selected != null) {
cName = selected.name;
}
m.vm.$router.push({
name: "biz-license-list",
params: {
aType: window.$gz.type.Customer,
objectId: m.vm.obj.customerId,
name: cName
}
});
}
break;
case "license":
{
if (!m.vm.canDuplicate()) {
alert("Save this record first");
return;
}
if (m.vm.obj.fetchEmail == null) {
throw new Error("Email address Required");
}
if (m.vm.obj.regTo == null) {
throw new Error("Registered to Required");
}
if (m.vm.obj.pGroup == 0 || m.vm.obj.pGroup == 4) {
throw new Error("Invalid product group");
}
if (m.vm.obj.items.length == 0) {
throw new Error("No subscription items to license");
}
if (
(m.vm.obj.pGroup == 2 || m.vm.obj.pGroup == 3) &&
m.vm.obj.dbId == null
) {
throw new Error("DB ID Required");
}
const RAVEN_PERPETUAL_PRODUCT_SOCKEYE_ID = 4;
const RAVEN_SUBSCRIPTION_MONTHLY_PRODUCT_SOCKEYE_ID = 22;
const RAVEN_SUBSCRIPTION_YEARLY_PRODUCT_SOCKEYE_ID = 24;
// const PRODUCT_INTERNAL_ID = [
// { id: 19, name: "AyaNova Lite ", active: true },
// {
// id: 4,
// name:
// "AyaNova perpetual single user license includes one year maintenance plan ",
// active: true
// },
// { id: 22, name: "AyaNova subscription one user monthly ", active: true },
// { id: 24, name: "AyaNova subscription one user yearly ", active: true },
// { id: 23, name: "Custom 539230073 ", active: true },
// { id: 21, name: "Custom 733918243 ", active: true },
// { id: 10, name: "Export to XLS ", active: true },
// { id: 11, name: "Importexport.csv duplicate ", active: true },
// { id: 14, name: "Key Administration ", active: true },
// { id: 13, name: "MBI ", active: true },
// { id: 16, name: "OLI ", active: true },
// { id: 18, name: "Outlook Schedule Export ", active: true },
// { id: 15, name: "PTI ", active: true },
// { id: 8, name: "QBI ", active: true },
// { id: 6, name: "QBOI ", active: true },
// { id: 5, name: "Quick Notification ", active: true },
// { id: 3, name: "RI ", active: true },
// { id: 7, name: "Single ", active: true },
// { id: 9, name: "Up to 10 ", active: true },
// { id: 17, name: "Up to 15 ", active: true },
// id 25 = up to 25
// { id: 12, name: "Up to 20 ", active: true },
// { id: 2, name: "Up to 5 ", active: true },
// { id: 20, name: "Up to 999 ", active: true },
// { id: 1, name: "WBI ", active: true }
// ];
//generate license from subscription values here
//copied from biz-license default record values
let l = {
id: 0,
concurrency: 0,
created: window.$gz.locale.nowUTC8601String(),
active: false, //here, active means it's ready for pickup
customerId: m.vm.obj.customerId,
pGroup: m.vm.obj.pGroup,
regTo: m.vm.obj.regTo,
key: null,
fetchCode: null,
fetchEmail: m.vm.obj.fetchEmail,
fetchedOn: null, //here, non null fetchedOn is read only
dbId: null,
licenseExpire: null, //what it is in v8, "lockdate" in v7
maintenanceExpire: null,
notificationSent: false,
wiki: null,
tags: [],
trialMode: false,
renewal: true,
//dto only props
customerUsers: 250,
maxDataGB: 20,
users: 1,
wbi: false,
wbiExpires: null,
mbi: false,
mbiExpires: null,
ri: false,
riExpires: null,
qbi: false,
qbiExpires: null,
qboi: false,
qboiExpires: null,
pti: false,
ptiExpires: null,
quickNotification: false,
quickNotificationExpires: null,
exportToXLS: false,
exportToXLSExpires: null,
outlookSchedule: false,
outlookScheduleExpires: null,
oli: false,
oliExpires: null,
importExportCSVDuplicate: false,
importExportCSVDuplicateExpires: null
};
/*
public enum ProductGroup
{
Misc = 0,
AyaNova7 = 1,
RavenPerpetual = 2,
RavenSubscription = 3,
NotSet = 4
}
*/
switch (m.vm.obj.pGroup) {
case 1: //v7
{
l.dbId = null;
l.customerUsers = null;
l.maxDataGB = null;
//iterate items
m.vm.obj.items.forEach(z => {
if (z.active) {
//----------------
switch (z.productId) {
case 1: //WBI
l.wbi = true;
l.wbiExpires = z.expireDate;
break;
case 2: //Up to 5
l.users = 5;
l.maintenanceExpire = z.expireDate;
break;
case 3: //RI
l.ri = true;
l.riExpires = z.expireDate;
break;
case 5: //QuickNotification
l.quickNotification = true;
l.quickNotificationExpires = z.expireDate;
break;
case 6: //QBOI
l.qboi = true;
l.qboiExpires = z.expireDate;
break;
case 7: //SINGLE
l.users = 1;
l.maintenanceExpire = z.expireDate;
break;
case 8: //QBI
l.qbi = true;
l.qbiExpires = z.expireDate;
break;
case 9: //Up to 10
l.users = 10;
l.maintenanceExpire = z.expireDate;
break;
case 10: //EXPORT TO XLS
l.exportToXLS = true;
l.exportToXLSExpires = z.expireDate;
break;
case 11: //Import Export CSV Duplicate
l.importExportCSVDuplicate = true;
l.importExportCSVDuplicateExpires = z.expireDate;
break;
case 12: //Up to 20
l.users = 20;
l.maintenanceExpire = z.expireDate;
break;
case 13: //MBI
l.mbi = true;
l.mbiExpires = z.expireDate;
break;
case 15: //PTI
l.pti = true;
l.ptiExpires = z.expireDate;
break;
case 16: //OLI
l.oli = true;
l.oliExpires = z.expireDate;
break;
case 17: //Up to 15
l.users = 15;
l.maintenanceExpire = z.expireDate;
break;
case 18: //Outlook schedule export
l.outlookSchedule = true;
l.outlookScheduleExpires = z.expireDate;
break;
case 19: //AyaNova Lite (but we coerce it to a single instead as it's deprecated / only one customer)
l.users = 1;
l.maintenanceExpire = z.expireDate;
break;
case 25: //Up to 25 //case 4576
l.users = 25;
l.maintenanceExpire = z.expireDate;
break;
case 20: //Up to 999
l.users = 999;
l.maintenanceExpire = z.expireDate;
break;
}
//----------------
}
});
}
break;
case 2: //Raven perpetual
{
l.dbId = m.vm.obj.dbId;
l.customerUsers = null;
l.maxDataGB = null;
//iterate items, count up users and find the furthest future expiry date
let newestDate = window.$gz.locale.nowUTC8601String();
let totalUserCount = 0;
m.vm.obj.items.forEach(z => {
if (
z.active &&
z.productId == RAVEN_PERPETUAL_PRODUCT_SOCKEYE_ID
) {
totalUserCount += z.quantity;
if (
window.$gz.locale.d1IsBeforeD2FromUTC8601String(
newestDate,
z.expireDate
)
) {
newestDate = z.expireDate;
}
}
});
l.users = totalUserCount;
l.maintenanceExpire = newestDate;
}
break;
case 3: //RavenSubscription
{
l.dbId = m.vm.obj.dbId;
l.customerUsers = 250;
l.maxDataGB = 20;
//iterate items, count up users and find the furthest future expiry date
let newestDate = window.$gz.locale.nowUTC8601String();
let totalUserCount = 0;
m.vm.obj.items.forEach(z => {
if (
z.active &&
(z.productId ==
RAVEN_SUBSCRIPTION_MONTHLY_PRODUCT_SOCKEYE_ID ||
z.productId ==
RAVEN_SUBSCRIPTION_YEARLY_PRODUCT_SOCKEYE_ID)
) {
totalUserCount += z.quantity;
if (
window.$gz.locale.d1IsBeforeD2FromUTC8601String(
newestDate,
z.expireDate
)
) {
newestDate = z.expireDate;
}
}
});
l.users = totalUserCount;
l.maintenanceExpire = newestDate;
l.licenseExpire = newestDate;
}
break;
}
console.log(l);
m.vm.$router.push({
name: "license-edit",
params: {
recordid: 0,
obj: l
}
});
}
break;
default:
window.$gz.eventBus.$emit(
"notify-warning",
FORM_KEY + "::context click: [" + m.key + "]"
);
}
}
}
//////////////////////
//
//
function generateMenu(vm) {
const menuOptions = {
isMain: false,
readOnly: vm.formState.readOnly,
icon: "$sockiFileContract",
title: "Subscription",
formData: {
sockType: window.$gz.type.Subscription,
recordId: vm.$route.params.recordid,
formCustomTemplateKey: FORM_CUSTOM_TEMPLATE_KEY,
recordName: vm.obj.subsite
},
menuItems: []
};
if (vm.rights.change) {
menuOptions.menuItems.push({
title: "Save",
icon: "$sockiSave",
surface: true,
key: FORM_KEY + ":save",
vm: vm
});
}
menuOptions.menuItems.push({
title: "Report",
icon: "$sockiFileAlt",
key: FORM_KEY + ":report",
vm: vm
});
const lastReport = window.$gz.form.getLastReport(FORM_KEY);
if (lastReport != null) {
menuOptions.menuItems.push({
title: lastReport.name,
notrans: true,
icon: "$sockiFileAlt",
key: FORM_KEY + ":report:" + lastReport.id,
vm: vm
});
}
if (vm.rights.change) {
menuOptions.menuItems.push({
title: "New",
icon: "$sockiPlus",
key: FORM_KEY + ":new",
vm: vm
});
}
if (vm.rights.change && vm.$route.params.recordid != 0) {
menuOptions.menuItems.push({
title: "Duplicate",
icon: "$sockiClone",
key: FORM_KEY + ":duplicate",
vm: vm
});
}
if (vm.rights.delete && vm.$route.params.recordid != 0) {
menuOptions.menuItems.push({
title: "Delete",
icon: "$sockiTrashAlt",
surface: false,
key: FORM_KEY + ":delete",
vm: vm
});
}
menuOptions.menuItems.push({ divider: true, inset: false });
if (vm.rights.change && vm.$route.params.recordid != 0 && vm.canDuplicate()) {
menuOptions.menuItems.push({
title: "Generate license",
notrans: true,
icon: "$sockiHandHoldingWater",
key: FORM_KEY + ":license",
vm: vm
});
}
menuOptions.menuItems.push({
title: "LicenseList",
icon: "$sockiGem",
key: FORM_KEY + ":LicenseList",
vm: vm
});
menuOptions.menuItems.push({ divider: true, inset: false });
window.$gz.eventBus.$emit("menu-change", menuOptions);
}
let JUST_DELETED = false;
/////////////////////////////////
//
//
async function initForm(vm) {
await fetchTranslatedText();
await window.$gz.formCustomTemplate.get(FORM_CUSTOM_TEMPLATE_KEY, vm);
await populateSelectionLists(vm);
}
//////////////////////////////////////////////////////////
//
// Ensures UI translated text is available
//
async function fetchTranslatedText() {
await window.$gz.translation.cacheTranslations([
"Subscription",
"Customer",
"ProductGroup",
"Product",
"SubSite",
"ContractNotes",
"ProductName",
"PurchaseQuantity",
"PurchaseExpireDate",
"SubscriptionItemList",
"OriginalOrderNumber",
"OriginalOrderDate",
"LicenseRegTo",
"LicenseFetchEmail",
"DatabaseID",
"Renewal"
]);
}
//////////////////////
//
//
async function populateSelectionLists(vm) {
//ensure the pick lists required are pre-fetched
await window.$gz.enums.fetchEnumList("productgroup");
vm.selectLists.pGroups = window.$gz.enums.getSelectionList("productgroup");
}
//////////////////////
//
//
function addToDate(dateValue, span) {
let newDate = dateValue;
if (newDate == null) {
newDate = window.$gz.locale.addDurationToUTC8601String(
window.$gz.locale.nowUTC8601String(),
span
);
} else {
newDate = window.$gz.locale.addDurationToUTC8601String(newDate, span);
}
return newDate;
}
</script>