Bug 32030: Fix date handling - conflicts with bug 30718
[koha-ffzg.git] / koha-tmpl / intranet-tmpl / prog / js / vue / components / ERM / AgreementsFormAdd.vue
1 <template>
2     <div v-if="!initialized">{{ $t("Loading") }}</div>
3     <div v-else id="agreements_add">
4         <h2 v-if="agreement.agreement_id">
5             {{ $t("Edit agreement .id", { id: agreement.agreement_id }) }}
6         </h2>
7         <h2 v-else>{{ $t("New agreement") }}</h2>
8         <div>
9             <form @submit="onSubmit($event)">
10                 <fieldset class="rows">
11                     <ol>
12                         <li>
13                             <label class="required" for="agreement_name"
14                                 >{{ $t("Agreement name") }}:</label
15                             >
16                             <input
17                                 id="agreement_name"
18                                 v-model="agreement.name"
19                                 :placeholder="$t('Agreement name')"
20                                 required
21                             />
22                             <span class="required">{{ $t("Required") }}</span>
23                         </li>
24                         <li>
25                             <label for="agreement_vendor_id"
26                                 >{{ $t("Vendor") }}:</label
27                             >
28                             <v-select
29                                 id="agreement_vendor_id"
30                                 v-model="agreement.vendor_id"
31                                 label="name"
32                                 :reduce="(vendor) => vendor.id"
33                                 :options="vendors"
34                             />
35                         </li>
36                         <li>
37                             <label for="agreement_description"
38                                 >{{ $t("Description") }}:
39                             </label>
40                             <textarea
41                                 id="agreement_description"
42                                 v-model="agreement.description"
43                                 :placeholder="$t('Description')"
44                                 rows="10"
45                                 cols="50"
46                                 required
47                             />
48                             <span class="required">{{ $t("Required") }}</span>
49                         </li>
50                         <li>
51                             <label for="agreement_status"
52                                 >{{ $t("Status") }}:</label
53                             >
54                             <v-select
55                                 id="agreement_status"
56                                 v-model="agreement.status"
57                                 label="lib"
58                                 :reduce="(av) => av.authorised_value"
59                                 :options="av_agreement_statuses"
60                                 @option:selected="onStatusChanged"
61                                 :required="!agreement.status"
62                             >
63                                 <template #search="{ attributes, events }">
64                                     <input
65                                         :required="!agreement.status"
66                                         class="vs__search"
67                                         v-bind="attributes"
68                                         v-on="events"
69                                     />
70                                 </template>
71                             </v-select>
72                             <span class="required">{{ $t("Required") }}</span>
73                         </li>
74                         <li>
75                             <label for="agreement_closure_reason"
76                                 >{{ $t("Closure reason") }}:</label
77                             >
78                             <v-select
79                                 id="agreement_closure_reason"
80                                 v-model="agreement.closure_reason"
81                                 label="lib"
82                                 :reduce="(av) => av.authorised_value"
83                                 :options="av_agreement_closure_reasons"
84                                 :disabled="
85                                     agreement.status == 'closed' ? false : true
86                                 "
87                             />
88                         </li>
89                         <li>
90                             <label for="agreement_is_perpetual" class="radio"
91                                 >{{ $t("Is perpetual") }}:</label
92                             >
93                             <label for="agreement_is_perpetual_yes">
94                                 <input
95                                     type="radio"
96                                     name="is_perpetual"
97                                     id="agreement_is_perpetual_yes"
98                                     :value="true"
99                                     v-model="agreement.is_perpetual"
100                                 />
101                                 Yes
102                             </label>
103                             <label for="agreement_is_perpetual_no">
104                                 <input
105                                     type="radio"
106                                     name="is_perpetual"
107                                     id="agreement_is_perpetual_no"
108                                     :value="false"
109                                     v-model="agreement.is_perpetual"
110                                 />
111                                 No
112                             </label>
113                         </li>
114                         <li>
115                             <label for="agreement_renewal_priority"
116                                 >{{ $t("Renewal priority") }}:</label
117                             >
118                             <v-select
119                                 id="agreement_renewal_priority"
120                                 v-model="agreement.renewal_priority"
121                                 label="lib"
122                                 :reduce="(av) => av.authorised_value"
123                                 :options="av_agreement_renewal_priorities"
124                             />
125                         </li>
126                         <li>
127                             <label for="agreement_license_info"
128                                 >{{ $t("License info") }}:
129                             </label>
130                             <textarea
131                                 id="agreement_license_info"
132                                 v-model="agreement.license_info"
133                                 placeholder="License info"
134                             />
135                         </li>
136
137                         <AgreementPeriods :periods="agreement.periods" />
138                         <AgreementUserRoles
139                             :user_roles="agreement.user_roles"
140                             :av_agreement_user_roles="av_agreement_user_roles"
141                         />
142                         <AgreementLicenses
143                             :agreement_licenses="agreement.agreement_licenses"
144                             :av_agreement_license_statuses="
145                                 av_agreement_license_statuses
146                             "
147                             :av_agreement_license_location="
148                                 av_agreement_license_location
149                             "
150                         />
151                         <AgreementRelationships
152                             :agreement_id="agreement.agreement_id"
153                             :relationships="agreement.agreement_relationships"
154                             :av_agreement_relationships="
155                                 av_agreement_relationships
156                             "
157                         />
158                         <Documents :documents="agreement.documents" />
159                     </ol>
160                 </fieldset>
161                 <fieldset class="action">
162                     <input type="submit" value="Submit" />
163                     <router-link
164                         to="/cgi-bin/koha/erm/agreements"
165                         role="button"
166                         class="cancel"
167                         >{{ $t("Cancel") }}</router-link
168                     >
169                 </fieldset>
170             </form>
171         </div>
172     </div>
173 </template>
174
175 <script>
176 import { inject } from 'vue'
177 import AgreementPeriods from './AgreementPeriods.vue'
178 import AgreementUserRoles from './AgreementUserRoles.vue'
179 import AgreementLicenses from './AgreementLicenses.vue'
180 import AgreementRelationships from './AgreementRelationships.vue'
181 import Documents from './Documents.vue'
182 import { setMessage, setError, setWarning } from "../../messages"
183 import { fetchAgreement } from '../../fetch'
184 import { storeToRefs } from "pinia"
185
186 export default {
187     setup() {
188         const vendorStore = inject('vendorStore')
189         const { vendors } = storeToRefs(vendorStore)
190
191         const AVStore = inject('AVStore')
192         const {
193             av_agreement_statuses,
194             av_agreement_closure_reasons,
195             av_agreement_renewal_priorities,
196             av_agreement_user_roles,
197             av_agreement_license_statuses,
198             av_agreement_license_location,
199             av_agreement_relationships,
200         } = storeToRefs(AVStore)
201
202         return {
203             vendors,
204             av_agreement_statuses,
205             av_agreement_closure_reasons,
206             av_agreement_renewal_priorities,
207             av_agreement_user_roles,
208             av_agreement_license_statuses,
209             av_agreement_license_location,
210             av_agreement_relationships,
211         }
212     },
213     data() {
214         return {
215             agreement: {
216                 agreement_id: null,
217                 name: '',
218                 vendor_id: null,
219                 description: '',
220                 status: '',
221                 closure_reason: '',
222                 is_perpetual: false,
223                 renewal_priority: '',
224                 license_info: '',
225                 periods: [],
226                 user_roles: [],
227                 agreement_licenses: [],
228                 agreement_relationships: [],
229                 documents: [],
230             },
231             initialized: false,
232         }
233     },
234     beforeRouteEnter(to, from, next) {
235         next(vm => {
236             if (to.params.agreement_id) {
237                 vm.agreement = vm.getAgreement(to.params.agreement_id)
238             } else {
239                 vm.initialized = true
240             }
241         })
242     },
243     methods: {
244         async getAgreement(agreement_id) {
245             const agreement = await fetchAgreement(agreement_id)
246             this.agreement = agreement
247             this.initialized = true
248         },
249         checkForm(agreement) {
250             let errors = []
251
252             let agreement_licenses = agreement.agreement_licenses
253             // Do not use al.license.name here! Its name is not the one linked with al.license_id
254             // At this point al.license is meaningless, form/template only modified al.license_id
255             const license_ids = agreement_licenses.map(al => al.license_id)
256             const duplicate_license_ids = license_ids.filter((id, i) => license_ids.indexOf(id) !== i)
257
258             if (duplicate_license_ids.length) {
259                 errors.push(this.$t("A license is used several times"))
260             }
261
262             const related_agreement_ids = agreement.agreement_relationships.map(rs => rs.related_agreement_id)
263             const duplicate_related_agreement_ids = related_agreement_ids.filter((id, i) => related_agreement_ids.indexOf(id) !== i)
264
265             if (duplicate_related_agreement_ids.length) {
266                 errors.push(this.$t("An agreement is used as relationship several times"))
267             }
268
269             if (agreement_licenses.filter(al => al.status == 'controlling').length > 1) {
270                 errors.push(this.$t("Only one controlling license is allowed"))
271             }
272
273             if (agreement_licenses.filter(al => al.status == 'controlling').length > 1) {
274                 errors.push(this.$t("Only one controlling license is allowed"))
275             }
276
277             errors.forEach(function (e) {
278                 setWarning(e)
279             })
280             return !errors.length
281         },
282         onSubmit(e) {
283             e.preventDefault()
284
285             //let agreement= Object.assign( {} ,this.agreement); // copy
286             let agreement = JSON.parse(JSON.stringify(this.agreement)) // copy
287
288             if (!this.checkForm(agreement)) {
289                 return false
290             }
291
292             let apiUrl = '/api/v1/erm/agreements'
293
294             let method = 'POST'
295             if (agreement.agreement_id) {
296                 method = 'PUT'
297                 apiUrl += '/' + agreement.agreement_id
298             }
299             delete agreement.agreement_id
300             delete agreement.vendor
301             agreement.is_perpetual = agreement.is_perpetual ? true : false
302
303             if (agreement.vendor_id == "") {
304                 agreement.vendor_id = null
305             }
306
307             agreement.periods = agreement.periods.map(({ agreement_id, agreement_period_id, ...keepAttrs }) => keepAttrs)
308
309             agreement.user_roles = agreement.user_roles.map(({ patron, patron_str, ...keepAttrs }) => keepAttrs)
310
311             agreement.agreement_licenses = agreement.agreement_licenses.map(({ license, agreement_id, agreement_license_id, ...keepAttrs }) => keepAttrs)
312
313             agreement.agreement_relationships = agreement.agreement_relationships.map(({ related_agreement, ...keepAttrs }) => keepAttrs)
314
315             agreement.documents = agreement.documents.map(({ file_type, uploaded_on, ...keepAttrs }) => keepAttrs)
316
317             delete agreement.agreement_packages
318
319             const options = {
320                 method: method,
321                 body: JSON.stringify(agreement),
322                 headers: {
323                     'Content-Type': 'application/json;charset=utf-8'
324                 },
325             }
326
327             fetch(apiUrl, options)
328                 .then(response => {
329                     if (response.status == 200) {
330                         this.$router.push("/cgi-bin/koha/erm/agreements")
331                         setMessage(this.$t("Agreement updated"))
332                     } else if (response.status == 201) {
333                         this.$router.push("/cgi-bin/koha/erm/agreements")
334                         setMessage(this.$t("Agreement created"))
335                     } else {
336                         setError(response.message || response.statusText)
337                     }
338                 }).catch(
339                     (error) => {
340                         this.setError(error)
341                     }
342                 )
343         },
344         onStatusChanged(e) {
345             if (e.authorised_value != 'closed') {
346                 this.agreement.closure_reason = ''
347             }
348         }
349     },
350     components: {
351         AgreementPeriods,
352         AgreementUserRoles,
353         AgreementLicenses,
354         AgreementRelationships,
355         Documents,
356     },
357     name: "AgreementsFormAdd",
358 }
359 </script>