Bug 38201: Migrate vendors to the framework
Signed-off-by: Michaela Sieber <michaela.sieber@kit.edu> Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org> Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
This commit is contained in:
parent
5f198fb3e9
commit
0b1d416b49
|
|
@ -1,10 +1,11 @@
|
|||
<template>
|
||||
<input
|
||||
:id="id"
|
||||
type="number"
|
||||
inputmode="numeric"
|
||||
v-model="model"
|
||||
:placeholder="placeholder"
|
||||
:required="required"
|
||||
:size="size"
|
||||
/>
|
||||
</template>
|
||||
|
||||
|
|
@ -16,6 +17,7 @@ export default {
|
|||
modelValue: Number,
|
||||
placeholder: String,
|
||||
required: Boolean,
|
||||
size: Number | null,
|
||||
},
|
||||
emits: ["update:modelValue"],
|
||||
setup(props, { emit }) {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
v-model="resource[attr.name]"
|
||||
:placeholder="attr.placeholder || attr.label"
|
||||
:required="attr.required ? true : false"
|
||||
:size="attr.size"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="attr.type == 'text'">
|
||||
|
|
|
|||
|
|
@ -17,27 +17,26 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { inject, onBeforeMount, ref } from "vue";
|
||||
import { inject, onBeforeMount } from "vue";
|
||||
import NavigationItem from "./NavigationItem.vue";
|
||||
import VendorMenu from "./Islands/VendorMenu.vue";
|
||||
import AcquisitionsMenu from "./Islands/AcquisitionsMenu.vue";
|
||||
import { storeToRefs } from "pinia";
|
||||
|
||||
export default {
|
||||
name: "LeftMenu",
|
||||
setup(props) {
|
||||
const navigationStore = inject("navigationStore");
|
||||
const { leftNavigation } = navigationStore;
|
||||
const { leftNavigation } = storeToRefs(navigationStore);
|
||||
|
||||
const navigationTree = ref(leftNavigation);
|
||||
onBeforeMount(async () => {
|
||||
if (props.condition)
|
||||
navigationTree.value = await props.condition(
|
||||
navigationTree.value
|
||||
leftNavigation.value = await props.condition(
|
||||
leftNavigation.value
|
||||
);
|
||||
});
|
||||
return {
|
||||
leftNavigation,
|
||||
navigationTree,
|
||||
};
|
||||
},
|
||||
props: {
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { onBeforeMount, ref } from "vue";
|
||||
import { onBeforeMount, provide, ref } from "vue";
|
||||
import FormElement from "./FormElement.vue";
|
||||
|
||||
export default {
|
||||
|
|
@ -59,6 +59,8 @@ export default {
|
|||
const resourceRelationshipCount = ref(null);
|
||||
const options = ref(null);
|
||||
|
||||
provide("resourceRelationships", props.resourceRelationships);
|
||||
|
||||
const addResourceRelationship = () => {
|
||||
props.resourceRelationships.push({
|
||||
...props.newRelationshipDefaultAttrs,
|
||||
|
|
|
|||
|
|
@ -174,10 +174,7 @@ export default {
|
|||
if (valueKey?.includes(".")) {
|
||||
return baseElement.accessNestedProperty(valueKey, resource);
|
||||
}
|
||||
const displayValue = attr.format(
|
||||
resource[valueKey] ? resource[valueKey] : valueKey,
|
||||
resource
|
||||
);
|
||||
const displayValue = attr.format(resource[valueKey], resource);
|
||||
if (displayValue == "Invalid Date") {
|
||||
return "";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { inject } from "vue";
|
||||
import { inject, onBeforeMount, ref } from "vue";
|
||||
import Breadcrumbs from "../Breadcrumbs.vue";
|
||||
import Help from "../Help.vue";
|
||||
import LeftMenu from "../LeftMenu.vue";
|
||||
|
|
@ -43,8 +43,32 @@ export default {
|
|||
const mainStore = inject("mainStore");
|
||||
const { loading, loaded, setError } = mainStore;
|
||||
|
||||
const permissionsStore = inject("permissionsStore");
|
||||
const { userPermissions } = storeToRefs(permissionsStore);
|
||||
const initialized = ref(false);
|
||||
|
||||
onBeforeMount(() => {
|
||||
loading();
|
||||
|
||||
loadAuthorisedValues(authorisedValues.value, vendorStore).then(
|
||||
() => {
|
||||
const client = APIClient.acquisition;
|
||||
client.config.get("vendors").then(result => {
|
||||
userPermissions.value = result.permissions;
|
||||
config.value.settings.edifact = result.edifact;
|
||||
config.value.settings.marcOrderAutomation =
|
||||
result.marcOrderAutomation;
|
||||
vendorStore.currencies = result.currencies;
|
||||
vendorStore.gstValues = result.gst_values.map(gv => {
|
||||
return {
|
||||
label: `${Number(gv.option * 100).format_price()}%`,
|
||||
value: gv.option,
|
||||
};
|
||||
});
|
||||
loaded();
|
||||
initialized.value = true;
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
return {
|
||||
vendorStore,
|
||||
|
|
@ -55,38 +79,9 @@ export default {
|
|||
config,
|
||||
loadAuthorisedValues,
|
||||
authorisedValues,
|
||||
initialized,
|
||||
};
|
||||
},
|
||||
beforeCreate() {
|
||||
this.loading();
|
||||
|
||||
this.loadAuthorisedValues(this.authorisedValues, this.vendorStore).then(
|
||||
() => {
|
||||
const client = APIClient.acquisition;
|
||||
client.config.get("vendors").then(config => {
|
||||
this.userPermissions = config.permissions;
|
||||
this.config.settings.edifact = config.edifact;
|
||||
this.config.settings.marcOrderAutomation =
|
||||
config.marcOrderAutomation;
|
||||
this.vendorStore.currencies = config.currencies;
|
||||
this.vendorStore.gstValues = config.gst_values.map(gv => {
|
||||
return {
|
||||
label: `${Number(gv.option * 100).format_price()}%`,
|
||||
value: gv.option,
|
||||
};
|
||||
});
|
||||
this.loaded();
|
||||
this.initialized = true;
|
||||
});
|
||||
}
|
||||
);
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
initialized: false,
|
||||
};
|
||||
},
|
||||
methods: {},
|
||||
components: {
|
||||
Breadcrumbs,
|
||||
Dialog,
|
||||
|
|
|
|||
|
|
@ -1,286 +1,115 @@
|
|||
<template>
|
||||
<fieldset class="rows" v-if="display">
|
||||
<h2>
|
||||
{{ $__("Contact") }}
|
||||
</h2>
|
||||
<span v-if="vendor.contacts.length === 0">{{
|
||||
$__("No contacts")
|
||||
}}</span>
|
||||
<ol v-for="contact in vendor.contacts" :key="contact.id">
|
||||
<legend>{{ contact.name }}</legend>
|
||||
<li>
|
||||
<label>{{ $__("Position") }}:</label>
|
||||
<span>{{ contact.position }}</span>
|
||||
</li>
|
||||
<li>
|
||||
<label>{{ $__("Phone") }}:</label>
|
||||
<span>{{ contact.phone }}</span>
|
||||
</li>
|
||||
<li>
|
||||
<label>{{ $__("Alternative phone") }}:</label>
|
||||
<span>{{ contact.altphone }}</span>
|
||||
</li>
|
||||
<li>
|
||||
<label>{{ $__("Fax") }}:</label>
|
||||
<span>{{ contact.fax }}</span>
|
||||
</li>
|
||||
<li v-if="contact.email">
|
||||
<label>{{ $__("Email") }}:</label>
|
||||
<span>
|
||||
<a :href="`mailto:${contact.email}`" target="_blank">{{
|
||||
contact.email
|
||||
}}</a>
|
||||
</span>
|
||||
</li>
|
||||
<li v-if="contact.notes">
|
||||
<label>{{ $__("Notes") }}:</label>
|
||||
<span>{{ contact.notes }}</span>
|
||||
</li>
|
||||
<li
|
||||
v-if="
|
||||
contact.acqprimary ||
|
||||
contact.orderacquisition ||
|
||||
contact.claimacquisition
|
||||
"
|
||||
>
|
||||
<span class="label">{{ $__("Acquisitions options") }}:</span>
|
||||
<ol>
|
||||
<li v-if="contact.acqprimary">
|
||||
<span class="contact_details"
|
||||
><i class="fa fa-check"></i>
|
||||
{{ $__("Primary acquisitions contact") }}</span
|
||||
>
|
||||
</li>
|
||||
<li v-if="contact.orderacquisition">
|
||||
<span class="contact_details"
|
||||
><i class="fa fa-check"></i>
|
||||
{{ $__("Receives orders") }}</span
|
||||
>
|
||||
</li>
|
||||
<li v-if="contact.claimacquisition">
|
||||
<span class="contact_details"
|
||||
><i class="fa fa-check"></i>
|
||||
{{ $__("Receives claims for late orders") }}</span
|
||||
>
|
||||
</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li v-if="contact.serialsprimary || contact.claimissues">
|
||||
<span class="label">{{ $__("Serials options") }}:</span>
|
||||
<ol>
|
||||
<li v-if="contact.serialsprimary">
|
||||
<span class="contact_details"
|
||||
><i class="fa fa-check"></i>
|
||||
{{ $__("Primary serials contact") }}</span
|
||||
>
|
||||
</li>
|
||||
<li v-if="contact.claimissues">
|
||||
<span class="contact_details"
|
||||
><i class="fa fa-check"></i>
|
||||
{{ $__("Receives claims for late issues") }}</span
|
||||
>
|
||||
</li>
|
||||
</ol>
|
||||
</li>
|
||||
</ol>
|
||||
</fieldset>
|
||||
<fieldset class="rows" v-else>
|
||||
<legend>{{ $__("Contacts") }}</legend>
|
||||
<fieldset
|
||||
class="rows"
|
||||
v-for="(contact, i) in vendor.contacts"
|
||||
v-bind:key="i"
|
||||
:id="`contact_${i}`"
|
||||
>
|
||||
<legend>{{ $__("Contact details") }}</legend>
|
||||
<ol>
|
||||
<li>
|
||||
<label :for="`contact_${i}_name`"
|
||||
>{{ $__("Contact name") }}:</label
|
||||
>
|
||||
<input :id="`contact_${i}_name`" v-model="contact.name" />
|
||||
</li>
|
||||
<li>
|
||||
<label :for="`contact_${i}_position`"
|
||||
>{{ $__("Position") }}:</label
|
||||
>
|
||||
<input
|
||||
:id="`contact_${i}_position`"
|
||||
v-model="contact.position"
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
<label :for="`contact_${i}_phone`"
|
||||
>{{ $__("Phone") }}:</label
|
||||
>
|
||||
<input :id="`contact_${i}_phone`" v-model="contact.phone" />
|
||||
</li>
|
||||
<li>
|
||||
<label :for="`contact_${i}_altphone`"
|
||||
>{{ $__("Alternative phone") }}:</label
|
||||
>
|
||||
<input
|
||||
:id="`contact_${i}_altphone`"
|
||||
v-model="contact.altphone"
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
<label :for="`contact_${i}_fax`">{{ $__("Fax") }}:</label>
|
||||
<input :id="`contact_${i}_fax`" v-model="contact.fax" />
|
||||
</li>
|
||||
<li>
|
||||
<label :for="`contact_${i}_email`"
|
||||
>{{ $__("Email") }}:</label
|
||||
>
|
||||
<input
|
||||
:id="`contact_${i}_email`"
|
||||
v-model="contact.email"
|
||||
type="email"
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
<label :for="`contact_${i}_notes`"
|
||||
>{{ $__("Notes") }}:</label
|
||||
>
|
||||
<textarea
|
||||
:id="`contact_${i}_notes`"
|
||||
v-model="contact.notes"
|
||||
cols="40"
|
||||
rows="3"
|
||||
/>
|
||||
</li>
|
||||
</ol>
|
||||
<div style="display: flex">
|
||||
<div>
|
||||
<fieldset class="rows">
|
||||
<legend>{{ $__("Acquisitions options") }}</legend>
|
||||
<ol class="radio">
|
||||
<li>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
:id="`contact_acqprimary_${i}`"
|
||||
class="contact_acqprimary"
|
||||
v-model="contact.acqprimary"
|
||||
@change="
|
||||
handlePrimaryContact(
|
||||
'acqprimary',
|
||||
i
|
||||
)
|
||||
"
|
||||
/>
|
||||
{{ $__("Primary acquisitions contact") }}
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
:id="`contact_orderacquisition_${i}`"
|
||||
class="contact_orderacquisition"
|
||||
v-model="contact.orderacquisition"
|
||||
/>
|
||||
{{ $__("Contact when ordering") }}
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
:id="`contact_claimacquisition_${i}`"
|
||||
class="contact_claimacquisition"
|
||||
v-model="contact.claimacquisition"
|
||||
/>
|
||||
{{ $__("Contact about late orders") }}
|
||||
</label>
|
||||
</li>
|
||||
</ol>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div>
|
||||
<fieldset class="rows">
|
||||
<legend>{{ $__("Serials options") }}</legend>
|
||||
<ol class="radio">
|
||||
<li>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
:id="`contact_serialsprimary_${i}`"
|
||||
class="contact_serialsprimary"
|
||||
v-model="contact.serialsprimary"
|
||||
@change="
|
||||
handlePrimaryContact(
|
||||
'serialsprimary',
|
||||
i
|
||||
)
|
||||
"
|
||||
/>
|
||||
{{ $__("Primary serials contact") }}
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
:id="`contact_claimissues_${i}`"
|
||||
class="contact_claimissues"
|
||||
v-model="contact.claimissues"
|
||||
/>
|
||||
{{ $__("Contact about late issues") }}
|
||||
</label>
|
||||
</li>
|
||||
</ol>
|
||||
</fieldset>
|
||||
</div>
|
||||
<fieldset class="rows" style="margin-top: 10px">
|
||||
<div style="display: flex">
|
||||
<div>
|
||||
<fieldset class="rows">
|
||||
<legend>{{ $__("Acquisitions options") }}</legend>
|
||||
<ol class="radio">
|
||||
<li>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
:id="`contact_acqprimary_${index}`"
|
||||
class="contact_acqprimary"
|
||||
v-model="contact.acqprimary"
|
||||
@change="
|
||||
handlePrimaryContact(
|
||||
'acqprimary',
|
||||
index
|
||||
)
|
||||
"
|
||||
/>
|
||||
{{ $__("Primary acquisitions contact") }}
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
:id="`contact_orderacquisition_${index}`"
|
||||
class="contact_orderacquisition"
|
||||
v-model="contact.orderacquisition"
|
||||
/>
|
||||
{{ $__("Contact when ordering") }}
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
:id="`contact_claimacquisition_${index}`"
|
||||
class="contact_claimacquisition"
|
||||
v-model="contact.claimacquisition"
|
||||
/>
|
||||
{{ $__("Contact about late orders") }}
|
||||
</label>
|
||||
</li>
|
||||
</ol>
|
||||
</fieldset>
|
||||
</div>
|
||||
<span class="btn btn-default" @click.prevent="deleteContact(i)"
|
||||
><font-awesome-icon icon="trash" />
|
||||
{{ $__("Delete contact") }}</span
|
||||
>
|
||||
</fieldset>
|
||||
<span class="btn btn-default" @click="addContact"
|
||||
><font-awesome-icon icon="plus" />
|
||||
{{ $__("Add new contact") }}</span
|
||||
>
|
||||
<div>
|
||||
<fieldset class="rows">
|
||||
<legend>{{ $__("Serials options") }}</legend>
|
||||
<ol class="radio">
|
||||
<li>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
:id="`contact_serialsprimary_${index}`"
|
||||
class="contact_serialsprimary"
|
||||
v-model="contact.serialsprimary"
|
||||
@change="
|
||||
handlePrimaryContact(
|
||||
'serialsprimary',
|
||||
index
|
||||
)
|
||||
"
|
||||
/>
|
||||
{{ $__("Primary serials contact") }}
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
:id="`contact_claimissues_${index}`"
|
||||
class="contact_claimissues"
|
||||
v-model="contact.claimissues"
|
||||
/>
|
||||
{{ $__("Contact about late issues") }}
|
||||
</label>
|
||||
</li>
|
||||
</ol>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { inject } from "vue";
|
||||
export default {
|
||||
props: {
|
||||
vendor: Object,
|
||||
display: Boolean,
|
||||
contact: Object,
|
||||
index: Number | null,
|
||||
},
|
||||
methods: {
|
||||
addContact() {
|
||||
this.vendor.contacts.push({
|
||||
name: "",
|
||||
position: "",
|
||||
email: "",
|
||||
phone: "",
|
||||
notes: "",
|
||||
altphone: "",
|
||||
fax: "",
|
||||
acqprimary: false,
|
||||
orderacquisition: false,
|
||||
claimacquisition: false,
|
||||
serialsprimary: false,
|
||||
claimissues: false,
|
||||
});
|
||||
},
|
||||
handlePrimaryContact(type, i) {
|
||||
const contact = this.vendor.contacts[i];
|
||||
setup(props) {
|
||||
const resourceRelationships = inject("resourceRelationships");
|
||||
|
||||
const handlePrimaryContact = (type, index) => {
|
||||
const contact = resourceRelationships[index];
|
||||
if (contact[type]) {
|
||||
this.vendor.contacts.forEach((contact, j) => {
|
||||
if (j !== i) {
|
||||
resourceRelationships.forEach((contact, j) => {
|
||||
if (j !== index) {
|
||||
contact[type] = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
deleteContact(i) {
|
||||
this.vendor.contacts.splice(i, 1);
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
handlePrimaryContact,
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,733 @@
|
|||
<template>
|
||||
<BaseResource
|
||||
:routeAction="routeAction"
|
||||
:instancedResource="this"
|
||||
></BaseResource>
|
||||
</template>
|
||||
<script>
|
||||
import { inject } from "vue";
|
||||
import BaseResource from "../BaseResource.vue";
|
||||
import { useBaseResource } from "../../composables/base-resource.js";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { APIClient } from "../../fetch/api-client.js";
|
||||
import { $__ } from "../../i18n";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
routeAction: String,
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const vendorStore = inject("vendorStore");
|
||||
const { currencies, gstValues } = storeToRefs(vendorStore);
|
||||
|
||||
const handleContactOptions = value => {
|
||||
return value ? "Yes" : "No";
|
||||
};
|
||||
|
||||
const baseResource = useBaseResource({
|
||||
resourceName: "vendor",
|
||||
nameAttr: "name",
|
||||
idAttr: "id",
|
||||
showComponent: "VendorShow",
|
||||
listComponent: "VendorList",
|
||||
addComponent: "VendorFormAdd",
|
||||
editComponent: "VendorFormAddEdit",
|
||||
apiClient: APIClient.acquisition.vendors,
|
||||
resourceTableUrl:
|
||||
APIClient.acquisition.httpClient._baseURL + "vendors",
|
||||
i18n: {
|
||||
deleteConfirmationMessage: __(
|
||||
"Are you sure you want to remove this vendor?"
|
||||
),
|
||||
deleteSuccessMessage: __("Vendor %s deleted"),
|
||||
displayName: __("Vendor"),
|
||||
editLabel: __("Edit vendor #%s"),
|
||||
emptyListMessage: __("There are no vendors defined"),
|
||||
newLabel: __("New vendor"),
|
||||
},
|
||||
props,
|
||||
moduleStore: "vendorStore",
|
||||
resourceAttrs: [
|
||||
{
|
||||
name: "id",
|
||||
group: $__("Details"),
|
||||
label: __("ID"),
|
||||
type: "text",
|
||||
hideIn: ["Form", "Show"],
|
||||
},
|
||||
{
|
||||
name: "name",
|
||||
group: $__("Details"),
|
||||
required: true,
|
||||
type: "text",
|
||||
label: __("Vendor name"),
|
||||
},
|
||||
{
|
||||
name: "postal",
|
||||
group: $__("Details"),
|
||||
type: "textarea",
|
||||
label: __("Postal address"),
|
||||
textAreaRows: 3,
|
||||
hideIn: ["List"],
|
||||
},
|
||||
{
|
||||
name: "physical",
|
||||
group: $__("Details"),
|
||||
type: "textarea",
|
||||
label: __("Physical address"),
|
||||
textAreaRows: 3,
|
||||
hideIn: ["List"],
|
||||
},
|
||||
{
|
||||
name: "phone",
|
||||
group: $__("Details"),
|
||||
type: "text",
|
||||
label: __("Phone"),
|
||||
hideIn: ["List"],
|
||||
},
|
||||
{
|
||||
name: "fax",
|
||||
group: $__("Details"),
|
||||
type: "text",
|
||||
label: __("Fax"),
|
||||
hideIn: ["List"],
|
||||
},
|
||||
{
|
||||
name: "url",
|
||||
group: $__("Details"),
|
||||
type: "text",
|
||||
label: __("Website"),
|
||||
hideIn: ["List"],
|
||||
},
|
||||
{
|
||||
name: "accountnumber",
|
||||
group: $__("Details"),
|
||||
type: "text",
|
||||
label: __("Account number"),
|
||||
hideIn: ["List"],
|
||||
},
|
||||
{
|
||||
name: "type",
|
||||
group: $__("Details"),
|
||||
type: "select",
|
||||
label: $__("Vendor type"),
|
||||
avCat: "av_vendor_types",
|
||||
},
|
||||
{
|
||||
name: "aliases",
|
||||
type: "relationshipWidget",
|
||||
group: $__("Aliases"),
|
||||
showElement: {
|
||||
type: "table",
|
||||
columnData: "aliases",
|
||||
hidden: vendor => !!vendor.aliases?.length,
|
||||
columns: [
|
||||
{
|
||||
name: $__("Alias"),
|
||||
value: "alias",
|
||||
},
|
||||
],
|
||||
},
|
||||
componentProps: {
|
||||
resourceRelationships: {
|
||||
resourceProperty: "aliases",
|
||||
},
|
||||
relationshipStrings: {
|
||||
nameLowerCase: __("alias"),
|
||||
nameUpperCase: __("Alias"),
|
||||
namePlural: __("aliases"),
|
||||
},
|
||||
newRelationshipDefaultAttrs: {
|
||||
type: "object",
|
||||
value: {
|
||||
alias: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
relationshipFields: [
|
||||
{
|
||||
name: "alias",
|
||||
type: "text",
|
||||
label: __("Alias"),
|
||||
indexRequired: true,
|
||||
},
|
||||
],
|
||||
hideIn: ["List"],
|
||||
},
|
||||
{
|
||||
name: "contacts",
|
||||
type: "relationshipWidget",
|
||||
group: $__("Contacts"),
|
||||
showElement: {
|
||||
type: "table",
|
||||
columnData: "contacts",
|
||||
hidden: vendor => !!vendor.contacts?.length,
|
||||
columns: [
|
||||
{
|
||||
name: $__("Name"),
|
||||
value: "name",
|
||||
},
|
||||
{
|
||||
name: $__("Position"),
|
||||
value: "role",
|
||||
},
|
||||
{
|
||||
name: $__("Phone"),
|
||||
value: "phone",
|
||||
},
|
||||
{
|
||||
name: $__("Alternative phone"),
|
||||
value: "altphone",
|
||||
},
|
||||
{
|
||||
name: $__("Fax"),
|
||||
value: "fax",
|
||||
},
|
||||
{
|
||||
name: $__("Email"),
|
||||
value: "email",
|
||||
},
|
||||
{
|
||||
name: $__("Notes"),
|
||||
value: "notes",
|
||||
},
|
||||
{
|
||||
name: $__("Primary acquisitions contact"),
|
||||
value: "acqprimary",
|
||||
format: handleContactOptions,
|
||||
},
|
||||
{
|
||||
name: $__("Contact when ordering"),
|
||||
value: "orderacquisition",
|
||||
format: handleContactOptions,
|
||||
},
|
||||
{
|
||||
name: $__("Contact about late orders"),
|
||||
value: "claimacquisition",
|
||||
format: handleContactOptions,
|
||||
},
|
||||
{
|
||||
name: $__("Primary serials contact"),
|
||||
value: "serialsprimary",
|
||||
format: handleContactOptions,
|
||||
},
|
||||
{
|
||||
name: $__("Contact about late issues"),
|
||||
value: "claimissues",
|
||||
format: handleContactOptions,
|
||||
},
|
||||
],
|
||||
},
|
||||
componentProps: {
|
||||
resourceRelationships: {
|
||||
resourceProperty: "contacts",
|
||||
},
|
||||
relationshipStrings: {
|
||||
nameLowerCase: __("contact"),
|
||||
nameUpperCase: __("Contact"),
|
||||
namePlural: __("contacts"),
|
||||
},
|
||||
newRelationshipDefaultAttrs: {
|
||||
type: "object",
|
||||
value: {
|
||||
name: "",
|
||||
position: "",
|
||||
email: "",
|
||||
phone: "",
|
||||
notes: "",
|
||||
altphone: "",
|
||||
fax: "",
|
||||
acqprimary: false,
|
||||
orderacquisition: false,
|
||||
claimacquisition: false,
|
||||
serialsprimary: false,
|
||||
claimissues: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
relationshipFields: [
|
||||
{
|
||||
name: "name",
|
||||
type: "text",
|
||||
label: __("Name"),
|
||||
indexRequired: true,
|
||||
},
|
||||
{
|
||||
name: "position",
|
||||
type: "text",
|
||||
label: __("Position"),
|
||||
indexRequired: true,
|
||||
},
|
||||
{
|
||||
name: "phone",
|
||||
type: "text",
|
||||
label: __("Phone"),
|
||||
indexRequired: true,
|
||||
},
|
||||
{
|
||||
name: "altphone",
|
||||
type: "text",
|
||||
label: __("Alternative phone"),
|
||||
indexRequired: true,
|
||||
},
|
||||
{
|
||||
name: "fax",
|
||||
type: "text",
|
||||
label: __("Fax"),
|
||||
indexRequired: true,
|
||||
},
|
||||
{
|
||||
name: "email",
|
||||
type: "text",
|
||||
label: __("Email"),
|
||||
indexRequired: true,
|
||||
},
|
||||
{
|
||||
name: "notes",
|
||||
type: "text",
|
||||
label: __("Notes"),
|
||||
indexRequired: true,
|
||||
},
|
||||
{
|
||||
type: "component",
|
||||
// label: __("User"),
|
||||
componentPath: "./Vendors/VendorContacts.vue",
|
||||
indexRequired: true,
|
||||
componentProps: {
|
||||
contact: {
|
||||
type: "resource",
|
||||
value: null,
|
||||
},
|
||||
},
|
||||
hideIn: ["List", "Show"],
|
||||
},
|
||||
],
|
||||
hideIn: ["List"],
|
||||
},
|
||||
{
|
||||
name: "interfaces",
|
||||
type: "relationshipWidget",
|
||||
group: __("Interfaces"),
|
||||
showElement: {
|
||||
type: "table",
|
||||
columnData: "interfaces",
|
||||
hidden: vendor => !!vendor.interfaces?.length,
|
||||
columns: [
|
||||
{
|
||||
name: $__("Type"),
|
||||
value: "type",
|
||||
av: "av_vendor_interface_types",
|
||||
},
|
||||
{
|
||||
name: $__("Name"),
|
||||
value: "name",
|
||||
},
|
||||
{
|
||||
name: $__("URI"),
|
||||
value: "uri",
|
||||
},
|
||||
{
|
||||
name: $__("Password"),
|
||||
value: "password",
|
||||
},
|
||||
{
|
||||
name: $__("Email"),
|
||||
value: "account_email",
|
||||
},
|
||||
{
|
||||
name: $__("Notes"),
|
||||
value: "notes",
|
||||
},
|
||||
],
|
||||
},
|
||||
componentProps: {
|
||||
resourceRelationships: {
|
||||
resourceProperty: "interfaces",
|
||||
},
|
||||
relationshipStrings: {
|
||||
nameLowerCase: __("interface"),
|
||||
nameUpperCase: __("Interface"),
|
||||
namePlural: __("interfaces"),
|
||||
},
|
||||
newRelationshipDefaultAttrs: {
|
||||
type: "object",
|
||||
value: {
|
||||
type: "",
|
||||
name: "",
|
||||
uri: "",
|
||||
login: "",
|
||||
password: "",
|
||||
account_email: "",
|
||||
notes: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
relationshipFields: [
|
||||
{
|
||||
name: "name",
|
||||
type: "text",
|
||||
label: __("Name"),
|
||||
indexRequired: true,
|
||||
},
|
||||
{
|
||||
name: "type",
|
||||
type: "select",
|
||||
label: $__("Type"),
|
||||
avCat: "av_vendor_interface_types",
|
||||
indexRequired: true,
|
||||
},
|
||||
{
|
||||
name: "uri",
|
||||
type: "text",
|
||||
label: __("URI"),
|
||||
indexRequired: true,
|
||||
},
|
||||
{
|
||||
name: "login",
|
||||
type: "text",
|
||||
label: __("Login"),
|
||||
indexRequired: true,
|
||||
},
|
||||
{
|
||||
name: "password",
|
||||
type: "text",
|
||||
label: __("Password"),
|
||||
indexRequired: true,
|
||||
},
|
||||
{
|
||||
name: "account_email",
|
||||
type: "text",
|
||||
label: __("Account email"),
|
||||
indexRequired: true,
|
||||
},
|
||||
{
|
||||
name: "notes",
|
||||
type: "text",
|
||||
label: __("Notes"),
|
||||
indexRequired: true,
|
||||
},
|
||||
],
|
||||
hideIn: ["List"],
|
||||
},
|
||||
{
|
||||
name: "active",
|
||||
group: $__("Ordering information"),
|
||||
label: $__("Vendor is"),
|
||||
type: "radio",
|
||||
options: [
|
||||
{ value: true, description: $__("Active") },
|
||||
{ value: false, description: $__("Inactive") },
|
||||
],
|
||||
value: true,
|
||||
hideIn: ["List"],
|
||||
},
|
||||
{
|
||||
name: "list_currency",
|
||||
group: $__("Ordering information"),
|
||||
type: "select",
|
||||
label: __("List prices are"),
|
||||
selectLabel: "currency",
|
||||
requiredKey: "currency",
|
||||
options: currencies.value,
|
||||
defaultValue: null,
|
||||
hideIn: ["List"],
|
||||
},
|
||||
{
|
||||
name: "invoice_currency",
|
||||
group: $__("Ordering information"),
|
||||
type: "select",
|
||||
selectLabel: "currency",
|
||||
requiredKey: "currency",
|
||||
label: __("Invoice prices are"),
|
||||
options: currencies.value,
|
||||
defaultValue: null,
|
||||
},
|
||||
{
|
||||
name: "gst",
|
||||
group: $__("Ordering information"),
|
||||
label: $__("Tax number registered"),
|
||||
type: "radio",
|
||||
options: [
|
||||
{ value: true, description: $__("Yes") },
|
||||
{ value: false, description: $__("No") },
|
||||
],
|
||||
value: true,
|
||||
hideIn: ["List"],
|
||||
},
|
||||
{
|
||||
name: "invoice_includes_gst",
|
||||
group: $__("Ordering information"),
|
||||
label: $__("Invoice prices"),
|
||||
type: "radio",
|
||||
options: [
|
||||
{ value: true, description: $__("Include tax") },
|
||||
{ value: false, description: $__("Don't include tax") },
|
||||
],
|
||||
value: true,
|
||||
hideIn: ["List"],
|
||||
},
|
||||
{
|
||||
name: "list_includes_gst",
|
||||
group: $__("Ordering information"),
|
||||
label: $__("List prices"),
|
||||
type: "radio",
|
||||
options: [
|
||||
{ value: true, description: $__("Include tax") },
|
||||
{ value: false, description: $__("Don't include tax") },
|
||||
],
|
||||
value: true,
|
||||
hideIn: ["List"],
|
||||
},
|
||||
{
|
||||
name: "tax_rate",
|
||||
group: $__("Ordering information"),
|
||||
type: "select",
|
||||
label: __("Tax rate"),
|
||||
options: gstValues.value,
|
||||
defaultValue: null,
|
||||
hideIn: ["List"],
|
||||
},
|
||||
{
|
||||
name: "discount",
|
||||
group: $__("Ordering information"),
|
||||
type: "number",
|
||||
label: __("Discount"),
|
||||
defaultValue: null,
|
||||
size: 6,
|
||||
hideIn: ["List"],
|
||||
},
|
||||
{
|
||||
name: "deliverytime",
|
||||
group: $__("Ordering information"),
|
||||
type: "number",
|
||||
label: __("Delivery time (days)"),
|
||||
hideIn: ["List"],
|
||||
},
|
||||
{
|
||||
name: "notes",
|
||||
group: $__("Ordering information"),
|
||||
type: "textarea",
|
||||
label: __("Notes"),
|
||||
hideIn: ["List"],
|
||||
},
|
||||
{
|
||||
name: "baskets",
|
||||
tableColumnDefinition: {
|
||||
title: $__("Baskets"),
|
||||
data: "baskets_count",
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
render(data, type, row, meta) {
|
||||
return row.baskets_count
|
||||
? '<a href="/cgi-bin/koha/acqui/booksellers.pl?booksellerid=' +
|
||||
row.id +
|
||||
'" class="show">' +
|
||||
escape_str(
|
||||
__("%s basket(s)").format(
|
||||
row.baskets_count
|
||||
)
|
||||
) +
|
||||
"</a>"
|
||||
: escape_str(__("No baskets"));
|
||||
},
|
||||
},
|
||||
hideIn: ["Show", "Form"],
|
||||
},
|
||||
{
|
||||
name: "subscriptions",
|
||||
tableColumnDefinition: {
|
||||
title: $__("Subscriptions"),
|
||||
data: "subscriptions_count",
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
render(data, type, row, meta) {
|
||||
return row.subscriptions_count
|
||||
? '<a href="/cgi-bin/koha/serials/serials-search.pl?bookseller_filter=' +
|
||||
escape_str(row.name) +
|
||||
"&searched=1" +
|
||||
'" class="show">' +
|
||||
escape_str(
|
||||
__("%s subscription(s)").format(
|
||||
row.subscriptions_count
|
||||
)
|
||||
) +
|
||||
"</a>"
|
||||
: escape_str(__("No subscriptions"));
|
||||
},
|
||||
},
|
||||
hideIn: ["Show", "Form"],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const tableOptions = {
|
||||
options: {
|
||||
embed: "aliases,baskets+count,subscriptions+count,invoices+count",
|
||||
},
|
||||
url: baseResource.getResourceTableUrl(),
|
||||
table_settings: baseResource.vendorTableSettings,
|
||||
add_filters: true,
|
||||
filters_options: {
|
||||
1: [
|
||||
{ _id: 0, _str: baseResource.$__("Inactive") },
|
||||
{ _id: 1, _str: baseResource.$__("Active") },
|
||||
],
|
||||
...(baseResource.map_av_dt_filter("av_vendor_types").length && {
|
||||
2: () => baseResource.map_av_dt_filter("av_vendor_types"),
|
||||
}),
|
||||
},
|
||||
actions: {
|
||||
0: ["show"],
|
||||
"-1": [
|
||||
"edit",
|
||||
{
|
||||
delete: {
|
||||
text: baseResource.$__("Delete"),
|
||||
icon: "fa fa-trash",
|
||||
should_display: row =>
|
||||
row.baskets_count === 0 &&
|
||||
row.subscriptions_count === 0 &&
|
||||
row.invoices_count === 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
receive: {
|
||||
text: baseResource.$__("Receive shipments"),
|
||||
icon: "fa fa-inbox",
|
||||
should_display: row =>
|
||||
row.active &&
|
||||
row.baskets_count > 0 &&
|
||||
// baseResource.isUserPermitted(
|
||||
// "CAN_user_acquisition_order_receive"
|
||||
// ),
|
||||
true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const checkContactOrInterface = array => {
|
||||
return array.reduce((acc, curr) => {
|
||||
const atLeastOneFieldFilled = Object.keys(curr).some(
|
||||
key => curr[key]
|
||||
);
|
||||
if (atLeastOneFieldFilled) {
|
||||
acc.push(curr);
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
};
|
||||
const verifyDiscountValue = discount => {
|
||||
return /^[\-]?\d{0,2}(\.\d{0,3})*$/.test(discount);
|
||||
};
|
||||
|
||||
const onSubmit = (e, vendorToSave) => {
|
||||
e.preventDefault();
|
||||
const errors = [];
|
||||
const vendor = JSON.parse(JSON.stringify(vendorToSave));
|
||||
|
||||
const vendorId = vendor.id;
|
||||
delete vendor.id;
|
||||
|
||||
if (vendor.physical) {
|
||||
const addressLines = vendor.physical.split("\n");
|
||||
if (addressLines.length > 4) {
|
||||
addressLines.length = 4;
|
||||
}
|
||||
addressLines.forEach((line, i) => {
|
||||
vendor[`address${i + 1}`] = line;
|
||||
});
|
||||
}
|
||||
delete vendor.physical;
|
||||
delete vendor.subscriptions_count;
|
||||
delete vendor.baskets;
|
||||
delete vendor.baskets_count;
|
||||
delete vendor.subscriptions;
|
||||
delete vendor.contracts;
|
||||
delete vendor.invoices_count;
|
||||
|
||||
if (vendor.discount && !verifyDiscountValue(vendor.discount))
|
||||
errors.push(baseResource.$__("Invalid discount value"));
|
||||
|
||||
vendor.contacts = checkContactOrInterface(
|
||||
vendor.contacts.map(
|
||||
({ id, booksellerid, ...requiredProperties }) =>
|
||||
requiredProperties
|
||||
)
|
||||
);
|
||||
vendor.interfaces = checkContactOrInterface(
|
||||
vendor.interfaces.map(
|
||||
({
|
||||
vendor_interface_id,
|
||||
vendor_id,
|
||||
...requiredProperties
|
||||
}) => requiredProperties
|
||||
)
|
||||
);
|
||||
|
||||
baseResource.setWarning(errors.join("<br>"));
|
||||
if (errors.length) return false;
|
||||
|
||||
if (vendorId) {
|
||||
baseResource.apiClient.update(vendor, vendorId).then(
|
||||
success => {
|
||||
baseResource.setMessage(
|
||||
baseResource.$__("Vendor updated")
|
||||
);
|
||||
baseResource.router.push({ name: "VendorList" });
|
||||
},
|
||||
error => {}
|
||||
);
|
||||
} else {
|
||||
baseResource.apiClient.create(vendor).then(
|
||||
success => {
|
||||
baseResource.setMessage(
|
||||
baseResource.$__("Vendor created")
|
||||
);
|
||||
baseResource.router.push({ name: "VendorList" });
|
||||
},
|
||||
error => {}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const afterResourceFetch = (componentData, resource, caller) => {
|
||||
if (caller === "form") {
|
||||
let physical = "";
|
||||
resource.address1 && (physical += resource.address1 + "\n");
|
||||
resource.address2 && (physical += resource.address2 + "\n");
|
||||
resource.address3 && (physical += resource.address3 + "\n");
|
||||
resource.address4 && (physical += resource.address4 + "\n");
|
||||
componentData.resource.value.physical = physical;
|
||||
|
||||
if (!componentData.resource.value.discount)
|
||||
componentData.resource.value.discount = 0.0;
|
||||
const decimalPlaces =
|
||||
componentData.resource.value.discount
|
||||
.toString()
|
||||
.split(".")[1]?.length || 0;
|
||||
if (!decimalPlaces) {
|
||||
componentData.resource.value.discount =
|
||||
componentData.resource.value.discount.toFixed(1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
baseResource.created();
|
||||
|
||||
return {
|
||||
...baseResource,
|
||||
tableOptions,
|
||||
onSubmit,
|
||||
afterResourceFetch,
|
||||
currencies,
|
||||
};
|
||||
},
|
||||
name: "VendorResource",
|
||||
emits: ["select-resource"],
|
||||
components: {
|
||||
BaseResource,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -122,6 +122,9 @@ export function useBaseElement(instancedElement) {
|
|||
}
|
||||
});
|
||||
}
|
||||
if (instancedElement.attr.indexRequired) {
|
||||
acc.index = instancedElement.index;
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
const attr = show
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import Home from "../components/Vendors/Home.vue";
|
|||
import VendorList from "../components/Vendors/VendorList.vue";
|
||||
import VendorShow from "../components/Vendors/VendorShow.vue";
|
||||
import VendorFormAdd from "../components/Vendors/VendorFormAdd.vue";
|
||||
import ResourceWrapper from "../components/ResourceWrapper.vue";
|
||||
|
||||
import { $__ } from "../i18n";
|
||||
|
||||
|
|
@ -33,31 +34,32 @@ export const routes = [
|
|||
icon: "fa fa-shopping-cart",
|
||||
is_end_node: true,
|
||||
breadcrumbFormat: vendorSearchBreadcrumb,
|
||||
resource: "Vendors/VendorResource.vue",
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
name: "VendorList",
|
||||
component: markRaw(VendorList),
|
||||
component: markRaw(ResourceWrapper),
|
||||
alternateLeftMenu: "AcquisitionsMenu",
|
||||
},
|
||||
{
|
||||
path: ":id",
|
||||
name: "VendorShow",
|
||||
component: markRaw(VendorShow),
|
||||
component: markRaw(ResourceWrapper),
|
||||
title: $__("Show vendor"),
|
||||
alternateLeftMenu: "VendorMenu",
|
||||
},
|
||||
{
|
||||
path: "add",
|
||||
name: "VendorFormAdd",
|
||||
component: markRaw(VendorFormAdd),
|
||||
component: markRaw(ResourceWrapper),
|
||||
title: $__("Add vendor"),
|
||||
alternateLeftMenu: "none",
|
||||
},
|
||||
{
|
||||
path: "edit/:id",
|
||||
name: "VendorFormAddEdit",
|
||||
component: markRaw(VendorFormAdd),
|
||||
component: markRaw(ResourceWrapper),
|
||||
title: $__("Edit vendor"),
|
||||
alternateLeftMenu: "VendorMenu",
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue