View | Details | Raw Unified | Return to bug 40333
Collapse All | Expand All

(-)a/acqui/invoice.pl (+29 lines)
Lines 44-49 use Koha::DateUtils qw( output_pref ); Link Here
44
use Koha::Misc::Files;
44
use Koha::Misc::Files;
45
use Koha::Acquisition::Invoice::Adjustments;
45
use Koha::Acquisition::Invoice::Adjustments;
46
use Koha::Acquisition::Invoices;
46
use Koha::Acquisition::Invoices;
47
use Koha::Edifact::Files;
47
48
48
my $input = CGI->new;
49
my $input = CGI->new;
49
my ( $template, $loggedinuser, $cookie, $flags ) = get_template_and_user(
50
my ( $template, $loggedinuser, $cookie, $flags ) = get_template_and_user(
Lines 317-322 $template->param( Link Here
317
    additional_field_values     => $invoice->get_additional_field_values_for_template,
318
    additional_field_values     => $invoice->get_additional_field_values_for_template,
318
);
319
);
319
320
321
# Check for EDIFACT message information
322
my $edifact_message;
323
my $edifact_errors  = [];
324
my $edifact_enabled = C4::Context->preference('EDIFACT');
325
326
if ( $edifact_enabled && $details->{'message_id'} ) {
327
    $edifact_message = Koha::Edifact::Files->find( $details->{'message_id'} );
328
329
    if ($edifact_message) {
330
331
        # Get any processing errors for this message using the relation accessor
332
        my $errors = $edifact_message->errors;
333
334
        while ( my $error = $errors->next ) {
335
            push @$edifact_errors, {
336
                section => $error->section,
337
                details => $error->details,
338
            };
339
        }
340
    }
341
}
342
343
$template->param(
344
    edifact_enabled => $edifact_enabled,
345
    edifact_message => $edifact_message,
346
    edifact_errors  => $edifact_errors,
347
);
348
320
$template->param(
349
$template->param(
321
    invoiceid                   => $details->{'invoiceid'},
350
    invoiceid                   => $details->{'invoiceid'},
322
    invoicenumber               => $details->{'invoicenumber'},
351
    invoicenumber               => $details->{'invoicenumber'},
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/modals/edifact-modal.inc (+38 lines)
Line 0 Link Here
1
[%# EDIFACT message modal include %]
2
[%# This modal can be used on any page that needs to display EDIFACT messages %]
3
4
<!-- Modal to display EDIFACT messages -->
5
<div class="modal" id="EDI_modal" tabindex="-1" role="dialog" aria-labelledby="EDI_modal_label" aria-hidden="true">
6
    <div class="modal-dialog modal-lg">
7
        <div class="modal-content">
8
            <div class="modal-header">
9
                <h1 class="modal-title" id="EDI_modal_label">EDIFACT message</h1>
10
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
11
            </div>
12
            <div class="modal-body">
13
                <div id="edi_loading"><img src="[% interface | html %]/[% theme | html %]/img/spinner-small.gif" alt="" /> Loading</div>
14
            </div>
15
            <div class="modal-footer">
16
                <button class="btn btn-default" data-bs-dismiss="modal">Close</button>
17
            </div>
18
        </div>
19
    </div>
20
</div>
21
22
<!-- Modal to display EDIFACT errors -->
23
<div class="modal" id="EDI_errors_modal" tabindex="-1" role="dialog" aria-labelledby="EDI_errors_modal_label" aria-hidden="true">
24
    <div class="modal-dialog modal-lg">
25
        <div class="modal-content">
26
            <div class="modal-header">
27
                <h1 class="modal-title" id="EDI_errors_modal_label">EDIFACT processing errors for <span id="EDI_errors_filename"></span></h1>
28
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
29
            </div>
30
            <div class="modal-body">
31
                <div id="edi_errors_loading"><img src="[% interface | html %]/[% theme | html %]/img/spinner-small.gif" alt="" /> Loading</div>
32
            </div>
33
            <div class="modal-footer">
34
                <button class="btn btn-default" data-bs-dismiss="modal">Close</button>
35
            </div>
36
        </div>
37
    </div>
38
</div>
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/edifactmsgs.tt (-178 / +112 lines)
Lines 37-232 Link Here
37
    </div>
37
    </div>
38
    <!-- /#acqui_edifactmsgs -->
38
    <!-- /#acqui_edifactmsgs -->
39
39
40
    <!-- Modal to display EDIFACT messages -->
40
    [% INCLUDE 'modals/edifact-modal.inc' %]
41
    <div class="modal" id="EDI_modal" tabindex="-1" role="dialog" aria-labelledby="EDI_modal_label" aria-hidden="true">
42
        <div class="modal-dialog modal-lg">
43
            <div class="modal-content">
44
                <div class="modal-header">
45
                    <h1 class="modal-title" id="EDI_modal_label">EDIFACT message</h1>
46
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
47
                </div>
48
                <div class="modal-body"> </div>
49
                <div class="modal-footer">
50
                    <button class="btn btn-default" data-bs-dismiss="modal">Close</button>
51
                </div>
52
            </div>
53
        </div>
54
    </div>
55
56
    <!-- Modal to display EDIFACT errors -->
57
    <div class="modal" id="EDI_errors_modal" tabindex="-1" role="dialog" aria-labelledby="EDI_errors_modal_label" aria-hidden="true">
58
        <div class="modal-dialog modal-lg">
59
            <div class="modal-content">
60
                <div class="modal-header">
61
                    <h1 class="modal-title" id="EDI_errors_modal_label">EDIFACT processing errors for <span id="EDI_errors_filename"></span></h1>
62
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
63
                </div>
64
                <div class="modal-body">
65
                    <div id="loading"> <img src="[% interface | html %]/[% theme | html %]/img/spinner-small.gif" alt="" /> Loading </div>
66
                </div>
67
                <div class="modal-footer">
68
                    <button class="btn btn-default" data-bs-dismiss="modal">Close</button>
69
                </div>
70
            </div>
71
        </div>
72
    </div>
73
[% END %]
41
[% END %]
74
42
75
[% MACRO jsinclude BLOCK %]
43
[% MACRO jsinclude BLOCK %]
76
    [% Asset.js("js/acquisitions-menu.js") | $raw %]
44
    [% Asset.js("js/acquisitions-menu.js") | $raw %]
77
    [% INCLUDE 'datatables.inc' %]
45
    [% INCLUDE 'datatables.inc' %]
46
    [% Asset.js("js/modals/edifact-modal.js") | $raw %]
78
    <script>
47
    <script>
79
        $(document).ready(function() {
48
        $(document).ready(function () {
80
            let edi_msgs_table_url = '/api/v1/acquisitions/edifiles?';
49
            let edi_msgs_table_url = "/api/v1/acquisitions/edifiles?";
81
50
82
            var edi_msgs_table = $("#edi_msgs").kohaTable({
51
            var edi_msgs_table = $("#edi_msgs").kohaTable(
83
                "ajax": {
52
                {
84
                    "url": edi_msgs_table_url
53
                    ajax: {
85
                },
54
                        url: edi_msgs_table_url,
86
                "embed": [
87
                    "vendor",
88
                    "basket",
89
                    "errors"
90
                ],
91
                "order": [[ 1, "desc" ]],
92
                "columns": [
93
                    {
94
                        "data": "type",
95
                        "title": _("Type"),
96
                        "searchable": true,
97
                        "orderable": true
98
                    },
99
                    {
100
                        "data": "transfer_date",
101
                        "title": _("Transferred"),
102
                        "searchable": true,
103
                        "orderable": true,
104
                        "render": function(data, type, row, meta) {
105
                            return $date(row.transfer_date);
106
                        }
107
                    },
55
                    },
108
                    {
56
                    embed: ["vendor", "basket", "errors"],
109
                        "data": "status",
57
                    order: [[1, "desc"]],
110
                        "title": _("Status"),
58
                    columns: [
111
                        "searchable": true,
59
                        {
112
                        "orderable": true,
60
                            data: "type",
113
                        "render": function(daya, type, row, meta) {
61
                            title: _("Type"),
114
                            let rendered = '';
62
                            searchable: true,
115
                            if ( row.errors.length > 0 ) {
63
                            orderable: true,
116
                                let errorsList = '<ul>';
64
                        },
117
                                row.errors.forEach(error => {
65
                        {
118
                                    if (error.details) {
66
                            data: "transfer_date",
119
                                        errorsList += '<li>'
67
                            title: _("Transferred"),
120
                                        errorsList += error.details
68
                            searchable: true,
121
                                        if (error.section) {
69
                            orderable: true,
122
                                            errorsList += '</br><pre>' + error.section + '</pre>';
70
                            render: function (data, type, row, meta) {
71
                                return $date(row.transfer_date);
72
                            },
73
                        },
74
                        {
75
                            data: "status",
76
                            title: _("Status"),
77
                            searchable: true,
78
                            orderable: true,
79
                            render: function (daya, type, row, meta) {
80
                                let rendered = "";
81
                                if (row.errors.length > 0) {
82
                                    let errorsList = "<ul>";
83
                                    row.errors.forEach(error => {
84
                                        if (error.details) {
85
                                            errorsList += "<li>";
86
                                            errorsList += "<strong>" + error.details + "</strong>";
87
                                            if (error.section) {
88
                                                errorsList += "<br/><pre>" + error.section + "</pre>";
89
                                            }
90
                                            errorsList += "</li>";
123
                                        }
91
                                        }
124
                                        errorsList += '</li>';
92
                                    });
93
                                    errorsList += "</ul>";
94
                                    rendered = row.status + ' (<a href="#" data-bs-toggle="modal" data-bs-target="#EDI_errors_modal" data-bs-errors="' + errorsList + '" data-bs-filename="' + row.filename + '">' + _("with errors") + "</a>)";
95
                                } else {
96
                                    rendered = row.status;
97
                                }
98
                                return rendered;
99
                            },
100
                        },
101
                        {
102
                            data: "vendor.name",
103
                            title: _("Vendor"),
104
                            searchable: true,
105
                            orderable: true,
106
                            render: function (data, type, row, meta) {
107
                                let link;
108
                                if (row.vendor) {
109
                                    link = '<a href="/cgi-bin/koha/acquisition/vendors/' + row.vendor_id + '">' + row.vendor.name + "</a>";
110
                                } else {
111
                                    link = '<a href="/cgi-bin/koha/acquisition/vendors/' + row.vendor_id + '">' + row.vendor_id + "</a>";
112
                                }
113
                                return link;
114
                            },
115
                        },
116
                        {
117
                            data: "basket_id:type",
118
                            title: _("Details"),
119
                            searchable: false,
120
                            orderable: true,
121
                            render: function (data, type, row, meta) {
122
                                let rendered = "";
123
                                if (row.type == "QUOTE" || row.type == "ORDERS") {
124
                                    if (row.basket_id) {
125
                                        rendered = '<a href="/cgi-bin/koha/acqui/basket.pl?basketno=' + row.basket_id + '">' + _("Basket") + ": " + row.basket_id + "</a>";
125
                                    }
126
                                    }
126
                                });
127
                                } else {
127
                                errorsList += '</ul>';
128
                                    rendered = '<a href="/cgi-bin/koha/acqui/invoices.pl?message_id=' + row.id + '&op=do_search">' + _("Invoices") + "</a>";
128
                                rendered = row.status + ' (<a href="#" data-bs-toggle="modal" data-bs-target="#EDI_errors_modal" data-bs-errors="'+ errorsList + '" data-bs-filename="' + row.filename + '">' + _("with errors") + '</a>)';
129
                            } else {
130
                                rendered = row.status;
131
                            }
132
                            return rendered;
133
                        }
134
                    },
135
                    {
136
                        "data": "vendor.name",
137
                        "title": _("Vendor"),
138
                        "searchable": true,
139
                        "orderable": true,
140
                        "render": function(data, type, row, meta) {
141
                            let link;
142
                            if ( row.vendor ) {
143
                               link = '<a href="/cgi-bin/koha/acquisition/vendors/'+row.vendor_id+'">'+row.vendor.name+'</a>';
144
                            } else {
145
                               link = '<a href="/cgi-bin/koha/acquisition/vendors/'+row.vendor_id+'">'+row.vendor_id+'</a>';
146
                            }
147
                            return link;
148
                        }
149
                    },
150
                    {
151
                        "data": "basket_id:type",
152
                        "title": _("Details"),
153
                        "searchable": false,
154
                        "orderable": true,
155
                        "render": function(data, type, row, meta) {
156
                            let rendered = '';
157
                            if ( row.type == 'QUOTE' || row.type == 'ORDERS' ) {
158
                                if ( row.basket_id ) {
159
                                    rendered = '<a href="/cgi-bin/koha/acqui/basket.pl?basketno='+row.basket_id+'">'+_("Basket")+': '+row.basket_id+'</a>';
160
                                }
129
                                }
161
                            } else {
130
                                return rendered;
162
                                rendered = '<a href="/cgi-bin/koha/acqui/invoices.pl?message_id='+row.id+'&op=do_search">'+_("Invoices")+'</a>';
131
                            },
163
                            }
132
                        },
164
                            return rendered;
133
                        {
165
                        }
134
                            data: "filename",
166
                    },
135
                            title: _("Filename"),
167
                    {
136
                            searchable: true,
168
                        "data": "filename",
137
                            orderable: true,
169
                        "title": _("Filename"),
138
                        },
170
                        "searchable": true,
139
                        {
171
                        "orderable": true
140
                            title: _("Actions"),
172
                    },
141
                            className: "actions",
173
                    {
142
                            searchable: false,
174
                        "title": _("Actions"),
143
                            orderable: false,
175
                        "className": "actions",
144
                            render: function (data, type, row, meta) {
176
                        "searchable": false,
145
                                var result =
177
                        "orderable": false,
146
                                    '<a class="btn btn-default btn-xs view_message" target="_blank" href="/cgi-bin/koha/acqui/edimsg.pl?id=' + encodeURIComponent(row.id) + '"><i class="fa fa-search"></i> ' + _("View message") + "</a> ";
178
                        "render": function(data, type, row, meta) {
147
                                result += '<form action="/cgi-bin/koha/acqui/edifactmsgs.pl" method="post"><input type="hidden" name="message_id" value="' + encodeURIComponent(row.id) + '" />';
179
                            var result = '<a class="btn btn-default btn-xs view_message" target="_blank" href="/cgi-bin/koha/acqui/edimsg.pl?id='+encodeURIComponent(row.id)+'"><i class="fa fa-search"></i> '+_("View message")+'</a> ';
148
                                result += '<input type="hidden" name="csrf_token" value="' + $('meta[name="csrf-token"]').attr("content").trim() + '" />';
180
                            result += '<form action="/cgi-bin/koha/acqui/edifactmsgs.pl" method="post"><input type="hidden" name="message_id" value="'+encodeURIComponent(row.id)+'" />';
149
                                result += '<input type="hidden" name="op" value="cud-delete" /><button type="submit" class="btn btn-default btn-xs delete_msg"><i class="fa fa-trash-can"></i> ' + _("Delete") + "</button> ";
181
                            result += '<input type="hidden" name="csrf_token" value="' + $('meta[name="csrf-token"]').attr('content').trim() + '" />';
150
                                if (row.status == "new") {
182
                            result += '<input type="hidden" name="op" value="cud-delete" /><button type="submit" class="btn btn-default btn-xs delete_msg"><i class="fa fa-trash-can"></i> '+_("Delete")+'</button> ';
151
                                    result +=
183
                            if ( row.status == 'new' ) {
152
                                        '<a class="btn btn-default btn-xs import_msg" href="/cgi-bin/koha/acqui/edifactmsgs.pl?op=import&amp;message_id=' + encodeURIComponent(row.id) + '"><i class="fa fa-cog"></i> ' + _("Import") + "</a> ";
184
                                result += '<a class="btn btn-default btn-xs import_msg" href="/cgi-bin/koha/acqui/edifactmsgs.pl?op=import&amp;message_id='+encodeURIComponent(row.id)+'"><i class="fa fa-cog"></i> '+_("Import")+'</a> ';
153
                                }
185
                            }
154
                                return result;
186
                            return result;
155
                            },
187
                        }
156
                        },
188
                    }
157
                    ],
189
                ]
158
                },
190
            }, 0, 0);
159
                0,
191
160
                0
192
            var EDIModal = $("#EDI_modal");
161
            );
193
            var EDIModalBody = $("#EDI_modal .modal-body");
194
195
            $("body").on("click", ".view_message", function(e){
196
                e.preventDefault();
197
                var page = $(this).attr("href");
198
                EDIModalBody.load(page + " #edimsg");
199
                EDIModal.modal("show");
200
            });
201
            EDIModal.on("click",".btn-close",function(e){
202
                e.preventDefault();
203
                EDIModal.modal("hide");
204
            });
205
            EDIModal.on("hidden.bs.modal", function(){
206
                EDIModalBody.html("<div id=\"loading\"><img src=\"[% interface | html %]/[% theme | html %]/img/spinner-small.gif\" alt=\"\" /> "+_("Loading")+"</div>");
207
            });
208
209
            const errorsModal = document.getElementById('EDI_errors_modal')
210
            if (errorsModal) {
211
              errorsModal.addEventListener('show.bs.modal', event => {
212
                // Link that triggered the modal
213
                const link = event.relatedTarget
214
215
                // Extract info from data-bs-* attributes
216
                const filename = link.getAttribute('data-bs-filename')
217
                const errors = link.getAttribute('data-bs-errors')
218
219
                // Update the modal's title.
220
                const modalTitleSpan = errorsModal.querySelector('.modal-title #EDI_errors_filename')
221
                modalTitleSpan.textContent = filename;
222
223
                // Update the modal's content.
224
                const modalBody = errorsModal.querySelector('.modal-body')
225
                modalBody.innerHTML = errors;
226
              })
227
            }
228
162
229
            $("body").on("click", ".delete_msg" ,function(){
163
            $("body").on("click", ".delete_msg", function () {
230
                return confirm(_("Are you sure you want to delete this message?"));
164
                return confirm(_("Are you sure you want to delete this message?"));
231
            });
165
            });
232
        });
166
        });
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/invoice.tt (+35 lines)
Lines 57-62 Link Here
57
57
58
    <p>Vendor: <a href="/cgi-bin/koha/acquisition/vendors/[% booksellerid | uri %]">[% suppliername | html %]</a></p>
58
    <p>Vendor: <a href="/cgi-bin/koha/acquisition/vendors/[% booksellerid | uri %]">[% suppliername | html %]</a></p>
59
59
60
    [% IF edifact_enabled && edifact_message %]
61
        <div class="page-section">
62
            <h3>EDIFACT Message</h3>
63
            <p>
64
                <strong>Message type:</strong> [% edifact_message.message_type | html %] <strong>Transfer date:</strong> [% edifact_message.transfer_date | $KohaDates %] <strong>Status:</strong> [% edifact_message.status | html %]
65
                [% IF edifact_message.filename %]
66
                    <strong>Filename:</strong> [% edifact_message.filename | html %]
67
                [% END %]
68
            </p>
69
            <p>
70
                <a href="#" class="btn btn-default btn-sm view_edifact_message" data-message-id="[% edifact_message.id | html %]"> <i class="fa fa-search"></i> View EDIFACT message </a>
71
            </p>
72
73
            [% IF edifact_errors.size > 0 %]
74
                <div class="alert alert-warning">
75
                    <h4><i class="fa fa-exclamation-triangle"></i> EDIFACT Processing Errors</h4>
76
                    <ul>
77
                        [% FOREACH error IN edifact_errors %]
78
                            <li>
79
                                <strong>[% error.details | html %]</strong>
80
                                [% IF error.section %]
81
                                    <br /><pre class="mt-1 mb-0 small text-muted">[% error.section | html %]</pre>
82
                                [% END %]
83
                            </li>
84
                        [% END %]
85
                    </ul>
86
                </div>
87
            [% END %]
88
        </div>
89
    [% END %]
90
60
    <form action="/cgi-bin/koha/acqui/invoice.pl" method="post" class="validated">
91
    <form action="/cgi-bin/koha/acqui/invoice.pl" method="post" class="validated">
61
        [% INCLUDE 'csrf-token.inc' %]
92
        [% INCLUDE 'csrf-token.inc' %]
62
        <fieldset class="rows">
93
        <fieldset class="rows">
Lines 524-529 Link Here
524
</div>
555
</div>
525
<!-- /#updateFund.modal -->
556
<!-- /#updateFund.modal -->
526
557
558
[% INCLUDE 'modals/edifact-modal.inc' %]
559
527
<div style="display:none;">
560
<div style="display:none;">
528
    <select id="all_fund_dropdown">
561
    <select id="all_fund_dropdown">
529
        <option value="">No fund</option>
562
        <option value="">No fund</option>
Lines 545-550 Link Here
545
    [% Asset.js("js/additional-fields-entry.js") | $raw %]
578
    [% Asset.js("js/additional-fields-entry.js") | $raw %]
546
    [% INCLUDE 'calendar.inc' %]
579
    [% INCLUDE 'calendar.inc' %]
547
    [% INCLUDE 'datatables.inc' %]
580
    [% INCLUDE 'datatables.inc' %]
581
    [% Asset.js("js/modals/edifact-modal.js") | $raw %]
548
    <script>
582
    <script>
549
        function updateColumnsVisibility(visible) {
583
        function updateColumnsVisibility(visible) {
550
            if ( visible ) {
584
            if ( visible ) {
Lines 678-683 Link Here
678
                    $('.ab_inactive').remove();
712
                    $('.ab_inactive').remove();
679
                }
713
                }
680
            });
714
            });
715
681
        });
716
        });
