24af07e5b8706d68a1932b086f4853a9a78095a1
[kivitendo-erp.git] / templates / webpages / csv_import / form.html
1 [%- USE HTML %]
2 [%- USE LxERP %]
3 [%- USE L %]
4 [%- USE T8 %]
5
6  <div class="listtop">[% FORM.title %]</div>
7
8  [%- INCLUDE 'common/flash.html' %]
9
10  <form method="post" action="controller.pl" enctype="multipart/form-data">
11   [% L.hidden_tag('form_sent', '1') %]
12   [% L.hidden_tag('action', 'CsvImport/dispatch') %]
13   [% L.hidden_tag('profile.type', SELF.profile.type) %]
14
15   <h2>[%- LxERP.t8('Import profiles') %]</h2>
16
17   <table>
18    [%- IF SELF.profile.id %]
19     <tr>
20      <th align="right">[%- LxERP.t8('Current profile') %]:</th>
21      <td>[%- HTML.escape(SELF.profile.name) %]</td>
22     </tr>
23    [%- END %]
24
25    [%- IF SELF.all_profiles.size %]
26     <tr>
27      <th align="right">[%- LxERP.t8('Existing profiles') %]:</th>
28      <td>
29       [% L.select_tag('profile.id', SELF.all_profiles, title_key = 'name', default = SELF.profile.id, style = 'width: 300px') %]
30      </td>
31      <td>
32       [% L.submit_tag('action_new', LxERP.t8('Load profile')) %]
33       [% L.submit_tag('action_destroy', LxERP.t8('Delete profile'), confirm => LxERP.t8('Do you really want to delete this object?')) %]
34      </td>
35     </tr>
36    [%- END %]
37
38    <tr>
39     <th align="right" valign="top">[%- LxERP.t8('Save settings as') %]:</th>
40     <td valign="top">
41      [% L.input_tag('profile.name', '', style => 'width: 300px') %]
42      <br>
43      [% L.checkbox_tag('profile.is_default', label => LxERP.t8('Make default profile')) %]
44     </td>
45     <td valign="top">[% L.submit_tag('action_save', LxERP.t8('Save profile')) %]</td>
46    </tr>
47   </table>
48
49   <hr>
50
51   <h2>[%- LxERP.t8('Help on column names') %]</h2>
52
53   <div class="help_toggle">
54    <a href="#" onClick="javascript:$('.help_toggle').toggle()">[% LxERP.t8("Show help text") %]</a>
55   </div>
56
57   <div class="help_toggle" style="display:none">
58    <p><a href="#" onClick="javascript:$('.help_toggle').toggle()">[% LxERP.t8("Hide help text") %]</a></p>
59
60    [%- IF SELF.worker.is_multiplexed %]
61      <table>
62        <tr class="listheading">
63          [%- FOREACH p = SELF.worker.profile %]
64            <th>[%- p.row_ident %]</th>
65          [%- END %]
66        </tr>
67        <tr class="listrow[% loop.count % 2 %]">
68          [%- FOREACH p = SELF.worker.profile %]
69            [% SET ri = p.row_ident %]
70          <td>
71            <table>
72              <tr class="listheading">
73                <th>[%- LxERP.t8('Column name') %]</th>
74                <th>[%- LxERP.t8('Meaning') %]</th>
75              </tr>
76
77              [%- FOREACH row = SELF.displayable_columns.$ri %]
78              <tr class="listrow[% loop.count % 2 %]">
79                <td>[%- HTML.escape(row.name) %]</td>
80                <td>[%- HTML.escape(row.description) %]</td>
81              </tr>
82              [%- END %]
83            </table>
84          </td>
85          [%- END %]
86        </tr>
87      </table>
88    [%- ELSE %]
89      <table>
90        <tr class="listheading">
91          <th>[%- LxERP.t8('Column name') %]</th>
92          <th>[%- LxERP.t8('Meaning') %]</th>
93        </tr>
94
95        [%- FOREACH row = SELF.displayable_columns %]
96        <tr class="listrow[% loop.count % 2 %]">
97          <td>[%- HTML.escape(row.name) %]</td>
98          <td>[%- HTML.escape(row.description) %]</td>
99        </tr>
100        [%- END %]
101      </table>
102    [%- END %]
103
104 [%- IF SELF.type == 'contacts' %]
105    <p>
106     [%- LxERP.t8("You can update existing contacts by providing the 'cp_id' column with their database IDs. Otherwise: ") %]
107     [%- LxERP.t8('At least one of the columns #1, customer, customernumber, vendor, vendornumber (depending on the target table) is required for matching the entry to an existing customer or vendor.', 'cp_cv_id') %]
108    </p>
109
110 [%- ELSIF SELF.type == 'addresses' %]
111    <p>
112     [%- LxERP.t8('At least one of the columns #1, customer, customernumber, vendor, vendornumber (depending on the target table) is required for matching the entry to an existing customer or vendor.', 'trans_id') %]
113    </p>
114
115 [%- ELSIF SELF.type == 'parts' %]
116    <p>
117     [1]:
118     [% LxERP.t8('The three columns "make_X", "model_X" and "lastcost_X" with the same number "X" are used to import vendor part numbers and vendor prices.') %]
119     [% LxERP.t8('The column triplets can occur multiple times with different numbers "X" each time (e.g. "make_1", "model_1", "lastcost_1", "make_2", "model_2", "lastcost_2", "make_3", "model_3", "lastcost_3" etc).') %]
120     [% LxERP.t8('The items are imported accoring do their number "X" regardless of the column order inside the file.') %]
121     [% LxERP.t8('The column "make_X" can contain either a vendor\'s database ID, a vendor number or a vendor\'s name.') %]
122    </p>
123     <p>
124     [2]:
125     [% LxERP.t8('Onhand only sets the quantity in master data, not in inventory. This is only a legacy info field and will be overwritten as soon as a inventory transfer happens.') %]
126    </p>
127    <p>
128     [3]:
129     [% LxERP.t8("If the article type is set to 'mixed' then a column called 'type' must be present.") %]
130     [% LxERP.t8("Type can be either 'part', 'service' or 'assembly'.") %]
131     [% LxERP.t8("Assemblies can not be imported (yet). But the type column is used for sanity checks on price updates in order to prevent that articles with the wrong type will be updated.") %]
132    </p>
133
134 [%- ELSIF SELF.type == 'orders' %]
135    <p>
136     [1]:
137     [% LxERP.t8('The column "datatype" must be present and must be at the same position / column in each data set. The values must be the row names (see settings) for order and item data respectively.') %]
138    </p>
139    <p>
140     [2]:
141     [%- LxERP.t8('Amount and net amount are calculated by kivitendo. "verify_amount" and "verify_netamount" can be used for sanity checks.') %]<br>
142     [%- LxERP.t8('If amounts differ more than "Maximal amount difference" (see settings), this item is marked as invalid.') %]<br>
143    </p>
144 [%- END %]
145
146    <p>
147     [%- L.submit_tag('action_download_sample', LxERP.t8('Download sample file')) %]
148    </p>
149
150   </div>
151
152   <hr>
153
154   <h2>[%- LxERP.t8('Settings') %]</h2>
155
156   <div class="settings_toggle"[% UNLESS SELF.deferred || SELF.import_status %] style="display:none"[% END %]>
157    <a href="#" onClick="javascript:$('.settings_toggle').toggle()">[% LxERP.t8("Show settings") %]</a>
158   </div>
159
160   <div class="settings_toggle"[% IF SELF.deferred || SELF.import_status %] style="display:none"[% END %]>
161    <p><a href="#" onClick="javascript:$('.settings_toggle').toggle()">[% LxERP.t8("Hide settings") %]</a></p>
162
163   <table>
164    <tr>
165     <th align="right">[%- LxERP.t8('Number Format') %]:</th>
166     <td colspan="10">
167      [% L.select_tag('settings.numberformat', ['1.000,00', '1000,00', '1,000.00', '1000.00'], default = SELF.profile.get('numberformat'), style = 'width: 300px') %]
168     </td>
169    </tr>
170
171    <tr>
172     <th align="right">[%- LxERP.t8('Charset') %]:</th>
173     <td colspan="10">[% L.select_tag('settings.charset', SELF.all_charsets, default = SELF.profile.get('charset'), style = 'width: 300px') %]</td>
174    </tr>
175
176    <tr>
177     <th align="right">[%- LxERP.t8('Separator') %]:</th>
178     [% SET custom_sep_char = SELF.sep_char %]
179     [% FOREACH entry = SELF.all_sep_chars %]
180      <td>
181       [% IF SELF.sep_char == entry.first %] [% SET custom_sep_char = '' %] [%- END %]
182       [% L.radio_button_tag('sep_char', value => entry.first, label => entry.last, checked => SELF.sep_char == entry.first) %]
183      </td>
184     [%- END %]
185
186     <td>
187      [% L.radio_button_tag('sep_char', value => 'custom', checked => custom_sep_char != '') %]
188      [% L.input_tag('custom_sep_char', custom_sep_char, size => 3, maxlength => 1) %]
189     </td>
190    </tr>
191
192    <tr>
193     <th align="right">[%- LxERP.t8('Quote character') %]:</th>
194     [% SET custom_quote_char = SELF.quote_char %]
195     [% FOREACH entry = SELF.all_quote_chars %]
196      <td>
197       [% IF SELF.quote_char == entry.first %] [% SET custom_quote_char = '' %] [%- END %]
198       [% L.radio_button_tag('quote_char', value => entry.first, label => entry.last, checked => SELF.quote_char == entry.first) %]
199      </td>
200     [%- END %]
201
202     <td>
203      [% L.radio_button_tag('quote_char', value => 'custom', checked => custom_quote_char != '') %]
204      [% L.input_tag('custom_quote_char', custom_quote_char, size => 3, maxlength => 1) %]
205     </td>
206    </tr>
207
208    <tr>
209     <th align="right">[%- LxERP.t8('Escape character') %]:</th>
210     [% SET custom_escape_char = SELF.escape_char %]
211     [% FOREACH entry = SELF.all_escape_chars %]
212      <td>
213       [% IF SELF.escape_char == entry.first %] [% SET custom_escape_char = '' %] [%- END %]
214       [% L.radio_button_tag('escape_char', value => entry.first, label => entry.last, checked => SELF.escape_char == entry.first) %]
215      </td>
216     [%- END %]
217
218     <td>
219      [% L.radio_button_tag('escape_char', value => 'custom', checked => custom_escape_char != '') %]
220      [% L.input_tag('custom_escape_char', custom_escape_char, size => 3, maxlength => 1) %]
221     </td>
222    </tr>
223
224    [% duplicate_fields = SELF.worker.get_duplicate_check_fields() %]
225    [% IF ( duplicate_fields.size ) %]
226      <tr>
227        <th align="right">[%- LxERP.t8('Check for duplicates') %]:</th>
228
229        <td colspan=10>
230          [% FOREACH key = duplicate_fields.keys %]
231            <input type="checkbox" name="settings.duplicates_[% key | html %]" id="settings.duplicates_[% key | html %]" value="1"[% IF ( SELF.profile.get('duplicates_'_ key) || (duplicate_fields.$key.default && !FORM.form_sent ) ) %] checked="checked"[% END %]>
232            <label for="settings.duplicates_[% key | html %]">[% duplicate_fields.$key.label | html %]</label>
233          [% END %]
234        </td>
235      </tr>
236
237      <tr>
238        <th align="right"></th>
239
240        <td colspan=10>
241          [% opts = [ [ 'no_check',  LxERP.t8('Do not check for duplicates') ],
242                      [ 'check_csv', LxERP.t8('Discard duplicate entries in CSV file') ],
243                      [ 'check_db',  LxERP.t8('Discard entries with duplicates in database or CSV file') ] ] %]
244          [% L.select_tag('settings.duplicates', opts, default = SELF.profile.get('duplicates'), style = 'width: 300px') %]
245        </td>
246      </tr>
247    [% END %]
248
249 [%- IF SELF.type == 'parts' %]
250  [%- INCLUDE 'csv_import/_form_parts.html' %]
251 [%- ELSIF SELF.type == 'customers_vendors' %]
252  [%- INCLUDE 'csv_import/_form_customers_vendors.html' %]
253 [%- ELSIF SELF.type == 'contacts' %]
254  [%- INCLUDE 'csv_import/_form_contacts.html' %]
255 [%- ELSIF SELF.type == 'orders' %]
256  [%- INCLUDE 'csv_import/_form_orders.html' %]
257 [%- END %]
258
259    <tr>
260     <th align="right">[%- LxERP.t8('Preview Mode') %]:</th>
261     <td colspan="10">
262       [% L.radio_button_tag('settings.full_preview', value=2, checked=SELF.profile.get('full_preview')==2, label=LxERP.t8('Full Preview')) %]
263       [% L.radio_button_tag('settings.full_preview', value=1, checked=SELF.profile.get('full_preview')==1, label=LxERP.t8('Only Warnings and Errors')) %]
264       [% L.radio_button_tag('settings.full_preview', value=0, checked=!SELF.profile.get('full_preview'),   label=LxERP.t8('First 20 Lines')) %]
265     </td>
266    </tr>
267
268    <tr>
269     <th align="right">[%- LxERP.t8('Import file') %]:</th>
270     <td colspan="10">[% L.input_tag('file', '', type => 'file', accept => '*') %]</td>
271    </tr>
272
273    [%- IF SELF.file.exists %]
274     <tr>
275      <th align="right">[%- LxERP.t8('Existing file on server') %]:</th>
276      <td colspan="10">[%- LxERP.t8('Uploaded on #1, size #2 kB', SELF.file.displayable_mtime, LxERP.format_amount(SELF.file.size / 1024, 2)) %]</td>
277     </tr>
278    [%- END %]
279
280   </table>
281
282   </div>
283   <hr>
284
285   [% L.submit_tag('action_test', LxERP.t8('Test and preview')) %]
286   [% L.submit_tag('action_import', LxERP.t8('Import'), style='display:none') %]
287
288  </form>
289
290  <div id='results'>
291  [%- IF SELF.deferred %]
292    [%- PROCESS 'csv_import/_deferred_results.html' %]
293  [%- ELSIF SELF.import_status %]
294    [%- PROCESS 'csv_import/_results.html' %]
295  [%- END %]
296  </div>
297
298
299  <script type="text/javascript">
300   <!--
301     $(document).ready(function() {
302       $('#action_save').click(function() {
303         if ($('#profile_name').val() != '')
304           return true;
305         alert('[% LxERP.t8('Please enter a profile name.') %]');
306         return false;
307       })
308     });
309     -->
310  </script>