Merge lp:~mukunde/unifield-server/US-12645 into lp:unifield-server
- US-12645
- Merge into trunk
Proposed by
jftempo
Status: | Merged |
---|---|
Merged at revision: | 6287 |
Proposed branch: | lp:~mukunde/unifield-server/US-12645 |
Merge into: | lp:unifield-server |
Diff against target: |
1115 lines (+706/-28) (has conflicts) 3 files modified
bin/addons/msf_profile/i18n/fr_MF.po (+213/-12) bin/addons/product_asset/product_asset.py (+407/-9) bin/addons/product_asset/product_asset_view.xml (+86/-7) Text conflict in bin/addons/msf_profile/i18n/fr_MF.po |
To merge this branch: | bzr merge lp:~mukunde/unifield-server/US-12645 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
UniField Reviewer Team | Pending | ||
Review via email: mp+465661@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
- 6250. By Gaël Mukunde
-
US-12440 [IMP] Add caches for frequently searched objects that may be the same across rows
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'bin/addons/msf_profile/i18n/fr_MF.po' |
2 | --- bin/addons/msf_profile/i18n/fr_MF.po 2024-05-02 13:19:58 +0000 |
3 | +++ bin/addons/msf_profile/i18n/fr_MF.po 2024-05-10 12:38:34 +0000 |
4 | @@ -5905,6 +5905,7 @@ |
5 | #: field:wizard.temp.posting.line,name:0 |
6 | #: field:product.template,name:0 |
7 | #: field:product.asset.type,description:0 |
8 | +#: field:product.asset.import.entries.errors,name:0 |
9 | #, python-format |
10 | msgid "Description" |
11 | msgstr "Description" |
12 | @@ -8671,7 +8672,7 @@ |
13 | msgid "The currency used to enter statement" |
14 | msgstr "Devise utilisée pour entrer les relevés" |
15 | |
16 | -#. modules: register_accounting, account_hq_entries, msf_homere_interface, msf_doc_import, account |
17 | +#. modules: register_accounting, account_hq_entries, msf_homere_interface, msf_doc_import, account, product_asset |
18 | #: field:msf.doc.import.accounting,filename:0 |
19 | #: field:hq.entries.import,filename:0 |
20 | #: field:hr.expat.employee.import,filename:0 |
21 | @@ -8682,6 +8683,7 @@ |
22 | #: field:account.invoice.import,filename:0 |
23 | #: field:account.cv.import,filename:0 |
24 | #: field:esc.line.import,filename:0 |
25 | +#: field:product.asset.import.entries,filename:0 |
26 | msgid "Imported filename" |
27 | msgstr "Nom du fichier importé" |
28 | |
29 | @@ -10156,8 +10158,9 @@ |
30 | msgid " e.g: 1 * (this unit) = ratio * (reference unit)" |
31 | msgstr " par exemple : 1 x (cette unité) = ratio x (unité de référence)" |
32 | |
33 | -#. module: msf_doc_import |
34 | +#. module: msf_doc_import, product_asset |
35 | #: view:msf.doc.import.accounting:0 |
36 | +#: view:product.asset.import.entries:0 |
37 | msgid "Import template" |
38 | msgstr "Import template" |
39 | |
40 | @@ -15467,6 +15470,7 @@ |
41 | #: code:addons/consumption_calculation/history_consumption.py:719 |
42 | #: field:msf_button_access_rights.button_access_rule,bar_type:0 |
43 | #: report:addons/account/report/export_cv.mako:137 |
44 | +#: field:product.asset.import.entries.lines,type:0 |
45 | msgid "Type" |
46 | msgstr "Type" |
47 | |
48 | @@ -19935,7 +19939,7 @@ |
49 | msgid "Some entries are already reconciled !" |
50 | msgstr "Certaines écritures sont déjà lettrées !" |
51 | |
52 | -#. modules: msf_doc_import, register_accounting, consumption_calculation, account, account_hq_entries |
53 | +#. modules: msf_doc_import, register_accounting, consumption_calculation, account, account_hq_entries, product_asset |
54 | #: field:weekly.forecast.report,progress:0 |
55 | #: field:abstract.wizard.import,progression:0 |
56 | #: field:msf.doc.import.accounting,progression:0 |
57 | @@ -19946,6 +19950,7 @@ |
58 | #: field:hq.entries.import,progress:0 |
59 | #: field:account.cv.import,progression:0 |
60 | #: field:esc.line.import,progress:0 |
61 | +#: field:product.asset.import.entries,progression:0 |
62 | msgid "Progression" |
63 | msgstr "Progression" |
64 | |
65 | @@ -20824,6 +20829,7 @@ |
66 | #: selection:product.asset,state:0 |
67 | #: selection:product.asset.event,asset_state:0 |
68 | #: selection:signature.follow_up,doc_state:0 |
69 | +#: selection:product.asset.import.entries,state:0 |
70 | msgid "Done" |
71 | msgstr "Clôturé" |
72 | |
73 | @@ -30182,7 +30188,7 @@ |
74 | msgid "Operator '%s' not suported" |
75 | msgstr "Operator '%s' not suported" |
76 | |
77 | -#. modules: register_accounting, account_mcdb, msf_homere_interface, financing_contract, procurement_request, consumption_calculation, sync_client, msf_config_locations, stock_forecast, base, msf_currency_revaluation, specific_rules, msf_doc_import, stock, analytic_distribution, account, purchase, product |
78 | +#. modules: register_accounting, account_mcdb, msf_homere_interface, financing_contract, procurement_request, consumption_calculation, sync_client, msf_config_locations, stock_forecast, base, msf_currency_revaluation, specific_rules, msf_doc_import, stock, analytic_distribution, account, purchase, product, product_asset |
79 | #: view:account.line.csv.export:0 |
80 | #: field:account.line.csv.export,message:0 |
81 | #: field:import.commitment.wizard,last_error:0 |
82 | @@ -30239,6 +30245,7 @@ |
83 | #: field:product.mass.update,message:0 |
84 | #: field:account.cv.import,message:0 |
85 | #: field:message.action,message:0 |
86 | +#: field:product.asset.import.entries,message:0 |
87 | msgid "Message" |
88 | msgstr "Message" |
89 | |
90 | @@ -37138,6 +37145,7 @@ |
91 | #: view:product.asset.type:0 |
92 | #: field:product.template,asset_type_id:0 |
93 | #: field:product.asset.useful.life,asset_type_id:0 |
94 | +#: field:product.asset.import.entries.lines,asset_type_id:0 |
95 | msgid "Asset Type" |
96 | msgstr "Type d'Immobilisation" |
97 | |
98 | @@ -38123,6 +38131,7 @@ |
99 | #: view:account.move.line:0 |
100 | #: field:wizard.account.invoice.line,move_lines:0 |
101 | #: field:product.asset,move_line_id:0 |
102 | +#: field:product.asset.import.entries.lines,move_line_id:0 |
103 | msgid "Journal Item" |
104 | msgstr "Ligne d'écriture comptable" |
105 | |
106 | @@ -39127,6 +39136,7 @@ |
107 | #: field:sale.report,year:0 |
108 | #: view:report.stock.move:0 |
109 | #: field:report.stock.move,year:0 |
110 | +#: field:product.asset.import.entries.lines,year:0 |
111 | msgid "Year" |
112 | msgstr "Année" |
113 | |
114 | @@ -39271,6 +39281,7 @@ |
115 | #: field:sync.client.log_sale_purchase,model_id:0 |
116 | #: view:account.model:0 |
117 | #: field:signature,signature_res_model:0 |
118 | +#: field:product.asset.import.entries.lines,model:0 |
119 | msgid "Model" |
120 | msgstr "Modèle" |
121 | |
122 | @@ -39703,6 +39714,7 @@ |
123 | #: report:product.asset:0 |
124 | #: field:product.asset,serial_nb:0 |
125 | #: field:product.asset.event,serial_nb:0 |
126 | +#: field:product.asset.import.entries.lines,serial_nb:0 |
127 | msgid "Serial Number" |
128 | msgstr "Numéro de Série" |
129 | |
130 | @@ -41160,6 +41172,7 @@ |
131 | #: report:product.asset:0 |
132 | #: field:product.asset,brand:0 |
133 | #: field:product.asset.event,brand:0 |
134 | +#: field:product.asset.import.entries.lines,brand:0 |
135 | msgid "Brand" |
136 | msgstr "Marque" |
137 | |
138 | @@ -41995,7 +42008,7 @@ |
139 | msgid "Contract code/name:" |
140 | msgstr "Contrat - Code/Nom:" |
141 | |
142 | -#. modules: sales_followup, register_accounting, import_data, sync_client, base, purchase_followup, msf_doc_import, stock, product, account, account_hq_entries |
143 | +#. modules: sales_followup, register_accounting, import_data, sync_client, base, purchase_followup, msf_doc_import, stock, product, account, account_hq_entries, product_asset |
144 | #: view:base.module.update:0 |
145 | #: view:base.update.translations:0 |
146 | #: selection:import_data,import_mode:0 |
147 | @@ -42026,6 +42039,7 @@ |
148 | #: view:hq.entries.import:0 |
149 | #: view:account.cv.import:0 |
150 | #: view:esc.line.import:0 |
151 | +#: view:product.asset.import.entries:0 |
152 | msgid "Update" |
153 | msgstr "Mettre à jour" |
154 | |
155 | @@ -43460,6 +43474,7 @@ |
156 | #: field:unidata.project,msl_product_ids:0 |
157 | #: field:replenishment.product.list,l_default_code:0 |
158 | #: field:unifield.instance,msl_product_ids:0 |
159 | +#: field:product.asset.import.entries.lines,prod_int_code:0 |
160 | #, python-format |
161 | msgid "Product Code" |
162 | msgstr "Code Produit" |
163 | @@ -45042,7 +45057,7 @@ |
164 | msgid "Output Out" |
165 | msgstr "Modèles de Taxe" |
166 | |
167 | -#. modules: stock_forecast, register_accounting, msf_outgoing, documents_done, unifield_setup, account_override, purchase_compare_rfq, base, stock, msf_profile, msf_doc_import, sale, account_hq_entries, res_currency_tables, account |
168 | +#. modules: stock_forecast, register_accounting, msf_outgoing, documents_done, unifield_setup, account_override, purchase_compare_rfq, base, stock, msf_profile, msf_doc_import, sale, account_hq_entries, res_currency_tables, account, product_asset |
169 | #: field:wizard.split.invoice.lines,wizard_id:0 |
170 | #: view:ir.actions.wizard:0 |
171 | #: field:wizard.ir.model.menu.create.line,wizard_id:0 |
172 | @@ -45076,6 +45091,8 @@ |
173 | #: field:wizard.hard.posting.line,wizard_id:0 |
174 | #: field:wizard.ignore.posting.line,wizard_id:0 |
175 | #: field:wizard.temp.posting.line,wizard_id:0 |
176 | +#: field:product.asset.import.entries.errors,wizard_id:0 |
177 | +#: field:product.asset.import.entries.lines,wizard_id:0 |
178 | msgid "Wizard" |
179 | msgstr "Assistant" |
180 | |
181 | @@ -68707,7 +68724,7 @@ |
182 | msgid "Kit Composition" |
183 | msgstr "Kit - Composition" |
184 | |
185 | -#. modules: register_accounting, msf_homere_interface, account_override, base, msf_doc_import, msf_profile, sync_client, msf_supply_doc_export, account |
186 | +#. modules: register_accounting, msf_homere_interface, account_override, base, msf_doc_import, msf_profile, sync_client, msf_supply_doc_export, account, product_asset |
187 | #: view:ir.attachment:0 |
188 | #: view:ir.attachment:0 |
189 | #: selection:msf.doc.import.accounting,state:0 |
190 | @@ -68722,6 +68739,7 @@ |
191 | #: code:addons/msf_supply_doc_export/msf_supply_doc_export.py:896 |
192 | #: selection:account.invoice.import,state:0 |
193 | #: selection:account.cv.import,state:0 |
194 | +#: selection:product.asset.import.entries,state:0 |
195 | msgid "Created" |
196 | msgstr "Créé" |
197 | |
198 | @@ -72414,7 +72432,7 @@ |
199 | msgid "Expected Pack Date" |
200 | msgstr "Date Prévue de Colisage" |
201 | |
202 | -#. modules: tender_flow, analytic_distribution_supply, product_nomenclature, financing_contract, msf_tools, account_hq_entries, export_import_lang, account_override, procurement_cycle, account_journal, register_accounting, mission_stock, return_claim, sync_client, account_mcdb, res_currency_tables, supplier_catalogue, stock_schedule, procurement_request, spreadsheet_xml, unifield_setup, purchase_compare_rfq, stock_batch_recall, purchase_followup, stock_override, msf_doc_import, analytic_distribution, msf_order_date, msf_cross_docking, reason_types_moves, purchase_allocation_report, finance, msf_homere_interface, msf_instance, account_reconciliation, service_purchasing, consumption_calculation, purchase_override, specific_rules, kit, base, account_subscription, res_currency_functional, msf_budget, account_corrections, account, msf_outgoing, stock_move_tracking, msf_partner, product_attributes, order_nomenclature, documents_done, sale, msf_config_locations, sales_followup, sourcing, msf_custom_settings, product_list, object_query, stock, msf_profile, product, msf_supply_doc_export, purchase |
203 | +#. modules: tender_flow, analytic_distribution_supply, product_nomenclature, financing_contract, msf_tools, account_hq_entries, export_import_lang, account_override, procurement_cycle, account_journal, register_accounting, mission_stock, return_claim, sync_client, account_mcdb, res_currency_tables, supplier_catalogue, stock_schedule, procurement_request, spreadsheet_xml, unifield_setup, purchase_compare_rfq, stock_batch_recall, purchase_followup, stock_override, msf_doc_import, analytic_distribution, msf_order_date, msf_cross_docking, reason_types_moves, purchase_allocation_report, finance, msf_homere_interface, msf_instance, account_reconciliation, service_purchasing, consumption_calculation, purchase_override, specific_rules, kit, base, account_subscription, res_currency_functional, msf_budget, account_corrections, account, msf_outgoing, stock_move_tracking, msf_partner, product_attributes, order_nomenclature, documents_done, sale, msf_config_locations, sales_followup, sourcing, msf_custom_settings, product_list, object_query, stock, msf_profile, product, msf_supply_doc_export, purchase, product_asset |
204 | #: code:addons/account/account.py:294 |
205 | #: code:addons/account/account.py:988 |
206 | #: code:addons/account/account.py:992 |
207 | @@ -73589,6 +73607,7 @@ |
208 | #: selection:unidata.sync,last_msl_execution_status:0 |
209 | #: field:unidata.sync.log,error:0 |
210 | #: selection:unidata.sync.log,state:0 |
211 | +#: selection:product.asset.import.entries,state:0 |
212 | #, python-format, python-format |
213 | msgid "Error" |
214 | msgstr "Erreur" |
215 | @@ -74026,7 +74045,7 @@ |
216 | msgid "Do you want to update the Date of Stock Take of all/selected draft Order lines ?" |
217 | msgstr "Voulez-vous mettre à jour la Date de Prise de Stock sur toutes les lignes brouillon de la Commande ou les lignes brouillon sélectionnées ?" |
218 | |
219 | -#. modules: register_accounting, msf_homere_interface, documents_done, consumption_calculation, msf_button_access_rights, mission_stock, msf_doc_import, analytic_distribution, sourcing, sale, account, account_hq_entries |
220 | +#. modules: register_accounting, msf_homere_interface, documents_done, consumption_calculation, msf_button_access_rights, mission_stock, msf_doc_import, analytic_distribution, sourcing, sale, account, account_hq_entries, product_asset |
221 | #: field:mass.reallocation.verification.wizard,error_ids:0 |
222 | #: field:monthly.review.consumption.line,text_error:0 |
223 | #: field:real.average.consumption.line,text_error:0 |
224 | @@ -74047,6 +74066,7 @@ |
225 | #: field:hq.entries.import,nberrors:0 |
226 | #: field:account.cv.import,error_ids:0 |
227 | #: field:esc.line.import,nberrors:0 |
228 | +#: field:product.asset.import.entries,error_ids:0 |
229 | #, python-format |
230 | msgid "Errors" |
231 | msgstr "Erreurs" |
232 | @@ -81079,7 +81099,7 @@ |
233 | msgid "Wizard lines for internal picking processor" |
234 | msgstr "Wizard lines for internal picking processor" |
235 | |
236 | -#. modules: vertical_integration, register_accounting, res_currency_tables, account_hq_entries, update_client, msf_tools, msf_doc_import, analytic_distribution, account, procurement_cycle |
237 | +#. modules: vertical_integration, register_accounting, res_currency_tables, account_hq_entries, update_client, msf_tools, msf_doc_import, analytic_distribution, account, procurement_cycle, product_asset |
238 | #: view:hq.entries.import:0 |
239 | #: view:import.commitment.wizard:0 |
240 | #: view:msf.doc.import.accounting:0 |
241 | @@ -81099,6 +81119,7 @@ |
242 | #: view:account.cv.import:0 |
243 | #: view:esc.line.import:0 |
244 | #: field:esc.line.import.rejected,wiz_id:0 |
245 | +#: view:product.asset.import.entries:0 |
246 | msgid "Import" |
247 | msgstr "Importer" |
248 | |
249 | @@ -81809,6 +81830,7 @@ |
250 | #: report:delivery.order:0 |
251 | #: field:stock.move,ship_influenced_state:0 |
252 | #: field:product.asset,state:0 |
253 | +#: field:product.asset.import.entries,state:0 |
254 | #, python-format |
255 | msgid "State" |
256 | msgstr "Statut" |
257 | @@ -82985,7 +83007,7 @@ |
258 | msgid "Computation" |
259 | msgstr "Calcul" |
260 | |
261 | -#. modules: register_accounting, msf_homere_interface, import_data, account_hq_entries, export_import_lang, base, msf_doc_import, mission_stock, analytic_distribution, account |
262 | +#. modules: register_accounting, msf_homere_interface, import_data, account_hq_entries, export_import_lang, base, msf_doc_import, mission_stock, analytic_distribution, account, product_asset |
263 | #: field:int.commitment.export.wizard,data:0 |
264 | #: field:import_category,file:0 |
265 | #: field:import_nomenclature,file:0 |
266 | @@ -83006,6 +83028,7 @@ |
267 | #: field:account.invoice.import,file:0 |
268 | #: field:account.cv.import,file:0 |
269 | #: field:esc.line.import,file:0 |
270 | +#: field:product.asset.import.entries,file:0 |
271 | msgid "File" |
272 | msgstr "Fichier" |
273 | |
274 | @@ -83663,7 +83686,7 @@ |
275 | msgid "Sourced-n line" |
276 | msgstr "Ligne sourcée-n" |
277 | |
278 | -#. modules: analytic_distribution, sales_followup, register_accounting, reason_types_moves, msf_homere_interface, stock_override, consumption_calculation, sale, specific_rules, order_types, msf_tools, mission_stock, msf_doc_import, stock, product, acccount, msf_supply_doc_export, account |
279 | +#. modules: analytic_distribution, sales_followup, register_accounting, reason_types_moves, msf_homere_interface, stock_override, consumption_calculation, sale, specific_rules, order_types, msf_tools, mission_stock, msf_doc_import, stock, product, acccount, msf_supply_doc_export, account, product_asset |
280 | #: field:import.commitment.wizard,in_progress:0 |
281 | #: view:product.history.consumption:0 |
282 | #: selection:product.history.consumption,fake_status:0 |
283 | @@ -83713,6 +83736,7 @@ |
284 | #: selection:wizard.import.ad.line,state:0 |
285 | #: selection:supplier.performance.wizard,state:0 |
286 | #: selection:account.cv.import,state:0 |
287 | +#: selection:product.asset.import.entries,state:0 |
288 | #, python-format |
289 | msgid "In Progress" |
290 | msgstr "En cours" |
291 | @@ -96645,6 +96669,7 @@ |
292 | #: selection:product.asset.event,asset_state:0 |
293 | #: view:product.asset.generate.entries:0 |
294 | #: view:journal.change.account:0 |
295 | +#: view:product.asset.import.entries:0 |
296 | #, python-format |
297 | msgid "Cancel" |
298 | msgstr "Annuler" |
299 | @@ -120983,6 +121008,7 @@ |
300 | #: field:product.asset,asset_bs_depreciation_account_id:0 |
301 | #: field:product.asset.line,asset_bs_depreciation_account_id:0 |
302 | #: field:product.category,asset_bs_depreciation_account_id:0 |
303 | +#: field:product.asset.import.entries.lines,asset_bs_depreciation_account_id:0 |
304 | msgid "Asset B/S Depreciation Account" |
305 | msgstr "Compte de bilan des amortissements" |
306 | |
307 | @@ -121028,6 +121054,7 @@ |
308 | #. module: product_asset |
309 | #: field:product.asset,asset_pl_account_id:0 |
310 | #: field:product.asset.line,asset_pl_account_id:0 |
311 | +#: field:product.asset.import.entries.lines,asset_pl_account_id:0 |
312 | msgid "Asset P&L Depreciation Account" |
313 | msgstr "Compte de résultat des amortissements" |
314 | |
315 | @@ -121237,6 +121264,7 @@ |
316 | |
317 | #. module: product_asset |
318 | #: field:product.asset,useful_life_id:0 |
319 | +#: field:product.asset.import.entries.lines,useful_life_id:0 |
320 | msgid "Useful Life" |
321 | msgstr "Durée Amortissement" |
322 | |
323 | @@ -121806,6 +121834,7 @@ |
324 | #, python-format |
325 | msgid "This action can only be done on a Picking" |
326 | msgstr "Cette action peut uniquement être faite sur un Picking" |
327 | +<<<<<<< TREE |
328 | |
329 | #. modules: purchase, sale |
330 | #: code:addons/purchase/purchase_workflow.py:107 |
331 | @@ -122096,3 +122125,175 @@ |
332 | msgid "No valid catalogue" |
333 | msgstr "Aucun catalogue valide" |
334 | |
335 | +======= |
336 | + |
337 | +#. module: product_asset |
338 | +#: field:product.asset,external_asset_id:0 |
339 | +#: field:product.asset.import.entries.lines,external_asset_id:0 |
340 | +msgid "External Asset ID" |
341 | +msgstr "Immobilisation - ID Externe" |
342 | + |
343 | +#. module: product_asset |
344 | +#: model:ir.model,name:product_asset.model_product_asset_import_entries_errors |
345 | +msgid "Asset Entries Import - Error List" |
346 | +msgstr "Import d'immobilisations - Liste des erreurs" |
347 | + |
348 | +#. module: product_asset |
349 | +#: code:addons/product_asset/product_asset.py:1462 |
350 | +#, python-format |
351 | +msgid "Checking file..." |
352 | +msgstr "Vérification du fichier..." |
353 | + |
354 | +#. module: product_asset |
355 | +#: code:addons/product_asset/product_asset.py:1417 |
356 | +#, python-format |
357 | +msgid "Cleaning up old imports..." |
358 | +msgstr "Nettoyage des anciens imports..." |
359 | + |
360 | +#. module: product_asset |
361 | +#: code:addons/product_asset/product_asset.py:1427 |
362 | +#, python-format |
363 | +msgid "Copying file..." |
364 | +msgstr "Copie du fichier..." |
365 | + |
366 | +#. module: product_asset |
367 | +#: model:ir.actions.act_window,name:product_asset.action_product_asset_import_entries |
368 | +#: model:ir.model,name:product_asset.model_product_asset_import_entries |
369 | +#: model:ir.ui.menu,name:product_asset.menu_product_asset_import_entries |
370 | +#: view:product.asset.import.entries:0 |
371 | +msgid "Import Asset Entries" |
372 | +msgstr "Import d'immobilisations" |
373 | + |
374 | +#. module: product_asset |
375 | +#: code:addons/product_asset/product_asset.py:1404 |
376 | +#, python-format |
377 | +msgid "Initialization..." |
378 | +msgstr "Initialisation..." |
379 | + |
380 | +#. module: product_asset |
381 | +#: code:addons/product_asset/product_asset.py:1605 |
382 | +#, python-format |
383 | +msgid "Line %s: A problem occurred for line registration. Please contact an Administrator." |
384 | +msgstr "Ligne %s: Un problème est survenu lors de l'enregistrement de la ligne. Veuillez contacter un administrateur." |
385 | + |
386 | +#. module: product_asset |
387 | +#: code:addons/product_asset/product_asset.py:1564 |
388 | +#, python-format |
389 | +msgid "Line %s: Asset B/S Depreciation Account \"%s\" must have \"Regular\" as Internal Type and \"Asset\" as Account Type" |
390 | +msgstr "Ligne %s: Le compte de bilan des amortissements \"%s\" doit avoir \"Normal\" comme type interne et \"Immobilisation\" comme type de compte" |
391 | + |
392 | +#. module: product_asset |
393 | +#: code:addons/product_asset/product_asset.py:1560 |
394 | +#, python-format |
395 | +msgid "Line %s: Asset B/S Depreciation Account \"%s\" not found!" |
396 | +msgstr "Ligne %s: Le compte de bilan des amortissements \"%s\" n'a pas été trouvé!" |
397 | + |
398 | +#. module: product_asset |
399 | +#: code:addons/product_asset/product_asset.py:1581 |
400 | +#, python-format |
401 | +msgid "Line %s: Asset P&L Depreciation Account \"%s\" must have \"Expense\" or \"Income\" as Account Type" |
402 | +msgstr "Ligne %s: Le compte de résultat des amortissements \"%s\" doit avoir \"Dépenses\" ou \"Recettes\" comme type de compte" |
403 | + |
404 | +#. module: product_asset |
405 | +#: code:addons/product_asset/product_asset.py:1575 |
406 | +#, python-format |
407 | +msgid "Line %s: Asset P&L Depreciation Account \"%s\" not found!" |
408 | +msgstr "Ligne %s: Le compte de résultat des amortissements \"%s\" n'a pas été trouvé!" |
409 | + |
410 | +#. module: product_asset |
411 | +#: code:addons/product_asset/product_asset.py:1507 |
412 | +#, python-format |
413 | +msgid "Line %s: Asset Type \"%s\" not found!" |
414 | +msgstr "Ligne %s: Le type d'immobilisation \"%s\" n'a pas été trouvé!" |
415 | + |
416 | +#. module: product_asset |
417 | +#: code:addons/product_asset/product_asset.py:1535 |
418 | +#, python-format |
419 | +msgid "Line %s: Journal Item \"%s\" not found!\n" |
420 | +"Please check if that JI exists or has the product specified" |
421 | +msgstr "Ligne %s: La ligne d'écriture comptable \"%s\" n'a pas été trouvé!\n" |
422 | +"Veuillez vérifiez si cette ligne d'écriture existe ou si elle contient le produit spécifié" |
423 | + |
424 | +#. module: product_asset |
425 | +#: code:addons/product_asset/product_asset.py:1501 |
426 | +#, python-format |
427 | +msgid "Line %s: No Asset Type specified! (External Asset ID: %s, Serial Number: %s)" |
428 | +msgstr "Ligne %s: Pas de type d'immobilisation spécifié! (Immobilisation - ID Externe: %s, Numéro de série: %s)" |
429 | + |
430 | +#. module: product_asset |
431 | +#: code:addons/product_asset/product_asset.py:1488 |
432 | +#, python-format |
433 | +msgid "Line %s: No Product Code specified! (External Asset ID: %s, Serial Number: %s)" |
434 | +msgstr "Ligne %s: Pas de code produit spécifié! (Immobilisation - ID Externe: %s, Numéro de série: %s)" |
435 | + |
436 | +#. module: product_asset |
437 | +#: code:addons/product_asset/product_asset.py:1515 |
438 | +#, python-format |
439 | +msgid "Line %s: No Useful Life specified! (External Asset ID: %s, Serial Number: %s)" |
440 | +msgstr "Ligne %s: Pas de durée d'amortissement spécifiée! (Immobilisation - ID Externe: %s, Numéro de série: %s)" |
441 | + |
442 | +#. module: product_asset |
443 | +#: code:addons/product_asset/product_asset.py:1494 |
444 | +#, python-format |
445 | +msgid "Line %s: Product Code \"%s\" not found!" |
446 | +msgstr "Ligne %s: Le code produit \"%s\" n'a pas été trouvé!" |
447 | + |
448 | +#. module: product_asset |
449 | +#: code:addons/product_asset/product_asset.py:1521 |
450 | +#, python-format |
451 | +msgid "Line %s: The \"%s\" year(s) Useful Life of Asset Type \"%s\" not found!" |
452 | +msgstr "Ligne %s: La durée d'amortissement \"%s\" an(s) du Type d'Immobilisation \"%s\" n'a pas été trouvé!" |
453 | + |
454 | +#. module: product_asset |
455 | +#: code:addons/product_asset/product_asset.py:1547 |
456 | +#, python-format |
457 | +msgid "Line %s: The Journal Entry \"%s\" has to be in \"posted\" state." |
458 | +msgstr "Ligne %s: L'écriture comptable \"%s\" doit être à l'état \"comptabilisé\"." |
459 | + |
460 | +#. module: product_asset |
461 | +#: code:addons/product_asset/product_asset.py:1550 |
462 | +#, python-format |
463 | +msgid "Line %s: The account type of Journal Item \"%s\" has to be either Asset or Expense." |
464 | +msgstr "Ligne %s: Le type du compte de la ligne d'écriture comptable \"%s\" doit être soit Immobilisations soit Dépenses." |
465 | + |
466 | +#. module: product_asset |
467 | +#: code:addons/product_asset/product_asset.py:1544 |
468 | +#, python-format |
469 | +msgid "Line %s: The debit of Journal Item \"%s\" has to be greater than 0." |
470 | +msgstr "Ligne %s: Le débit de la ligne d'écriture comptable \"%s\" doit être supérieur à 0." |
471 | + |
472 | +#. module: product_asset |
473 | +#: code:addons/product_asset/product_asset.py:1541 |
474 | +#, python-format |
475 | +msgid "Line %s: The journal of Journal Item \"%s\" has to be of type Purchase, Correction HQ, HQ or Intermission!" |
476 | +msgstr "Ligne %s: Le journal de la ligne d'écriture comptable \"%s\" doit être de type Achat, Correction HQ, HQ ou Intermission!" |
477 | + |
478 | +#. module: product_asset |
479 | +#: code:addons/product_asset/product_asset.py:1435 |
480 | +#, python-format |
481 | +msgid "Processing line..." |
482 | +msgstr "Traitement de la ligne..." |
483 | + |
484 | +#. module: product_asset |
485 | +#: code:addons/product_asset/product_asset.py:1439 |
486 | +#, python-format |
487 | +msgid "Reading headers..." |
488 | +msgstr "Lecture des entêtes..." |
489 | + |
490 | +#. module: product_asset |
491 | +#: code:addons/product_asset/product_asset.py:1457 |
492 | +#, python-format |
493 | +msgid "Reading lines..." |
494 | +msgstr "Lecture des lignes..." |
495 | + |
496 | +#. module: product_asset |
497 | +#: view:product.asset.import.entries:0 |
498 | +msgid "This will import Entries from an XML file." |
499 | +msgstr "Ceci va importer les entrées d'immobilisations' depuis un fichier XML." |
500 | + |
501 | +#. module: product_asset |
502 | +#: code:addons/product_asset/product_asset.py:1632 |
503 | +#, python-format |
504 | +msgid "Writing changes..." |
505 | +msgstr "Écriture des modifications..." |
506 | +>>>>>>> MERGE-SOURCE |
507 | |
508 | === modified file 'bin/addons/product_asset/product_asset.py' |
509 | --- bin/addons/product_asset/product_asset.py 2023-11-16 13:03:16 +0000 |
510 | +++ bin/addons/product_asset/product_asset.py 2024-05-10 12:38:34 +0000 |
511 | @@ -6,6 +6,11 @@ |
512 | from tools import misc |
513 | from datetime import datetime |
514 | from dateutil.relativedelta import relativedelta |
515 | +import threading |
516 | +import pooler |
517 | +from tempfile import NamedTemporaryFile |
518 | +from base64 import b64decode |
519 | +from spreadsheet_xml.spreadsheet_xml import SpreadsheetXML |
520 | |
521 | |
522 | #---------------------------------------------------------- |
523 | @@ -187,7 +192,31 @@ |
524 | 'from_sync': False, |
525 | 'event_ids': [], |
526 | 'instance_id': False, |
527 | - 'invoice_id': False |
528 | + 'invoice_id': False, |
529 | + 'move_line_id': False, |
530 | + 'quantity_divisor': False, |
531 | + 'invo_value': False, |
532 | + 'invo_currency': False, |
533 | + 'invo_date': False, |
534 | + 'invo_supplier_id': False, |
535 | + 'invo_donator_code': False, |
536 | + 'invo_certif_depreciation': False, |
537 | + 'serial_nb': False, |
538 | + 'brand': False, |
539 | + 'type': False, |
540 | + 'model': False, |
541 | + 'year': False, |
542 | + 'project_po': False, |
543 | + 'orig_mission_code': False, |
544 | + 'international_po': False, |
545 | + 'arrival_date': False, |
546 | + 'receipt_place': False, |
547 | + 'comment': False, |
548 | + 'line_ids': [], |
549 | + 'depreciation_amount': False, |
550 | + 'disposal_amount': False, |
551 | + 'start_date': False, |
552 | + 'depreciation_method': False, |
553 | }) |
554 | return super(product_asset, self).copy_data(cr, uid, id, default, context=context) |
555 | |
556 | @@ -240,12 +269,12 @@ |
557 | vals['state'] = 'open' |
558 | |
559 | # fetch the product |
560 | - if 'product_id' in vals: |
561 | + if 'product_id' in vals and not context.get('from_import'): |
562 | productId = vals['product_id'] |
563 | # add readonly fields to vals |
564 | vals.update(self._getRelatedProductFields(cr, uid, productId, update_account=not from_sync)) |
565 | |
566 | - if not from_sync and not vals.get('from_invoice') and 'move_line_id' in vals: |
567 | + if not from_sync and not vals.get('from_invoice') and not context.get('from_import') and 'move_line_id' in vals: |
568 | vals.update(self._getRelatedMoveLineFields(cr, uid, vals['move_line_id'], divisor=vals.get('quantity_divisor'), context=context)) |
569 | |
570 | # UF-1617: set the current instance into the new object if it has not been sent from the sync |
571 | @@ -463,6 +492,7 @@ |
572 | 'asset_type_id': fields.many2one('product.asset.type', 'Asset Type'), # from product |
573 | 'description': fields.char('Asset Description', size=128), |
574 | 'product_id': fields.many2one('product.product', 'Product', required=True, ondelete='cascade'), |
575 | + 'external_asset_id': fields.char('External Asset ID', size=32), |
576 | # msf codification |
577 | 'prod_int_code': fields.char('Product Code', size=128, readonly=True), # from product |
578 | 'prod_int_name': fields.char('Product Description', size=128, readonly=True), # from product |
579 | @@ -484,13 +514,13 @@ |
580 | 'arrival_date': fields.date('Arrival Date'), # required=True), |
581 | 'receipt_place': fields.char('Receipt Place', size=128), # required=True), |
582 | # Invoice |
583 | - 'invo_date': fields.date('Invoice Date', required=True, readonly=1), |
584 | - 'invo_value': fields.float('Value', required=True, readonly=1), |
585 | + 'invo_date': fields.date('Invoice Date', readonly=1), |
586 | + 'invo_value': fields.float('Value', readonly=1), |
587 | 'invoice_id': fields.many2one('account.invoice', 'Invoice'), |
588 | - 'move_line_id': fields.many2one('account.move.line', 'Journal Item', domain="['&', '&', '&', ('journal_id.type', 'in', ['purchase', 'correction_hq', 'hq', 'intermission']), ('debit', '>', 0), ('move_id.state', '=', 'posted'), ('account_id.user_type_code', 'in', ['asset', 'expense'])]", required=1), |
589 | + 'move_line_id': fields.many2one('account.move.line', 'Journal Item', domain="['&', '&', '&', ('journal_id.type', 'in', ['purchase', 'correction_hq', 'hq', 'intermission']), ('debit', '>', 0), ('move_id.state', '=', 'posted'), ('account_id.user_type_code', 'in', ['asset', 'expense'])]"), |
590 | 'quantity_divisor': fields.integer_null('Divisor Quantity', help='This quantity will divide the total invoice value.'), |
591 | 'invoice_line_id': fields.many2one('account.invoice.line', 'Invoice Line'), |
592 | - 'invo_currency': fields.many2one('res.currency', 'Currency', required=True, readonly=1), |
593 | + 'invo_currency': fields.many2one('res.currency', 'Currency', readonly=1), |
594 | 'invo_supplier_id': fields.many2one('res.partner', 'Supplier', readonly=1), |
595 | 'invo_donator_code': fields.char('Donator Code', size=128), |
596 | 'invo_certif_depreciation': fields.char('Certificate of Depreciation', size=128), |
597 | @@ -505,7 +535,7 @@ |
598 | 'asset_bs_depreciation_account_id': fields.many2one('account.account', 'Asset B/S Depreciation Account', domain=[('type', '=', 'other'), ('user_type_code', '=', 'asset')]), |
599 | 'asset_pl_account_id': fields.many2one('account.account', 'Asset P&L Depreciation Account', domain=[('user_type_code', 'in', ['expense', 'income'])]), |
600 | 'useful_life_id': fields.many2one('product.asset.useful.life', 'Useful Life', ondelete='restrict'), |
601 | - 'start_date': fields.date('Start Date', required=1), |
602 | + 'start_date': fields.date('Start Date'), |
603 | 'line_ids': fields.one2many('product.asset.line', 'asset_id', 'Depreciation Lines'), |
604 | 'analytic_distribution_id': fields.many2one('analytic.distribution', 'Analytic Distribution'), |
605 | 'depreciation_amount': fields.function(_get_book_value, string='Depreciation', type='float', method=True, help="Sum of all Asset journal item lines", multi='get_book', with_null=True), |
606 | @@ -516,7 +546,7 @@ |
607 | 'can_be_disposed': fields.function(_get_can_be_disposed, string='Can be diposed', type='boolean', method=True), |
608 | 'instance_level': fields.function(_get_instance_level, string='Instance Level', type='char', method=True), |
609 | 'prorata': fields.boolean('Prorata Temporis'), |
610 | - 'depreciation_method': fields.selection([('straight', 'Straight Line')], 'Depreciation Method', required=True), |
611 | + 'depreciation_method': fields.selection([('straight', 'Straight Line')], 'Depreciation Method'), |
612 | 'period_id': fields.function(misc.get_fake, fnct_search=_search_period_id, method=True, type='many2one', relation='account.period', string='Start Period', domain=[('special', '=', False)]), |
613 | } |
614 | |
615 | @@ -1354,6 +1384,374 @@ |
616 | |
617 | product_asset_generate_entries() |
618 | |
619 | + |
620 | +class product_asset_import_entries(osv.osv_memory): |
621 | + _name = 'product.asset.import.entries' |
622 | + _description = 'Import Asset Entries' |
623 | + _columns = { |
624 | + 'file': fields.binary(string="File", filters='*.xml, *.xls', required=True), |
625 | + 'filename': fields.char(string="Imported filename", size=256), |
626 | + 'progression': fields.float(string="Progression", readonly=True), |
627 | + 'message': fields.char(string="Message", size=256, readonly=True), |
628 | + 'state': fields.selection( |
629 | + [('draft', 'Created'), ('inprogress', 'In Progress'), ('error', 'Error'), ('done', 'Done')], string="State", |
630 | + readonly=True, required=True), |
631 | + 'error_ids': fields.one2many('product.asset.import.entries.errors', 'wizard_id', "Errors", readonly=True), |
632 | + } |
633 | + _defaults = { |
634 | + 'progression': lambda *a: 0.0, |
635 | + 'state': lambda *a: 'draft', |
636 | + 'message': lambda *a: _('Initialization...'), |
637 | + } |
638 | + |
639 | + def _import(self, dbname, uid, ids, context=None): |
640 | + if context is None: |
641 | + context = {} |
642 | + cr = pooler.get_db(dbname).cursor() |
643 | + created = 0 |
644 | + processed = 0 |
645 | + errors = [] |
646 | + current_line_num = None |
647 | + acc_cache = {} |
648 | + prod_cache = {} |
649 | + asset_type_cache = {} |
650 | + use_life_cache = {} |
651 | + try: |
652 | + # Update wizard |
653 | + self.write(cr, uid, ids, {'message': _('Cleaning up old imports...'), 'progression': 1.00}) |
654 | + # Clean up old temporary imported lines |
655 | + old_lines_ids = self.pool.get('product.asset.import.entries.lines').search(cr, uid, []) |
656 | + self.pool.get('product.asset.import.entries.lines').unlink(cr, uid, old_lines_ids) |
657 | + |
658 | + for wiz in self.browse(cr, uid, ids): |
659 | + # Check that a file was given |
660 | + if not wiz.file: |
661 | + raise osv.except_osv(_('Error'), _('Nothing to import.')) |
662 | + # Update wizard |
663 | + self.write(cr, uid, [wiz.id], {'message': _('Copying file...'), 'progression': 2.00}) |
664 | + fileobj = NamedTemporaryFile('w+b', delete=False) |
665 | + fileobj.write(b64decode(wiz.file)) |
666 | + fileobj.close() |
667 | + content = SpreadsheetXML(xmlfile=fileobj.name, context=context) |
668 | + if not content: |
669 | + raise osv.except_osv(_('Warning'), _('No content')) |
670 | + # Update wizard |
671 | + self.write(cr, uid, [wiz.id], {'message': _('Processing line...'), 'progression': 4.00}) |
672 | + rows = content.getRows() |
673 | + nb_rows = len([x for x in content.getRows()]) |
674 | + # Update wizard |
675 | + self.write(cr, uid, [wiz.id], {'message': _('Reading headers...'), 'progression': 5.00}) |
676 | + # Use the first row to find which column to use |
677 | + cols = {} |
678 | + col_names = ['External Asset ID', 'Product Code', 'Asset Type', 'Useful Life', 'Serial Number', 'Brand', |
679 | + 'Type', 'Model', 'Year', 'Journal Item', 'Asset B/S Depreciation Account', |
680 | + 'Asset P&L Depreciation Account'] |
681 | + for num, r in enumerate(rows): |
682 | + header = [x and x.data for x in r.iter_cells()] |
683 | + for el in col_names: |
684 | + if el in header: |
685 | + cols[el] = header.index(el) |
686 | + break |
687 | + # Number of line to bypass in line's count |
688 | + base_num = 2 |
689 | + for el in col_names: |
690 | + if el not in cols: |
691 | + raise osv.except_osv(_('Error'), _("'%s' column not found in file.") % (el or '',)) |
692 | + # Update wizard |
693 | + self.write(cr, uid, [wiz.id], {'message': _('Reading lines...'), 'progression': 6.00}) |
694 | + # Check file's content |
695 | + for num, r in enumerate(rows): |
696 | + # Update wizard |
697 | + progression = ((float(num + 1) * 94) / float(nb_rows)) + 6 |
698 | + self.write(cr, uid, [wiz.id], {'message': _('Checking file...'), 'progression': progression}) |
699 | + # Prepare some values |
700 | + r_prod = False |
701 | + r_asset_type = False |
702 | + r_use_life = False |
703 | + r_ji = False |
704 | + r_bs_acc = False |
705 | + r_pl_acc = False |
706 | + |
707 | + current_line_num = num + base_num |
708 | + # Fetch all XML row values |
709 | + line = self.pool.get('import.cell.data').get_line_values(cr, uid, ids, r, context=context) |
710 | + |
711 | + # ignore empty lines |
712 | + if not self.pool.get('msf.doc.import.accounting')._check_has_data(line): |
713 | + continue |
714 | + |
715 | + # Check line length and fill the cropped empty/missing cells at end of line with False |
716 | + if len(line) < len(col_names): |
717 | + line.extend([False] * (len(col_names) - len(line))) |
718 | + |
719 | + line = self.pool.get('msf.doc.import.accounting')._format_special_char(line) |
720 | + |
721 | + # Check Product Code |
722 | + if not line[cols['Product Code']]: |
723 | + errors.append( |
724 | + _('Line %s: No Product Code specified! (External Asset ID: %s, Serial Number: %s)') % |
725 | + (current_line_num, line[cols['External Asset ID']] or '_', line[cols['Serial Number']] or '_')) |
726 | + else: |
727 | + if not prod_cache.get(line[cols['Product Code']], False): |
728 | + product_ids = self.pool.get('product.product').search(cr, uid, [('default_code', '=', line[cols['Product Code']])]) |
729 | + if product_ids: |
730 | + prod_cache[line[cols['Product Code']]] = product_ids[0] |
731 | + else: |
732 | + errors.append(_('Line %s: Product Code "%s" not found!') % (current_line_num, line[cols['Product Code']],)) |
733 | + r_prod = prod_cache.get(line[cols['Product Code']], False) |
734 | + |
735 | + # Check Asset Type |
736 | + if not line[cols['Asset Type']]: |
737 | + errors.append( |
738 | + _('Line %s: No Asset Type specified! (External Asset ID: %s, Serial Number: %s)') % |
739 | + (current_line_num, line[cols['External Asset ID']] or '_', line[cols['Serial Number']] or '_')) |
740 | + else: |
741 | + if not asset_type_cache.get(line[cols['Asset Type']], False): |
742 | + asset_type_ids = self.pool.get('product.asset.type').search(cr, uid, [('name', '=', line[cols['Asset Type']])]) |
743 | + if asset_type_ids: |
744 | + asset_type_cache[line[cols['Asset Type']]] = asset_type_ids[0] |
745 | + else: |
746 | + errors.append(_('Line %s: Asset Type "%s" not found!') % (current_line_num, line[cols['Asset Type']],)) |
747 | + r_asset_type = asset_type_cache.get(line[cols['Asset Type']], False) |
748 | + |
749 | + # Check Useful Life |
750 | + if not line[cols['Useful Life']]: |
751 | + errors.append( |
752 | + _('Line %s: No Useful Life specified! (External Asset ID: %s, Serial Number: %s)') % |
753 | + (current_line_num, line[cols['External Asset ID']] or '_', line[cols['Serial Number']] or '_')) |
754 | + elif line[cols['Useful Life']] and r_asset_type: |
755 | + if not use_life_cache.get((line[cols['Useful Life']], r_asset_type), False): |
756 | + use_life_ids = self.pool.get('product.asset.useful.life').search(cr, uid, [('asset_type_id', '=', r_asset_type), ('year', '=', line[cols['Useful Life']])]) |
757 | + if use_life_ids: |
758 | + use_life_cache[(line[cols['Useful Life']], r_asset_type)] = use_life_ids[0] |
759 | + else: |
760 | + errors.append( |
761 | + _('Line %s: The "%s" year(s) Useful Life of Asset Type "%s" not found!') % |
762 | + (current_line_num, line[cols['Useful Life']], line[cols['Asset Type']],)) |
763 | + r_use_life = use_life_cache.get((line[cols['Useful Life']], r_asset_type), False) |
764 | + |
765 | + # Check Journal Item |
766 | + move_ids = False |
767 | + aml_ids = False |
768 | + if line[cols['Journal Item']]: |
769 | + move_ids = self.pool.get('account.move').search(cr, uid, [('name', '=', line[cols['Journal Item']])]) |
770 | + if move_ids and move_ids[0]: |
771 | + if r_prod: |
772 | + product = self.pool.get('product.product').browse(cr, uid, r_prod, context=context) |
773 | + aml_ids = self.pool.get('account.move.line').search(cr, uid, [('move_id', '=', move_ids[0]), ('product_id', '=', product.id)]) |
774 | + if not move_ids or not aml_ids: |
775 | + errors.append(_('Line %s: Journal Item "%s" not found!\nPlease check if that JI exists or has the product specified') % (current_line_num, line[cols['Journal Item']],)) |
776 | + elif aml_ids: |
777 | + ji_error = False |
778 | + # Apply the same restrictions as in the asset form view |
779 | + aml = self.pool.get('account.move.line').browse(cr, uid, aml_ids[0], context=context) |
780 | + if aml.journal_id.type not in ['purchase', 'correction_hq', 'hq', 'intermission']: |
781 | + errors.append(_('Line %s: The journal of Journal Item "%s" has to be of type Purchase, Correction HQ, HQ or Intermission!') % (current_line_num, line[cols['Journal Item']],)) |
782 | + ji_error = True |
783 | + if not (aml.debit > 0): |
784 | + errors.append(_('Line %s: The debit of Journal Item "%s" has to be greater than 0.') % (current_line_num, line[cols['Journal Item']],)) |
785 | + ji_error = True |
786 | + if aml.move_id.state != 'posted': |
787 | + errors.append(_('Line %s: The Journal Entry "%s" has to be in "posted" state.') % (current_line_num, line[cols['Journal Item']],)) |
788 | + ji_error = True |
789 | + if aml.account_id.user_type_code not in ['asset', 'expense']: |
790 | + errors.append(_('Line %s: The account type of Journal Item "%s" has to be either Asset or Expense.') % (current_line_num, line[cols['Journal Item']],)) |
791 | + ji_error = True |
792 | + if not ji_error: |
793 | + r_ji = aml_ids[0] |
794 | + |
795 | + # Check Asset B/S Depreciation Account |
796 | + bs_ids = False |
797 | + if line[cols['Asset B/S Depreciation Account']]: |
798 | + if not acc_cache.get((line[cols['Asset B/S Depreciation Account']], 'bs'), False): |
799 | + bs_ids = self.pool.get('account.account').search(cr, uid, [('code', '=', line[cols['Asset B/S Depreciation Account']])]) |
800 | + if not bs_ids: |
801 | + errors.append(_('Line %s: Asset B/S Depreciation Account "%s" not found!') % (current_line_num, line[cols['Asset B/S Depreciation Account']],)) |
802 | + else: |
803 | + bs_account = self.pool.get('account.account').browse(cr, uid, bs_ids[0], context=context) |
804 | + if bs_account.type != 'other' or bs_account.user_type_code != 'asset': |
805 | + errors.append(_('Line %s: Asset B/S Depreciation Account "%s" must have "Regular" as Internal Type and "Asset" as Account Type') % |
806 | + (current_line_num, line[cols['Asset B/S Depreciation Account']],)) |
807 | + else: |
808 | + acc_cache[(line[cols['Asset B/S Depreciation Account']], 'bs')] = bs_ids[0] |
809 | + else: |
810 | + r_bs_acc = acc_cache.get((line[cols['Asset B/S Depreciation Account']], 'bs'), False) |
811 | + |
812 | + # Check Asset P&L Depreciation Account |
813 | + pl_ids = False |
814 | + if line[cols['Asset P&L Depreciation Account']]: |
815 | + if not acc_cache.get((line[cols['Asset P&L Depreciation Account']], 'pl'), False): |
816 | + pl_ids = self.pool.get('account.account').search(cr, uid, [('code', '=', line[cols['Asset P&L Depreciation Account']])]) |
817 | + if not pl_ids: |
818 | + errors.append(_('Line %s: Asset P&L Depreciation Account "%s" not found!') % |
819 | + (current_line_num, line[cols['Asset P&L Depreciation Account']],)) |
820 | + else: |
821 | + pl_account = self.pool.get('account.account').browse(cr, uid, pl_ids[0], context=context) |
822 | + if pl_account.user_type_code not in ['expense', 'income']: |
823 | + errors.append( |
824 | + _('Line %s: Asset P&L Depreciation Account "%s" must have "Expense" or "Income" as Account Type') % |
825 | + (current_line_num, line[cols['Asset P&L Depreciation Account']],)) |
826 | + else: |
827 | + acc_cache[(line[cols['Asset P&L Depreciation Account']], 'pl')] = pl_ids[0] |
828 | + else: |
829 | + r_pl_acc = acc_cache.get((line[cols['Asset P&L Depreciation Account']], 'pl'), False) |
830 | + |
831 | + vals = { |
832 | + 'external_asset_id': line[cols['External Asset ID']] or '', |
833 | + 'prod_int_code': line[cols['Product Code']], |
834 | + 'product_id': r_prod, |
835 | + 'asset_type_id': r_asset_type, |
836 | + 'useful_life_id': r_use_life, |
837 | + 'serial_nb': line[cols['Serial Number']] or '', |
838 | + 'brand': line[cols['Brand']], |
839 | + 'type': line[cols['Type']] or '', |
840 | + 'model': line[cols['Model']] or '', |
841 | + 'year': line[cols['Year']] or '', |
842 | + 'move_line_id': r_ji, |
843 | + 'asset_bs_depreciation_account_id': r_bs_acc, |
844 | + 'asset_pl_account_id': r_pl_acc, |
845 | + 'wizard_id': wiz.id, |
846 | + } |
847 | + |
848 | + if not errors: |
849 | + line_res = self.pool.get('product.asset.import.entries.lines').create(cr, uid, vals, context=context) |
850 | + if not line_res: |
851 | + errors.append(_('Line %s: A problem occurred for line registration. Please contact an Administrator.') % (current_line_num,)) |
852 | + continue |
853 | + created += 1 |
854 | + |
855 | + # Update wizard |
856 | + self.write(cr, uid, ids, |
857 | + {'message': _('Check complete. Reading potential errors or write needed changes.'), |
858 | + 'progression': 100.0}) |
859 | + |
860 | + wiz_state = 'done' |
861 | + # If errors, cancel probable modifications |
862 | + if errors: |
863 | + cr.rollback() |
864 | + created = 0 |
865 | + message = _('Import FAILED.') |
866 | + # Delete old errors |
867 | + error_ids = self.pool.get('product.asset.import.entries.errors').search(cr, uid, [], context) |
868 | + if error_ids: |
869 | + self.pool.get('product.asset.import.entries.errors').unlink(cr, uid, error_ids, context) |
870 | + # create errors lines |
871 | + for e in errors: |
872 | + self.pool.get('product.asset.import.entries.errors').create(cr, uid, |
873 | + {'wizard_id': wiz.id, 'name': e}, |
874 | + context) |
875 | + wiz_state = 'error' |
876 | + else: |
877 | + # Update wizard |
878 | + self.write(cr, uid, ids, {'message': _('Writing changes...'), 'progression': 0.0}) |
879 | + # Create all asset entries |
880 | + import_lines_ids = self.pool.get('product.asset.import.entries.lines').search(cr, uid, [('wizard_id', '=', wiz.id)], context=context) |
881 | + import_lines = self.pool.get('product.asset.import.entries.lines').browse(cr, uid, import_lines_ids, context=context) |
882 | + context.update({'from_import': True}) |
883 | + try: |
884 | + for asset in import_lines: |
885 | + asset_vals = { |
886 | + 'external_asset_id': asset.external_asset_id, |
887 | + 'prod_int_code': asset.prod_int_code, |
888 | + 'product_id': asset.product_id.id, |
889 | + 'asset_type_id': asset.asset_type_id.id, |
890 | + 'useful_life_id': asset.useful_life_id.id, |
891 | + 'serial_nb': asset.serial_nb, |
892 | + 'brand': asset.brand, |
893 | + 'type': asset.type, |
894 | + 'model': asset.model, |
895 | + 'year': asset.year, |
896 | + 'move_line_id': asset.move_line_id.id, |
897 | + 'asset_bs_depreciation_account_id': asset.asset_bs_depreciation_account_id.id, |
898 | + 'asset_pl_account_id': asset.asset_pl_account_id.id, |
899 | + } |
900 | + asset_id = self.pool.get('product.asset').create(cr, uid, asset_vals, context=context) |
901 | + message = _('Import successful.') |
902 | + except osv.except_osv as osv_error: |
903 | + cr.rollback() |
904 | + self.write(cr, uid, ids, |
905 | + {'message': _("An error occurred. %s: %s") % (osv_error.name, osv_error.value,), |
906 | + 'state': 'done', 'progression': 100.0}) |
907 | + cr.close(True) |
908 | + |
909 | + # Update wizard |
910 | + self.write(cr, uid, ids, {'message': message, 'state': wiz_state, 'progression': 100.0}) |
911 | + |
912 | + # Close cursor |
913 | + cr.commit() |
914 | + cr.close(True) |
915 | + |
916 | + except osv.except_osv as osv_error: |
917 | + cr.rollback() |
918 | + self.write(cr, uid, ids, {'message': _("An error occurred. %s: %s") % (osv_error.name, osv_error.value,), 'state': 'done', 'progression': 100.0}) |
919 | + cr.close(True) |
920 | + except Exception as e: |
921 | + cr.rollback() |
922 | + if current_line_num is not None: |
923 | + message = _("An error occurred on line %s: %s") % (current_line_num, e.args and e.args[0] or '') |
924 | + else: |
925 | + message = _("An error occurred: %s") % (e.args and e.args[0] or '',) |
926 | + self.write(cr, uid, ids, {'message': message, 'state': 'done', 'progression': 100.0}) |
927 | + cr.close(True) |
928 | + return True |
929 | + |
930 | + def button_validate(self, cr, uid, ids, context=None): |
931 | + """ |
932 | + Launch process in a thread and return a wizard |
933 | + """ |
934 | + if not context: |
935 | + context = {} |
936 | + thread = threading.Thread(target=self._import, args=(cr.dbname, uid, ids, context)) |
937 | + thread.start() |
938 | + return self.write(cr, uid, ids, {'state': 'inprogress'}, context=context) |
939 | + |
940 | + def button_update(self, cr, uid, ids, context=None): |
941 | + """ |
942 | + Update view |
943 | + """ |
944 | + return False |
945 | + |
946 | + |
947 | +product_asset_import_entries() |
948 | + |
949 | + |
950 | +class product_asset_import_entries_lines(osv.osv): |
951 | + _name = 'product.asset.import.entries.lines' |
952 | + |
953 | + _columns = { |
954 | + 'external_asset_id': fields.char('External Asset ID', size=32, readonly=True), |
955 | + 'prod_int_code': fields.char('Product Code', size=128, readonly=True, required=True), |
956 | + 'product_id': fields.many2one('product.product', 'Product', required=True), |
957 | + 'asset_type_id': fields.many2one('product.asset.type', 'Asset Type', readonly=True, required=True), |
958 | + 'useful_life_id': fields.many2one('product.asset.useful.life', 'Useful Life', ondelete='restrict', readonly=True, required=True), |
959 | + 'serial_nb': fields.char('Serial Number', size=128, readonly=True), |
960 | + 'brand': fields.char('Brand', size=128, readonly=True), |
961 | + 'type': fields.char('Type', size=128, readonly=True), |
962 | + 'model': fields.char('Model', size=128, readonly=True), |
963 | + 'year': fields.char('Year', size=4, readonly=True), |
964 | + 'move_line_id': fields.many2one('account.move.line', 'Journal Item', readonly=True), |
965 | + 'asset_bs_depreciation_account_id': fields.many2one('account.account', 'Asset B/S Depreciation Account', readonly=True), |
966 | + 'asset_pl_account_id': fields.many2one('account.account', 'Asset P&L Depreciation Account', readonly=True), |
967 | + 'wizard_id': fields.integer("Wizard", required=True, readonly=True), |
968 | + } |
969 | + |
970 | + |
971 | +product_asset_import_entries_lines() |
972 | + |
973 | + |
974 | +class product_asset_import_entries_errors(osv.osv_memory): |
975 | + _name = 'product.asset.import.entries.errors' |
976 | + _description = 'Asset Entries Import - Error List' |
977 | + |
978 | + _columns = { |
979 | + 'name': fields.text("Description", readonly=True, required=True), |
980 | + 'wizard_id': fields.many2one('product.asset.import.entries', "Wizard", required=True, readonly=True), |
981 | + } |
982 | + |
983 | + |
984 | +product_asset_import_entries_errors() |
985 | + |
986 | + |
987 | #---------------------------------------------------------- |
988 | # Products |
989 | #---------------------------------------------------------- |
990 | |
991 | === modified file 'bin/addons/product_asset/product_asset_view.xml' |
992 | --- bin/addons/product_asset/product_asset_view.xml 2024-03-13 13:36:47 +0000 |
993 | +++ bin/addons/product_asset/product_asset_view.xml 2024-05-10 12:38:34 +0000 |
994 | @@ -68,7 +68,10 @@ |
995 | <field name="arch" type="xml"> |
996 | <form string="Asset"> |
997 | <field name="name" /> |
998 | - <field name="instance_id" readonly='1'/> |
999 | + <group colspan="2" col="4"> |
1000 | + <field name="external_asset_id" attrs="{'readonly': ['|', ('lock_open', '=', True), ('state', 'not in', ['draft', 'open'])]}"/> |
1001 | + <field name="instance_id" readonly='1'/> |
1002 | + </group> |
1003 | <field name="journal_id" /> |
1004 | <group colspan="2" col="4"> |
1005 | <field name="asset_type_id" on_change="change_asset_type_id(asset_type_id, useful_life_id)" required="1" attrs="{'readonly': ['|', ('state', 'not in', ['draft', 'open']), ('lock_open', '!=', False)]}" /> |
1006 | @@ -112,11 +115,11 @@ |
1007 | |
1008 | <group colspan="2" col="4"> |
1009 | <separator string="Invoice" colspan="4" /> |
1010 | - <field name="move_line_id" colspan="4" attrs="{'readonly': ['|', ('state', '!=', 'draft'), ('from_invoice', '=', True)]}" on_change="change_invo_date(move_line_id, product_id)" /> |
1011 | + <field name="move_line_id" required="1" colspan="4" attrs="{'readonly': ['|', ('state', '!=', 'draft'), ('from_invoice', '=', True)]}" on_change="change_invo_date(move_line_id, product_id)" /> |
1012 | <field name="quantity_divisor" attrs="{'readonly': ['|', ('state', '!=', 'draft'), ('from_invoice', '=', True)]}" on_change="change_quantity_divisor(quantity_divisor, move_line_id)"/> |
1013 | - <field name="invo_value" /> |
1014 | - <field name="invo_currency" /> |
1015 | - <field name="invo_date" /> |
1016 | + <field name="invo_value" required="1"/> |
1017 | + <field name="invo_currency" required="1"/> |
1018 | + <field name="invo_date" required="1"/> |
1019 | <field name="invo_supplier_id" colspan="4" /> |
1020 | <field name="invo_donator_code" colspan="4" attrs="{'readonly': ['|', ('lock_open', '=', True), ('state', 'in', ['cancel', 'done'])]}"/> |
1021 | <field name="invo_certif_depreciation" colspan="4" attrs="{'readonly': ['|', ('lock_open', '=', True), ('state', 'in', ['cancel', 'done'])]}"/> |
1022 | @@ -141,8 +144,8 @@ |
1023 | </group> |
1024 | </page> |
1025 | <page string="Depreciation"> |
1026 | - <field name="start_date" attrs="{'readonly': ['|', ('state', 'not in', ['draft', 'open']), ('lock_open', '!=', False)]}" /> |
1027 | - <field name="depreciation_method" attrs="{'readonly': ['|', ('state', 'not in', ['draft', 'open']), ('lock_open', '!=', False)]}"/> |
1028 | + <field name="start_date" required="1" attrs="{'readonly': ['|', ('state', 'not in', ['draft', 'open']), ('lock_open', '!=', False)]}" /> |
1029 | + <field name="depreciation_method" required="1" attrs="{'readonly': ['|', ('state', 'not in', ['draft', 'open']), ('lock_open', '!=', False)]}"/> |
1030 | <newline /> |
1031 | <field name="depreciation_amount" /> |
1032 | <field name="disposal_amount" /> |
1033 | @@ -585,6 +588,82 @@ |
1034 | |
1035 | <menuitem sequence="200" action="action_product_asset_generate_entries" id="menu_product_asset_generate_entries" parent="product_asset.menu_asset_sales" /> |
1036 | |
1037 | + <record id="view_product_asset_import_entries" model="ir.ui.view"> |
1038 | + <field name="name">product.asset.import.entries.form</field> |
1039 | + <field name="model">product.asset.import.entries</field> |
1040 | + <field name="type">form</field> |
1041 | + <field name="arch" type="xml"> |
1042 | + <form string="Import Asset Entries"> |
1043 | + <separator string="This will import Entries from an XML file." colspan="4"/> |
1044 | + <field name="file" filename="filename" attrs="{'invisible': [('state', '!=', 'draft')]}"/> |
1045 | + <field name="filename" invisible="1"/> |
1046 | + <field name="progression" widget="progressbar" nolabel="1" attrs="{'invisible': [('state', '=', 'draft')]}" colspan="4" /> |
1047 | + <field name="message" nolabel="1" attrs="{'invisible': [('state', '=', 'draft')]}"/> |
1048 | + <newline/> |
1049 | + <button name="button_update" type="object" string="Update" icon="gtk-refresh" attrs="{'invisible': [('state', '!=', 'inprogress')]}"/> |
1050 | + <newline /> |
1051 | + <field name="error_ids" nolabel="1" attrs="{'invisible': [('state', '!=', 'error')]}"/> |
1052 | + <group col="4" colspan="4" attrs="{'invisible': [('state', '!=', 'draft')]}"> |
1053 | + <separator string="Import template"/> |
1054 | + <newline /> |
1055 | + <html> |
1056 | + <br /> |
1057 | + <table style="margin: 0 auto;"> |
1058 | + <thead> |
1059 | + <tr style='background-color: #ccc;font-size:1.2em;'> |
1060 | + <th class='external_asset_id' style='border: thin solid black; text-transform: none;'>External Asset ID</th> |
1061 | + <th class='prod_int_code' style='border: thin solid black; font-weigth:bold; border-left: none; text-transform: none;'>Product Code</th> |
1062 | + <th class='asset_type_id' style='border: thin solid black; font-weigth:bold; border-left: none; text-transform: none;'>Asset Type</th> |
1063 | + <th class='useful_life_id' style='border: thin solid black; font-weigth:bold; border-left: none; text-transform: none;'>Useful Life</th> |
1064 | + <th class='serial_nb' style="border: thin solid black; border-left: none; text-transform: none;">Serial Number</th> |
1065 | + <th class='brand' style='border: thin solid black; border-left: none; text-transform: none;'>Brand</th> |
1066 | + <th class='type' style='border: thin solid black; border-left: none; text-transform: none;'>Type</th> |
1067 | + <th class='model' style='border: thin solid black; border-left: none; text-transform: none;'>Model</th> |
1068 | + <th class='year' style='border: thin solid black; border-left: none; text-transform: none;'>Year</th> |
1069 | + <th class='move_line_id' style='border: thin solid black; border-left: none; text-transform: none;'>Journal Item</th> |
1070 | + <th class='asset_bs_depreciation_account_id' style='border: thin solid black; border-left: none; text-transform: none;'>Asset B/S Depreciation Account</th> |
1071 | + <th class='asset_pl_account_id' style='border: thin solid black; border-left: none; text-transform: none;'>Asset P&L Depreciation Account</th> |
1072 | + </tr> |
1073 | + </thead> |
1074 | + <tbody> |
1075 | + <tr> |
1076 | + <th style="border: thin solid black; border-top: none;"></th> |
1077 | + <th style="border: thin solid black; color:red; font-weigth:bold; font-size:1.2em; border-left: none; border-top: none;">Mandatory</th> |
1078 | + <th style="border: thin solid black; color:red; font-weigth:bold; font-size:1.2em; border-left: none; border-top: none;">Mandatory</th> |
1079 | + <th style="border: thin solid black; color:red; font-weigth:bold; font-size:1.2em; border-left: none; border-top: none;">Mandatory</th> |
1080 | + <th style="border: thin solid black; border-left: none; border-top: none;"></th> |
1081 | + <th style="border: thin solid black; border-left: none; border-top: none;"></th> |
1082 | + <th style="border: thin solid black; border-left: none; border-top: none;"></th> |
1083 | + <th style="border: thin solid black; border-left: none; border-top: none;"></th> |
1084 | + <th style="border: thin solid black; border-left: none; border-top: none;"></th> |
1085 | + <th style="border: thin solid black; border-left: none; border-top: none;"></th> |
1086 | + <th style="border: thin solid black; border-left: none; border-top: none;"></th> |
1087 | + <th style="border: thin solid black; border-left: none; border-top: none;"></th> |
1088 | + </tr> |
1089 | + </tbody> |
1090 | + </table> |
1091 | + <br /> |
1092 | + </html> |
1093 | + </group> |
1094 | + <group colspan="4" col="2" attrs="{'invisible': [('state', '!=', 'draft')]}"> |
1095 | + <button string="Cancel" special="cancel" icon="gtk-cancel"/> |
1096 | + <button name="button_validate" type="object" string="Import" icon="terp-camera_test"/> |
1097 | + </group> |
1098 | + <field name="state" invisible="1"/> |
1099 | + </form> |
1100 | + </field> |
1101 | + </record> |
1102 | + |
1103 | + <record id="action_product_asset_import_entries" model="ir.actions.act_window"> |
1104 | + <field name="name">Import Asset Entries</field> |
1105 | + <field name="res_model">product.asset.import.entries</field> |
1106 | + <field name="view_type">form</field> |
1107 | + <field name="view_mode">form</field> |
1108 | + <field name="target">new</field> |
1109 | + </record> |
1110 | + |
1111 | + <menuitem sequence="300" action="action_product_asset_import_entries" id="menu_product_asset_import_entries" parent="product_asset.menu_asset_sales" /> |
1112 | + |
1113 | |
1114 | |
1115 | </data> |