682
    </script>
717
    </script>
683
[% END %]
718
[% END %]
(-)a/koha-tmpl/intranet-tmpl/prog/js/modals/edifact-modal.js (-1 / +70 lines)
Line 0 Link Here
0
- 
1
// EDIFACT modal JavaScript functionality
2
// This script handles the EDIFACT message modal interactions
3
// Include this after the edifact-modal.inc template
4
5
/* global __ interface theme */
6
$(document).ready(function () {
7
    // Initialize modal elements
8
    var EDIModal = $("#EDI_modal");
9
    var EDIModalBody = $("#EDI_modal .modal-body");
10
    var EDIErrorsModal = $("#EDI_errors_modal");
11
12
    // Handle view EDIFACT message button clicks
13
    $("body").on("click", ".view_edifact_message", function (e) {
14
        e.preventDefault();
15
        var message_id = $(this).data("message-id");
16
        var page =
17
            "/cgi-bin/koha/acqui/edimsg.pl?id=" +
18
            encodeURIComponent(message_id);
19
        EDIModalBody.load(page + " #edimsg");
20
        EDIModal.modal("show");
21
    });
22
23
    // Handle view_message button clicks (for compatibility with existing code)
24
    $("body").on("click", ".view_message", function (e) {
25
        e.preventDefault();
26
        var page = $(this).attr("href");
27
        EDIModalBody.load(page + " #edimsg");
28
        EDIModal.modal("show");
29
    });
30
31
    // Handle modal close button
32
    EDIModal.on("click", ".btn-close", function (e) {
33
        e.preventDefault();
34
        EDIModal.modal("hide");
35
    });
36
37
    // Reset modal content when hidden
38
    EDIModal.on("hidden.bs.modal", function () {
39
        EDIModalBody.html(
40
            "<div id='edi_loading'><img style='display:inline-block' src='" +
41
                interface +
42
                "/" +
43
                theme +
44
                "/img/spinner-small.gif' alt='' /> Loading</div>"
45
        );
46
    });
47
48
    // Handle EDIFACT errors modal
49
    const errorsModal = document.getElementById("EDI_errors_modal");
50
    if (errorsModal) {
51
        errorsModal.addEventListener("show.bs.modal", function (event) {
52
            // Link that triggered the modal
53
            const link = event.relatedTarget;
54
55
            // Extract info from data-bs-* attributes
56
            const filename = link.getAttribute("data-bs-filename");
57
            const errors = link.getAttribute("data-bs-errors");
58
59
            // Update the modal's title
60
            const modalTitleSpan = errorsModal.querySelector(
61
                ".modal-title #EDI_errors_filename"
62
            );
63
            modalTitleSpan.textContent = filename;
64
65
            // Update the modal's content
66
            const modalBody = errorsModal.querySelector(".modal-body");
67
            modalBody.innerHTML = errors;
68
        });
69
    }
70
});

Return to bug 40333