diff --git a/.tx/config b/.tx/config new file mode 100644 index 00000000000..23e76595a0f --- /dev/null +++ b/.tx/config @@ -0,0 +1,1133 @@ +[main] +host = https://www.transifex.com +type = PO + +[odoo-9.base] +file_filter = openerp/addons/base/i18n/.po +source_file = openerp/addons/base/i18n/base.pot +source_lang = en + +[odoo-9.account] +file_filter = addons/account/i18n/.po +source_file = addons/account/i18n/account.pot +source_lang = en + +[odoo-9.account_accountant] +file_filter = addons/account_accountant/i18n/.po +source_file = addons/account_accountant/i18n/account_accountant.pot +source_lang = en + +[odoo-9.account_analytic_analysis] +file_filter = addons/account_analytic_analysis/i18n/.po +source_file = addons/account_analytic_analysis/i18n/account_analytic_analysis.pot +source_lang = en + +[odoo-9.account_analytic_default] +file_filter = addons/account_analytic_default/i18n/.po +source_file = addons/account_analytic_default/i18n/account_analytic_default.pot +source_lang = en + +[odoo-9.account_analytic_plans] +file_filter = addons/account_analytic_plans/i18n/.po +source_file = addons/account_analytic_plans/i18n/account_analytic_plans.pot +source_lang = en + +[odoo-9.account_anglo_saxon] +file_filter = addons/account_anglo_saxon/i18n/.po +source_file = addons/account_anglo_saxon/i18n/account_anglo_saxon.pot +source_lang = en + +[odoo-9.account_asset] +file_filter = addons/account_asset/i18n/.po +source_file = addons/account_asset/i18n/account_asset.pot +source_lang = en + +[odoo-9.account_bank_statement_extensions] +file_filter = addons/account_bank_statement_extensions/i18n/.po +source_file = addons/account_bank_statement_extensions/i18n/account_bank_statement_extensions.pot +source_lang = en + +[odoo-9.account_budget] +file_filter = addons/account_budget/i18n/.po +source_file = addons/account_budget/i18n/account_budget.pot +source_lang = en + +[odoo-9.account_cancel] +file_filter = addons/account_cancel/i18n/.po +source_file = addons/account_cancel/i18n/account_cancel.pot +source_lang = en + +[odoo-9.account_chart] +file_filter = addons/account_chart/i18n/.po +source_file = addons/account_chart/i18n/account_chart.pot +source_lang = en + +[odoo-9.account_check_writing] +file_filter = addons/account_check_writing/i18n/.po +source_file = addons/account_check_writing/i18n/account_check_writing.pot +source_lang = en + +[odoo-9.account_followup] +file_filter = addons/account_followup/i18n/.po +source_file = addons/account_followup/i18n/account_followup.pot +source_lang = en + +[odoo-9.account_payment] +file_filter = addons/account_payment/i18n/.po +source_file = addons/account_payment/i18n/account_payment.pot +source_lang = en + +[odoo-9.account_sequence] +file_filter = addons/account_sequence/i18n/.po +source_file = addons/account_sequence/i18n/account_sequence.pot +source_lang = en + +[odoo-9.account_test] +file_filter = addons/account_test/i18n/.po +source_file = addons/account_test/i18n/account_test.pot +source_lang = en + +[odoo-9.account_voucher] +file_filter = addons/account_voucher/i18n/.po +source_file = addons/account_voucher/i18n/account_voucher.pot +source_lang = en + +[odoo-9.analytic] +file_filter = addons/analytic/i18n/.po +source_file = addons/analytic/i18n/analytic.pot +source_lang = en + +[odoo-9.analytic_contract_hr_expense] +file_filter = addons/analytic_contract_hr_expense/i18n/.po +source_file = addons/analytic_contract_hr_expense/i18n/analytic_contract_hr_expense.pot +source_lang = en + +[odoo-9.analytic_user_function] +file_filter = addons/analytic_user_function/i18n/.po +source_file = addons/analytic_user_function/i18n/analytic_user_function.pot +source_lang = en + +[odoo-9.anonymization] +file_filter = addons/anonymization/i18n/.po +source_file = addons/anonymization/i18n/anonymization.pot +source_lang = en + +[odoo-9.association] +file_filter = addons/association/i18n/.po +source_file = addons/association/i18n/association.pot +source_lang = en + +[odoo-9.auth_crypt] +file_filter = addons/auth_crypt/i18n/.po +source_file = addons/auth_crypt/i18n/auth_crypt.pot +source_lang = en + +[odoo-9.auth_ldap] +file_filter = addons/auth_ldap/i18n/.po +source_file = addons/auth_ldap/i18n/auth_ldap.pot +source_lang = en + +[odoo-9.auth_oauth] +file_filter = addons/auth_oauth/i18n/.po +source_file = addons/auth_oauth/i18n/auth_oauth.pot +source_lang = en + +[odoo-9.auth_openid] +file_filter = addons/auth_openid/i18n/.po +source_file = addons/auth_openid/i18n/auth_openid.pot +source_lang = en + +[odoo-9.auth_signup] +file_filter = addons/auth_signup/i18n/.po +source_file = addons/auth_signup/i18n/auth_signup.pot +source_lang = en + +[odoo-9.base_action_rule] +file_filter = addons/base_action_rule/i18n/.po +source_file = addons/base_action_rule/i18n/base_action_rule.pot +source_lang = en + +[odoo-9.base_gengo] +file_filter = addons/base_gengo/i18n/.po +source_file = addons/base_gengo/i18n/base_gengo.pot +source_lang = en + +[odoo-9.base_geolocalize] +file_filter = addons/base_geolocalize/i18n/.po +source_file = addons/base_geolocalize/i18n/base_geolocalize.pot +source_lang = en + +[odoo-9.base_iban] +file_filter = addons/base_iban/i18n/.po +source_file = addons/base_iban/i18n/base_iban.pot +source_lang = en + +[odoo-9.base_import] +file_filter = addons/base_import/i18n/.po +source_file = addons/base_import/i18n/base_import.pot +source_lang = en + +[odoo-9.base_import_module] +file_filter = addons/base_import_module/i18n/.po +source_file = addons/base_import_module/i18n/base_import_module.pot +source_lang = en + +[odoo-9.base_report_designer] +file_filter = addons/base_report_designer/i18n/.po +source_file = addons/base_report_designer/i18n/base_report_designer.pot +source_lang = en + +[odoo-9.base_setup] +file_filter = addons/base_setup/i18n/.po +source_file = addons/base_setup/i18n/base_setup.pot +source_lang = en + +[odoo-9.base_vat] +file_filter = addons/base_vat/i18n/.po +source_file = addons/base_vat/i18n/base_vat.pot +source_lang = en + +[odoo-9.board] +file_filter = addons/board/i18n/.po +source_file = addons/board/i18n/board.pot +source_lang = en + +[odoo-9.bus] +file_filter = addons/bus/i18n/.po +source_file = addons/bus/i18n/bus.pot +source_lang = en + +[odoo-9.calendar] +file_filter = addons/calendar/i18n/.po +source_file = addons/calendar/i18n/calendar.pot +source_lang = en + +[odoo-9.claim_from_delivery] +file_filter = addons/claim_from_delivery/i18n/.po +source_file = addons/claim_from_delivery/i18n/claim_from_delivery.pot +source_lang = en + +[odoo-9.contacts] +file_filter = addons/contacts/i18n/.po +source_file = addons/contacts/i18n/contacts.pot +source_lang = en + +[odoo-9.crm] +file_filter = addons/crm/i18n/.po +source_file = addons/crm/i18n/crm.pot +source_lang = en + +[odoo-9.crm_claim] +file_filter = addons/crm_claim/i18n/.po +source_file = addons/crm_claim/i18n/crm_claim.pot +source_lang = en + +[odoo-9.crm_helpdesk] +file_filter = addons/crm_helpdesk/i18n/.po +source_file = addons/crm_helpdesk/i18n/crm_helpdesk.pot +source_lang = en + +[odoo-9.crm_mass_mailing] +file_filter = addons/crm_mass_mailing/i18n/.po +source_file = addons/crm_mass_mailing/i18n/crm_mass_mailing.pot +source_lang = en + +[odoo-9.crm_partner_assign] +file_filter = addons/crm_partner_assign/i18n/.po +source_file = addons/crm_partner_assign/i18n/crm_partner_assign.pot +source_lang = en + +[odoo-9.crm_profiling] +file_filter = addons/crm_profiling/i18n/.po +source_file = addons/crm_profiling/i18n/crm_profiling.pot +source_lang = en + +[odoo-9.crm_project_issue] +file_filter = addons/crm_project_issue/i18n/.po +source_file = addons/crm_project_issue/i18n/crm_project_issue.pot +source_lang = en + +[odoo-9.decimal_precision] +file_filter = addons/decimal_precision/i18n/.po +source_file = addons/decimal_precision/i18n/decimal_precision.pot +source_lang = en + +[odoo-9.delivery] +file_filter = addons/delivery/i18n/.po +source_file = addons/delivery/i18n/delivery.pot +source_lang = en + +[odoo-9.document] +file_filter = addons/document/i18n/.po +source_file = addons/document/i18n/document.pot +source_lang = en + +[odoo-9.edi] +file_filter = addons/edi/i18n/.po +source_file = addons/edi/i18n/edi.pot +source_lang = en + +[odoo-9.email_template] +file_filter = addons/email_template/i18n/.po +source_file = addons/email_template/i18n/email_template.pot +source_lang = en + +[odoo-9.event] +file_filter = addons/event/i18n/.po +source_file = addons/event/i18n/event.pot +source_lang = en + +[odoo-9.event_sale] +file_filter = addons/event_sale/i18n/.po +source_file = addons/event_sale/i18n/event_sale.pot +source_lang = en + +[odoo-9.fetchmail] +file_filter = addons/fetchmail/i18n/.po +source_file = addons/fetchmail/i18n/fetchmail.pot +source_lang = en + +[odoo-9.fleet] +file_filter = addons/fleet/i18n/.po +source_file = addons/fleet/i18n/fleet.pot +source_lang = en + +[odoo-9.gamification] +file_filter = addons/gamification/i18n/.po +source_file = addons/gamification/i18n/gamification.pot +source_lang = en + +[odoo-9.gamification_sale_crm] +file_filter = addons/gamification_sale_crm/i18n/.po +source_file = addons/gamification_sale_crm/i18n/gamification_sale_crm.pot +source_lang = en + +[odoo-9.google_account] +file_filter = addons/google_account/i18n/.po +source_file = addons/google_account/i18n/google_account.pot +source_lang = en + +[odoo-9.google_calendar] +file_filter = addons/google_calendar/i18n/.po +source_file = addons/google_calendar/i18n/google_calendar.pot +source_lang = en + +[odoo-9.google_drive] +file_filter = addons/google_drive/i18n/.po +source_file = addons/google_drive/i18n/google_drive.pot +source_lang = en + +[odoo-9.google_spreadsheet] +file_filter = addons/google_spreadsheet/i18n/.po +source_file = addons/google_spreadsheet/i18n/google_spreadsheet.pot +source_lang = en + +[odoo-9.hr] +file_filter = addons/hr/i18n/.po +source_file = addons/hr/i18n/hr.pot +source_lang = en + +[odoo-9.hr_applicant_document] +file_filter = addons/hr_applicant_document/i18n/.po +source_file = addons/hr_applicant_document/i18n/hr_applicant_document.pot +source_lang = en + +[odoo-9.hr_attendance] +file_filter = addons/hr_attendance/i18n/.po +source_file = addons/hr_attendance/i18n/hr_attendance.pot +source_lang = en + +[odoo-9.hr_contract] +file_filter = addons/hr_contract/i18n/.po +source_file = addons/hr_contract/i18n/hr_contract.pot +source_lang = en + +[odoo-9.hr_evaluation] +file_filter = addons/hr_evaluation/i18n/.po +source_file = addons/hr_evaluation/i18n/hr_evaluation.pot +source_lang = en + +[odoo-9.hr_expense] +file_filter = addons/hr_expense/i18n/.po +source_file = addons/hr_expense/i18n/hr_expense.pot +source_lang = en + +[odoo-9.hr_gamification] +file_filter = addons/hr_gamification/i18n/.po +source_file = addons/hr_gamification/i18n/hr_gamification.pot +source_lang = en + +[odoo-9.hr_holidays] +file_filter = addons/hr_holidays/i18n/.po +source_file = addons/hr_holidays/i18n/hr_holidays.pot +source_lang = en + +[odoo-9.hr_payroll] +file_filter = addons/hr_payroll/i18n/.po +source_file = addons/hr_payroll/i18n/hr_payroll.pot +source_lang = en + +[odoo-9.hr_payroll_account] +file_filter = addons/hr_payroll_account/i18n/.po +source_file = addons/hr_payroll_account/i18n/hr_payroll_account.pot +source_lang = en + +[odoo-9.hr_recruitment] +file_filter = addons/hr_recruitment/i18n/.po +source_file = addons/hr_recruitment/i18n/hr_recruitment.pot +source_lang = en + +[odoo-9.hr_timesheet] +file_filter = addons/hr_timesheet/i18n/.po +source_file = addons/hr_timesheet/i18n/hr_timesheet.pot +source_lang = en + +[odoo-9.hr_timesheet_invoice] +file_filter = addons/hr_timesheet_invoice/i18n/.po +source_file = addons/hr_timesheet_invoice/i18n/hr_timesheet_invoice.pot +source_lang = en + +[odoo-9.hr_timesheet_sheet] +file_filter = addons/hr_timesheet_sheet/i18n/.po +source_file = addons/hr_timesheet_sheet/i18n/hr_timesheet_sheet.pot +source_lang = en + +[odoo-9.im_chat] +file_filter = addons/im_chat/i18n/.po +source_file = addons/im_chat/i18n/im_chat.pot +source_lang = en + +[odoo-9.im_livechat] +file_filter = addons/im_livechat/i18n/.po +source_file = addons/im_livechat/i18n/im_livechat.pot +source_lang = en + +[odoo-9.im_odoo_support] +file_filter = addons/im_odoo_support/i18n/.po +source_file = addons/im_odoo_support/i18n/im_odoo_support.pot +source_lang = en + +[odoo-9.knowledge] +file_filter = addons/knowledge/i18n/.po +source_file = addons/knowledge/i18n/knowledge.pot +source_lang = en + +[odoo-9.l10n_ar] +file_filter = addons/l10n_ar/i18n/.po +source_file = addons/l10n_ar/i18n/l10n_ar.pot +source_lang = en + +[odoo-9.l10n_be] +file_filter = addons/l10n_be/i18n/.po +source_file = addons/l10n_be/i18n/l10n_be.pot +source_lang = en + +[odoo-9.l10n_be_coda] +file_filter = addons/l10n_be_coda/i18n/.po +source_file = addons/l10n_be_coda/i18n/l10n_be_coda.pot +source_lang = en + +[odoo-9.l10n_be_hr_payroll] +file_filter = addons/l10n_be_hr_payroll/i18n/.po +source_file = addons/l10n_be_hr_payroll/i18n/l10n_be_hr_payroll.pot +source_lang = en + +[odoo-9.l10n_be_intrastat] +file_filter = addons/l10n_be_intrastat/i18n/.po +source_file = addons/l10n_be_intrastat/i18n/l10n_be_intrastat.pot +source_lang = en + +[odoo-9.l10n_be_invoice_bba] +file_filter = addons/l10n_be_invoice_bba/i18n/.po +source_file = addons/l10n_be_invoice_bba/i18n/l10n_be_invoice_bba.pot +source_lang = en + +[odoo-9.l10n_bo] +file_filter = addons/l10n_bo/i18n/.po +source_file = addons/l10n_bo/i18n/l10n_bo.pot +source_lang = en + +[odoo-9.l10n_br] +file_filter = addons/l10n_br/i18n/.po +source_file = addons/l10n_br/i18n/l10n_br.pot +source_lang = en + +[odoo-9.l10n_cl] +file_filter = addons/l10n_cl/i18n/.po +source_file = addons/l10n_cl/i18n/l10n_cl.pot +source_lang = en + +[odoo-9.l10n_cr] +file_filter = addons/l10n_cr/i18n/.po +source_file = addons/l10n_cr/i18n/l10n_cr.pot +source_lang = en + +[odoo-9.l10n_de] +file_filter = addons/l10n_de/i18n/.po +source_file = addons/l10n_de/i18n/l10n_de.pot +source_lang = en + +[odoo-9.l10n_ec] +file_filter = addons/l10n_ec/i18n/.po +source_file = addons/l10n_ec/i18n/l10n_ec.pot +source_lang = en + +[odoo-9.l10n_es] +file_filter = addons/l10n_es/i18n/.po +source_file = addons/l10n_es/i18n/l10n_es.pot +source_lang = en + +[odoo-9.l10n_eu_service] +file_filter = addons/l10n_eu_service/i18n/.po +source_file = addons/l10n_eu_service/i18n/l10n_eu_service.pot +source_lang = en + +[odoo-9.l10n_fr] +file_filter = addons/l10n_fr/i18n/.po +source_file = addons/l10n_fr/i18n/l10n_fr.pot +source_lang = en + +[odoo-9.l10n_fr_rib] +file_filter = addons/l10n_fr_rib/i18n/.po +source_file = addons/l10n_fr_rib/i18n/l10n_fr_rib.pot +source_lang = en + +[odoo-9.l10n_gr] +file_filter = addons/l10n_gr/i18n/.po +source_file = addons/l10n_gr/i18n/l10n_gr.pot +source_lang = en + +[odoo-9.l10n_gt] +file_filter = addons/l10n_gt/i18n/.po +source_file = addons/l10n_gt/i18n/l10n_gt.pot +source_lang = en + +[odoo-9.l10n_hn] +file_filter = addons/l10n_hn/i18n/.po +source_file = addons/l10n_hn/i18n/l10n_hn.pot +source_lang = en + +[odoo-9.l10n_in] +file_filter = addons/l10n_in/i18n/.po +source_file = addons/l10n_in/i18n/l10n_in.pot +source_lang = en + +[odoo-9.l10n_in_hr_payroll] +file_filter = addons/l10n_in_hr_payroll/i18n/.po +source_file = addons/l10n_in_hr_payroll/i18n/l10n_in_hr_payroll.pot +source_lang = en + +[odoo-9.l10n_it] +file_filter = addons/l10n_it/i18n/.po +source_file = addons/l10n_it/i18n/l10n_it.pot +source_lang = en + +[odoo-9.l10n_lu] +file_filter = addons/l10n_lu/i18n/.po +source_file = addons/l10n_lu/i18n/l10n_lu.pot +source_lang = en + +[odoo-9.l10n_ma] +file_filter = addons/l10n_ma/i18n/.po +source_file = addons/l10n_ma/i18n/l10n_ma.pot +source_lang = en + +[odoo-9.l10n_multilang] +file_filter = addons/l10n_multilang/i18n/.po +source_file = addons/l10n_multilang/i18n/l10n_multilang.pot +source_lang = en + +[odoo-9.l10n_nl] +file_filter = addons/l10n_nl/i18n/.po +source_file = addons/l10n_nl/i18n/l10n_nl.pot +source_lang = en + +[odoo-9.l10n_pe] +file_filter = addons/l10n_pe/i18n/.po +source_file = addons/l10n_pe/i18n/l10n_pe.pot +source_lang = en + +[odoo-9.l10n_pl] +file_filter = addons/l10n_pl/i18n/.po +source_file = addons/l10n_pl/i18n/l10n_pl.pot +source_lang = en + +[odoo-9.l10n_syscohada] +file_filter = addons/l10n_syscohada/i18n/.po +source_file = addons/l10n_syscohada/i18n/l10n_syscohada.pot +source_lang = en + +[odoo-9.l10n_th] +file_filter = addons/l10n_th/i18n/.po +source_file = addons/l10n_th/i18n/l10n_th.pot +source_lang = en + +[odoo-9.l10n_uk] +file_filter = addons/l10n_uk/i18n/.po +source_file = addons/l10n_uk/i18n/l10n_uk.pot +source_lang = en + +[odoo-9.l10n_ve] +file_filter = addons/l10n_ve/i18n/.po +source_file = addons/l10n_ve/i18n/l10n_ve.pot +source_lang = en + +[odoo-9.lunch] +file_filter = addons/lunch/i18n/.po +source_file = addons/lunch/i18n/lunch.pot +source_lang = en + +[odoo-9.mail] +file_filter = addons/mail/i18n/.po +source_file = addons/mail/i18n/mail.pot +source_lang = en + +[odoo-9.marketing] +file_filter = addons/marketing/i18n/.po +source_file = addons/marketing/i18n/marketing.pot +source_lang = en + +[odoo-9.marketing_campaign] +file_filter = addons/marketing_campaign/i18n/.po +source_file = addons/marketing_campaign/i18n/marketing_campaign.pot +source_lang = en + +[odoo-9.marketing_campaign_crm_demo] +file_filter = addons/marketing_campaign_crm_demo/i18n/.po +source_file = addons/marketing_campaign_crm_demo/i18n/marketing_campaign_crm_demo.pot +source_lang = en + +[odoo-9.marketing_crm] +file_filter = addons/marketing_crm/i18n/.po +source_file = addons/marketing_crm/i18n/marketing_crm.pot +source_lang = en + +[odoo-9.mass_mailing] +file_filter = addons/mass_mailing/i18n/.po +source_file = addons/mass_mailing/i18n/mass_mailing.pot +source_lang = en + +[odoo-9.membership] +file_filter = addons/membership/i18n/.po +source_file = addons/membership/i18n/membership.pot +source_lang = en + +[odoo-9.mrp] +file_filter = addons/mrp/i18n/.po +source_file = addons/mrp/i18n/mrp.pot +source_lang = en + +[odoo-9.mrp_byproduct] +file_filter = addons/mrp_byproduct/i18n/.po +source_file = addons/mrp_byproduct/i18n/mrp_byproduct.pot +source_lang = en + +[odoo-9.mrp_operations] +file_filter = addons/mrp_operations/i18n/.po +source_file = addons/mrp_operations/i18n/mrp_operations.pot +source_lang = en + +[odoo-9.mrp_repair] +file_filter = addons/mrp_repair/i18n/.po +source_file = addons/mrp_repair/i18n/mrp_repair.pot +source_lang = en + +[odoo-9.multi_company] +file_filter = addons/multi_company/i18n/.po +source_file = addons/multi_company/i18n/multi_company.pot +source_lang = en + +[odoo-9.note] +file_filter = addons/note/i18n/.po +source_file = addons/note/i18n/note.pot +source_lang = en + +[odoo-9.note_pad] +file_filter = addons/note_pad/i18n/.po +source_file = addons/note_pad/i18n/note_pad.pot +source_lang = en + +[odoo-9.pad] +file_filter = addons/pad/i18n/.po +source_file = addons/pad/i18n/pad.pot +source_lang = en + +[odoo-9.pad_project] +file_filter = addons/pad_project/i18n/.po +source_file = addons/pad_project/i18n/pad_project.pot +source_lang = en + +[odoo-9.payment] +file_filter = addons/payment/i18n/.po +source_file = addons/payment/i18n/payment.pot +source_lang = en + +[odoo-9.payment_adyen] +file_filter = addons/payment_adyen/i18n/.po +source_file = addons/payment_adyen/i18n/payment_adyen.pot +source_lang = en + +[odoo-9.payment_buckaroo] +file_filter = addons/payment_buckaroo/i18n/.po +source_file = addons/payment_buckaroo/i18n/payment_buckaroo.pot +source_lang = en + +[odoo-9.payment_ogone] +file_filter = addons/payment_ogone/i18n/.po +source_file = addons/payment_ogone/i18n/payment_ogone.pot +source_lang = en + +[odoo-9.payment_paypal] +file_filter = addons/payment_paypal/i18n/.po +source_file = addons/payment_paypal/i18n/payment_paypal.pot +source_lang = en + +[odoo-9.payment_transfer] +file_filter = addons/payment_transfer/i18n/.po +source_file = addons/payment_transfer/i18n/payment_transfer.pot +source_lang = en + +[odoo-9.point_of_sale] +file_filter = addons/point_of_sale/i18n/.po +source_file = addons/point_of_sale/i18n/point_of_sale.pot +source_lang = en + +[odoo-9.portal] +file_filter = addons/portal/i18n/.po +source_file = addons/portal/i18n/portal.pot +source_lang = en + +[odoo-9.portal_claim] +file_filter = addons/portal_claim/i18n/.po +source_file = addons/portal_claim/i18n/portal_claim.pot +source_lang = en + +[odoo-9.portal_project] +file_filter = addons/portal_project/i18n/.po +source_file = addons/portal_project/i18n/portal_project.pot +source_lang = en + +[odoo-9.portal_project_issue] +file_filter = addons/portal_project_issue/i18n/.po +source_file = addons/portal_project_issue/i18n/portal_project_issue.pot +source_lang = en + +[odoo-9.portal_sale] +file_filter = addons/portal_sale/i18n/.po +source_file = addons/portal_sale/i18n/portal_sale.pot +source_lang = en + +[odoo-9.pos_discount] +file_filter = addons/pos_discount/i18n/.po +source_file = addons/pos_discount/i18n/pos_discount.pot +source_lang = en + +[odoo-9.pos_restaurant] +file_filter = addons/pos_restaurant/i18n/.po +source_file = addons/pos_restaurant/i18n/pos_restaurant.pot +source_lang = en + +[odoo-9.procurement] +file_filter = addons/procurement/i18n/.po +source_file = addons/procurement/i18n/procurement.pot +source_lang = en + +[odoo-9.procurement_jit] +file_filter = addons/procurement_jit/i18n/.po +source_file = addons/procurement_jit/i18n/procurement_jit.pot +source_lang = en + +[odoo-9.product] +file_filter = addons/product/i18n/.po +source_file = addons/product/i18n/product.pot +source_lang = en + +[odoo-9.product_email_template] +file_filter = addons/product_email_template/i18n/.po +source_file = addons/product_email_template/i18n/product_email_template.pot +source_lang = en + +[odoo-9.product_expiry] +file_filter = addons/product_expiry/i18n/.po +source_file = addons/product_expiry/i18n/product_expiry.pot +source_lang = en + +[odoo-9.product_extended] +file_filter = addons/product_extended/i18n/.po +source_file = addons/product_extended/i18n/product_extended.pot +source_lang = en + +[odoo-9.product_margin] +file_filter = addons/product_margin/i18n/.po +source_file = addons/product_margin/i18n/product_margin.pot +source_lang = en + +[odoo-9.product_visible_discount] +file_filter = addons/product_visible_discount/i18n/.po +source_file = addons/product_visible_discount/i18n/product_visible_discount.pot +source_lang = en + +[odoo-9.project] +file_filter = addons/project/i18n/.po +source_file = addons/project/i18n/project.pot +source_lang = en + +[odoo-9.project_issue] +file_filter = addons/project_issue/i18n/.po +source_file = addons/project_issue/i18n/project_issue.pot +source_lang = en + +[odoo-9.project_issue_sheet] +file_filter = addons/project_issue_sheet/i18n/.po +source_file = addons/project_issue_sheet/i18n/project_issue_sheet.pot +source_lang = en + +[odoo-9.project_timesheet] +file_filter = addons/project_timesheet/i18n/.po +source_file = addons/project_timesheet/i18n/project_timesheet.pot +source_lang = en + +[odoo-9.purchase] +file_filter = addons/purchase/i18n/.po +source_file = addons/purchase/i18n/purchase.pot +source_lang = en + +[odoo-9.purchase_analytic_plans] +file_filter = addons/purchase_analytic_plans/i18n/.po +source_file = addons/purchase_analytic_plans/i18n/purchase_analytic_plans.pot +source_lang = en + +[odoo-9.purchase_double_validation] +file_filter = addons/purchase_double_validation/i18n/.po +source_file = addons/purchase_double_validation/i18n/purchase_double_validation.pot +source_lang = en + +[odoo-9.purchase_requisition] +file_filter = addons/purchase_requisition/i18n/.po +source_file = addons/purchase_requisition/i18n/purchase_requisition.pot +source_lang = en + +[odoo-9.report] +file_filter = addons/report/i18n/.po +source_file = addons/report/i18n/report.pot +source_lang = en + +[odoo-9.report_intrastat] +file_filter = addons/report_intrastat/i18n/.po +source_file = addons/report_intrastat/i18n/report_intrastat.pot +source_lang = en + +[odoo-9.report_webkit] +file_filter = addons/report_webkit/i18n/.po +source_file = addons/report_webkit/i18n/report_webkit.pot +source_lang = en + +[odoo-9.resource] +file_filter = addons/resource/i18n/.po +source_file = addons/resource/i18n/resource.pot +source_lang = en + +[odoo-9.sale] +file_filter = addons/sale/i18n/.po +source_file = addons/sale/i18n/sale.pot +source_lang = en + +[odoo-9.sale_analytic_plans] +file_filter = addons/sale_analytic_plans/i18n/.po +source_file = addons/sale_analytic_plans/i18n/sale_analytic_plans.pot +source_lang = en + +[odoo-9.sale_crm] +file_filter = addons/sale_crm/i18n/.po +source_file = addons/sale_crm/i18n/sale_crm.pot +source_lang = en + +[odoo-9.sale_journal] +file_filter = addons/sale_journal/i18n/.po +source_file = addons/sale_journal/i18n/sale_journal.pot +source_lang = en + +[odoo-9.sale_layout] +file_filter = addons/sale_layout/i18n/.po +source_file = addons/sale_layout/i18n/sale_layout.pot +source_lang = en + +[odoo-9.sale_margin] +file_filter = addons/sale_margin/i18n/.po +source_file = addons/sale_margin/i18n/sale_margin.pot +source_lang = en + +[odoo-9.sale_mrp] +file_filter = addons/sale_mrp/i18n/.po +source_file = addons/sale_mrp/i18n/sale_mrp.pot +source_lang = en + +[odoo-9.sale_order_dates] +file_filter = addons/sale_order_dates/i18n/.po +source_file = addons/sale_order_dates/i18n/sale_order_dates.pot +source_lang = en + +[odoo-9.sale_service] +file_filter = addons/sale_service/i18n/.po +source_file = addons/sale_service/i18n/sale_service.pot +source_lang = en + +[odoo-9.sales_team] +file_filter = addons/sales_team/i18n/.po +source_file = addons/sales_team/i18n/sales_team.pot +source_lang = en + +[odoo-9.sale_stock] +file_filter = addons/sale_stock/i18n/.po +source_file = addons/sale_stock/i18n/sale_stock.pot +source_lang = en + +[odoo-9.share] +file_filter = addons/share/i18n/.po +source_file = addons/share/i18n/share.pot +source_lang = en + +[odoo-9.stock] +file_filter = addons/stock/i18n/.po +source_file = addons/stock/i18n/stock.pot +source_lang = en + +[odoo-9.stock_account] +file_filter = addons/stock_account/i18n/.po +source_file = addons/stock_account/i18n/stock_account.pot +source_lang = en + +[odoo-9.stock_dropshipping] +file_filter = addons/stock_dropshipping/i18n/.po +source_file = addons/stock_dropshipping/i18n/stock_dropshipping.pot +source_lang = en + +[odoo-9.stock_invoice_directly] +file_filter = addons/stock_invoice_directly/i18n/.po +source_file = addons/stock_invoice_directly/i18n/stock_invoice_directly.pot +source_lang = en + +[odoo-9.stock_landed_costs] +file_filter = addons/stock_landed_costs/i18n/.po +source_file = addons/stock_landed_costs/i18n/stock_landed_costs.pot +source_lang = en + +[odoo-9.stock_picking_wave] +file_filter = addons/stock_picking_wave/i18n/.po +source_file = addons/stock_picking_wave/i18n/stock_picking_wave.pot +source_lang = en + +[odoo-9.subscription] +file_filter = addons/subscription/i18n/.po +source_file = addons/subscription/i18n/subscription.pot +source_lang = en + +[odoo-9.survey] +file_filter = addons/survey/i18n/.po +source_file = addons/survey/i18n/survey.pot +source_lang = en + +[odoo-9.survey_crm] +file_filter = addons/survey_crm/i18n/.po +source_file = addons/survey_crm/i18n/survey_crm.pot +source_lang = en + +[odoo-9.warning] +file_filter = addons/warning/i18n/.po +source_file = addons/warning/i18n/warning.pot +source_lang = en + +[odoo-9.web] +file_filter = addons/web/i18n/.po +source_file = addons/web/i18n/web.pot +source_lang = en + +[odoo-9.web_calendar] +file_filter = addons/web_calendar/i18n/.po +source_file = addons/web_calendar/i18n/web_calendar.pot +source_lang = en + +[odoo-9.web_diagram] +file_filter = addons/web_diagram/i18n/.po +source_file = addons/web_diagram/i18n/web_diagram.pot +source_lang = en + +[odoo-9.web_gantt] +file_filter = addons/web_gantt/i18n/.po +source_file = addons/web_gantt/i18n/web_gantt.pot +source_lang = en + +[odoo-9.web_graph] +file_filter = addons/web_graph/i18n/.po +source_file = addons/web_graph/i18n/web_graph.pot +source_lang = en + +[odoo-9.web_kanban] +file_filter = addons/web_kanban/i18n/.po +source_file = addons/web_kanban/i18n/web_kanban.pot +source_lang = en + +[odoo-9.web_kanban_gauge] +file_filter = addons/web_kanban_gauge/i18n/.po +source_file = addons/web_kanban_gauge/i18n/web_kanban_gauge.pot +source_lang = en + +[odoo-9.web_linkedin] +file_filter = addons/web_linkedin/i18n/.po +source_file = addons/web_linkedin/i18n/web_linkedin.pot +source_lang = en + +[odoo-9.web_view_editor] +file_filter = addons/web_view_editor/i18n/.po +source_file = addons/web_view_editor/i18n/web_view_editor.pot +source_lang = en + +[odoo-9.website] +file_filter = addons/website/i18n/.po +source_file = addons/website/i18n/website.pot +source_lang = en + +[odoo-9.website_blog] +file_filter = addons/website_blog/i18n/.po +source_file = addons/website_blog/i18n/website_blog.pot +source_lang = en + +[odoo-9.website_certification] +file_filter = addons/website_certification/i18n/.po +source_file = addons/website_certification/i18n/website_certification.pot +source_lang = en + +[odoo-9.website_crm] +file_filter = addons/website_crm/i18n/.po +source_file = addons/website_crm/i18n/website_crm.pot +source_lang = en + +[odoo-9.website_crm_partner_assign] +file_filter = addons/website_crm_partner_assign/i18n/.po +source_file = addons/website_crm_partner_assign/i18n/website_crm_partner_assign.pot +source_lang = en + +[odoo-9.website_customer] +file_filter = addons/website_customer/i18n/.po +source_file = addons/website_customer/i18n/website_customer.pot +source_lang = en + +[odoo-9.website_event] +file_filter = addons/website_event/i18n/.po +source_file = addons/website_event/i18n/website_event.pot +source_lang = en + +[odoo-9.website_event_sale] +file_filter = addons/website_event_sale/i18n/.po +source_file = addons/website_event_sale/i18n/website_event_sale.pot +source_lang = en + +[odoo-9.website_event_track] +file_filter = addons/website_event_track/i18n/.po +source_file = addons/website_event_track/i18n/website_event_track.pot +source_lang = en + +[odoo-9.website_forum] +file_filter = addons/website_forum/i18n/.po +source_file = addons/website_forum/i18n/website_forum.pot +source_lang = en + +[odoo-9.website_forum_doc] +file_filter = addons/website_forum_doc/i18n/.po +source_file = addons/website_forum_doc/i18n/website_forum_doc.pot +source_lang = en + +[odoo-9.website_gengo] +file_filter = addons/website_gengo/i18n/.po +source_file = addons/website_gengo/i18n/website_gengo.pot +source_lang = en + +[odoo-9.website_google_map] +file_filter = addons/website_google_map/i18n/.po +source_file = addons/website_google_map/i18n/website_google_map.pot +source_lang = en + +[odoo-9.website_hr] +file_filter = addons/website_hr/i18n/.po +source_file = addons/website_hr/i18n/website_hr.pot +source_lang = en + +[odoo-9.website_hr_recruitment] +file_filter = addons/website_hr_recruitment/i18n/.po +source_file = addons/website_hr_recruitment/i18n/website_hr_recruitment.pot +source_lang = en + +[odoo-9.website_livechat] +file_filter = addons/website_livechat/i18n/.po +source_file = addons/website_livechat/i18n/website_livechat.pot +source_lang = en + +[odoo-9.website_mail] +file_filter = addons/website_mail/i18n/.po +source_file = addons/website_mail/i18n/website_mail.pot +source_lang = en + +[odoo-9.website_mail_group] +file_filter = addons/website_mail_group/i18n/.po +source_file = addons/website_mail_group/i18n/website_mail_group.pot +source_lang = en + +[odoo-9.website_membership] +file_filter = addons/website_membership/i18n/.po +source_file = addons/website_membership/i18n/website_membership.pot +source_lang = en + +[odoo-9.website_partner] +file_filter = addons/website_partner/i18n/.po +source_file = addons/website_partner/i18n/website_partner.pot +source_lang = en + +[odoo-9.website_payment] +file_filter = addons/website_payment/i18n/.po +source_file = addons/website_payment/i18n/website_payment.pot +source_lang = en + +[odoo-9.website_project] +file_filter = addons/website_project/i18n/.po +source_file = addons/website_project/i18n/website_project.pot +source_lang = en + +[odoo-9.website_quote] +file_filter = addons/website_quote/i18n/.po +source_file = addons/website_quote/i18n/website_quote.pot +source_lang = en + +[odoo-9.website_report] +file_filter = addons/website_report/i18n/.po +source_file = addons/website_report/i18n/website_report.pot +source_lang = en + +[odoo-9.website_sale] +file_filter = addons/website_sale/i18n/.po +source_file = addons/website_sale/i18n/website_sale.pot +source_lang = en + +[odoo-9.website_sale_delivery] +file_filter = addons/website_sale_delivery/i18n/.po +source_file = addons/website_sale_delivery/i18n/website_sale_delivery.pot +source_lang = en + +[odoo-9.website_sale_options] +file_filter = addons/website_sale_options/i18n/.po +source_file = addons/website_sale_options/i18n/website_sale_options.pot +source_lang = en + +[odoo-9.website_twitter] +file_filter = addons/website_twitter/i18n/.po +source_file = addons/website_twitter/i18n/website_twitter.pot +source_lang = en + +[odoo-9.web_tests] +file_filter = addons/web_tests/i18n/.po +source_file = addons/web_tests/i18n/web_tests.pot +source_lang = en + +[odoo-9.web_tests_demo] +file_filter = addons/web_tests_demo/i18n/.po +source_file = addons/web_tests_demo/i18n/web_tests_demo.pot +source_lang = en diff --git a/addons/account/account_bank_statement.py b/addons/account/account_bank_statement.py index e95a254415e..fb5cdedbb26 100644 --- a/addons/account/account_bank_statement.py +++ b/addons/account/account_bank_statement.py @@ -743,6 +743,60 @@ class account_bank_statement_line(osv.osv): 'account_id': account_id } + def _get_exchange_lines(self, cr, uid, st_line, mv_line, currency_diff, currency_id, move_id, context=None): + ''' + Prepare the two lines in company currency due to currency rate difference. + + :param line: browse record of the voucher.line for which we want to create currency rate difference accounting + entries + :param move_id: Account move wher the move lines will be. + :param currency_diff: Amount to be posted. + :param company_currency: id of currency of the company to which the voucher belong + :param current_currency: id of currency of the voucher + :return: the account move line and its counterpart to create, depicted as mapping between fieldname and value + :rtype: tuple of dict + ''' + if currency_diff > 0: + exchange_account_id = st_line.company_id.expense_currency_exchange_account_id.id + else: + exchange_account_id = st_line.company_id.income_currency_exchange_account_id.id + # Even if the amount_currency is never filled, we need to pass the foreign currency because otherwise + # the receivable/payable account may have a secondary currency, which render this field mandatory + if mv_line.account_id.currency_id: + account_currency_id = mv_line.account_id.currency_id.id + else: + account_currency_id = st_line.company_id.currency_id.id != currency_id and currency_id or False + move_line = { + 'journal_id': st_line.journal_id.id, + 'period_id': st_line.statement_id.period_id.id, + 'name': _('change') + ': ' + (st_line.name or '/'), + 'account_id': mv_line.account_id.id, + 'move_id': move_id, + 'partner_id': st_line.partner_id.id, + 'currency_id': account_currency_id, + 'amount_currency': 0.0, + 'quantity': 1, + 'credit': currency_diff > 0 and currency_diff or 0.0, + 'debit': currency_diff < 0 and -currency_diff or 0.0, + 'date': st_line.date, + 'counterpart_move_line_id': mv_line.id, + } + move_line_counterpart = { + 'journal_id': st_line.journal_id.id, + 'period_id': st_line.statement_id.period_id.id, + 'name': _('change') + ': ' + (st_line.name or '/'), + 'account_id': exchange_account_id, + 'move_id': move_id, + 'amount_currency': 0.0, + 'partner_id': st_line.partner_id.id, + 'currency_id': account_currency_id, + 'quantity': 1, + 'debit': currency_diff > 0 and currency_diff or 0.0, + 'credit': currency_diff < 0 and -currency_diff or 0.0, + 'date': st_line.date, + } + return (move_line, move_line_counterpart) + def process_reconciliations(self, cr, uid, data, context=None): for datum in data: self.process_reconciliation(cr, uid, datum[0], datum[1], context=context) @@ -857,6 +911,19 @@ class account_bank_statement_line(osv.osv): if credit_at_old_rate - credit_at_current_rate: currency_diff = credit_at_current_rate - credit_at_old_rate to_create.append(self.get_currency_rate_line(cr, uid, st_line, currency_diff, move_id, context=context)) + if mv_line.currency_id and mv_line_dict['currency_id'] == mv_line.currency_id.id: + amount_unreconciled = mv_line.amount_residual_currency + else: + amount_unreconciled = currency_obj.compute(cr, uid, company_currency.id, mv_line_dict['currency_id'] , mv_line.amount_residual, context=ctx) + if float_is_zero(mv_line_dict['amount_currency'] + amount_unreconciled, precision_rounding=mv_line.currency_id.rounding): + amount = mv_line_dict['debit'] or mv_line_dict['credit'] + sign = -1 if mv_line_dict['debit'] else 1 + currency_rate_difference = sign * (mv_line.amount_residual - amount) + if not company_currency.is_zero(currency_rate_difference): + exchange_lines = self._get_exchange_lines(cr, uid, st_line, mv_line, currency_rate_difference, mv_line_dict['currency_id'], move_id, context=context) + for exchange_line in exchange_lines: + to_create.append(exchange_line) + else: mv_line_dict['debit'] = debit_at_current_rate mv_line_dict['credit'] = credit_at_current_rate diff --git a/addons/account/tests/test_reconciliation.py b/addons/account/tests/test_reconciliation.py index cfd1b1e8973..1e875574d73 100644 --- a/addons/account/tests/test_reconciliation.py +++ b/addons/account/tests/test_reconciliation.py @@ -14,13 +14,17 @@ class TestReconciliation(TransactionCase): self.account_invoice_line_model = self.registry('account.invoice.line') self.acc_bank_stmt_model = self.registry('account.bank.statement') self.acc_bank_stmt_line_model = self.registry('account.bank.statement.line') + self.res_currency_model = self.registry('res.currency') + self.res_currency_rate_model = self.registry('res.currency.rate') self.partner_agrolait_id = self.registry("ir.model.data").get_object_reference(self.cr, self.uid, "base", "res_partner_2")[1] self.currency_swiss_id = self.registry("ir.model.data").get_object_reference(self.cr, self.uid, "base", "CHF")[1] self.currency_usd_id = self.registry("ir.model.data").get_object_reference(self.cr, self.uid, "base", "USD")[1] self.currency_euro_id = self.registry("ir.model.data").get_object_reference(self.cr, self.uid, "base", "EUR")[1] self.account_rcv_id = self.registry("ir.model.data").get_object_reference(self.cr, self.uid, "account", "a_recv")[1] - self.account_rsa_id = self.registry("ir.model.data").get_object_reference(self.cr, self.uid, "account", "rsa")[1] + self.account_fx_income_id = self.registry("ir.model.data").get_object_reference(self.cr, self.uid, "account", "income_fx_income")[1] + self.account_fx_expense_id = self.registry("ir.model.data").get_object_reference(self.cr, self.uid, "account", "income_fx_expense")[1] + self.product_id = self.registry("ir.model.data").get_object_reference(self.cr, self.uid, "product", "product_product_4")[1] self.bank_journal_usd_id = self.registry("ir.model.data").get_object_reference(self.cr, self.uid, "account", "bank_journal_usd")[1] @@ -29,8 +33,9 @@ class TestReconciliation(TransactionCase): self.account_euro_id = self.registry("ir.model.data").get_object_reference(self.cr, self.uid, "account", "bnk")[1] self.company_id = self.registry("ir.model.data").get_object_reference(self.cr, self.uid, "base", "main_company")[1] - #set expense_currency_exchange_account_id and income_currency_exchange_account_id to a random account - self.registry("res.company").write(self.cr, self.uid, [self.company_id], {'expense_currency_exchange_account_id': self.account_rsa_id, 'income_currency_exchange_account_id':self.account_rsa_id}) + + #set expense_currency_exchange_account_id and income_currency_exchange_account_id to the according accounts + self.registry("res.company").write(self.cr, self.uid, [self.company_id], {'expense_currency_exchange_account_id': self.account_fx_expense_id, 'income_currency_exchange_account_id':self.account_fx_income_id}) def create_invoice(self, type='out_invoice', currency=None): cr, uid = self.cr, self.uid @@ -130,12 +135,12 @@ class TestReconciliation(TransactionCase): self.check_results(customer_move_lines, { self.account_usd_id: {'debit': 40.0, 'credit': 0.0, 'amount_currency': 50, 'currency_id': self.currency_usd_id}, self.account_rcv_id: {'debit': 0.0, 'credit': 32.70, 'amount_currency': -50, 'currency_id': self.currency_usd_id}, - self.account_rsa_id: {'debit': 0.0, 'credit': 7.30, 'amount_currency': 0.0, 'currency_id': self.currency_usd_id}, + self.account_fx_income_id: {'debit': 0.0, 'credit': 7.30, 'amount_currency': 0.0, 'currency_id': self.currency_usd_id}, }) self.check_results(supplier_move_lines, { self.account_usd_id: {'debit': 0.0, 'credit': 40.0, 'amount_currency': -50, 'currency_id': self.currency_usd_id}, self.account_rcv_id: {'debit': 32.70, 'credit': 0.0, 'amount_currency': 50, 'currency_id': self.currency_usd_id}, - self.account_rsa_id: {'debit': 7.30, 'credit': 0.0, 'amount_currency': 0.0, 'currency_id': self.currency_usd_id}, + self.account_fx_income_id: {'debit': 7.30, 'credit': 0.0, 'amount_currency': 0.0, 'currency_id': self.currency_usd_id}, }) def test_statement_usd_invoice_chf_transaction_chf(self): @@ -143,12 +148,12 @@ class TestReconciliation(TransactionCase): self.check_results(customer_move_lines, { self.account_usd_id: {'debit': 27.47, 'credit': 0.0, 'amount_currency': 42, 'currency_id': self.currency_usd_id}, self.account_rcv_id: {'debit': 0.0, 'credit': 38.21, 'amount_currency': -50, 'currency_id': self.currency_swiss_id}, - self.account_rsa_id: {'debit': 10.74, 'credit': 0.0, 'amount_currency': 0.0, 'currency_id': self.currency_usd_id}, + self.account_fx_income_id: {'debit': 10.74, 'credit': 0.0, 'amount_currency': 0.0, 'currency_id': self.currency_usd_id}, }) self.check_results(supplier_move_lines, { self.account_usd_id: {'debit': 0.0, 'credit': 27.47, 'amount_currency': -42, 'currency_id': self.currency_usd_id}, self.account_rcv_id: {'debit': 38.21, 'credit': 0.0, 'amount_currency': 50, 'currency_id': self.currency_swiss_id}, - self.account_rsa_id: {'debit': 0.0, 'credit': 10.74, 'amount_currency': 0.0, 'currency_id': self.currency_usd_id}, + self.account_fx_income_id: {'debit': 0.0, 'credit': 10.74, 'amount_currency': 0.0, 'currency_id': self.currency_usd_id}, }) def test_statement_eur_invoice_usd_transaction_usd(self): @@ -156,12 +161,12 @@ class TestReconciliation(TransactionCase): self.check_results(customer_move_lines, { self.account_euro_id: {'debit': 40.0, 'credit': 0.0, 'amount_currency': 50, 'currency_id': self.currency_usd_id}, self.account_rcv_id: {'debit': 0.0, 'credit': 32.7, 'amount_currency': -50, 'currency_id': self.currency_usd_id}, - self.account_rsa_id: {'debit': 0.0, 'credit': 7.30, 'amount_currency': 0.0, 'currency_id': False}, + self.account_fx_income_id: {'debit': 0.0, 'credit': 7.30, 'amount_currency': 0.0, 'currency_id': False}, }) self.check_results(supplier_move_lines, { self.account_euro_id: {'debit': 0.0, 'credit': 40.0, 'amount_currency': -50, 'currency_id': self.currency_usd_id}, self.account_rcv_id: {'debit': 32.7, 'credit': 0.0, 'amount_currency': 50, 'currency_id': self.currency_usd_id}, - self.account_rsa_id: {'debit': 7.30, 'credit': 0.0, 'amount_currency': 0.0, 'currency_id': False}, + self.account_fx_income_id: {'debit': 7.30, 'credit': 0.0, 'amount_currency': 0.0, 'currency_id': False}, }) def test_statement_eur_invoice_usd_transaction_eur(self): @@ -180,10 +185,104 @@ class TestReconciliation(TransactionCase): self.check_results(customer_move_lines, { self.account_euro_id: {'debit': 42.0, 'credit': 0.0, 'amount_currency': 50, 'currency_id': self.currency_swiss_id}, self.account_rcv_id: {'debit': 0.0, 'credit': 38.21, 'amount_currency': -50, 'currency_id': self.currency_swiss_id}, - self.account_rsa_id: {'debit': 0.0, 'credit': 3.79, 'amount_currency': 0.0, 'currency_id': False}, + self.account_fx_income_id: {'debit': 0.0, 'credit': 3.79, 'amount_currency': 0.0, 'currency_id': False}, }) self.check_results(supplier_move_lines, { self.account_euro_id: {'debit': 0.0, 'credit': 42.0, 'amount_currency': -50, 'currency_id': self.currency_swiss_id}, self.account_rcv_id: {'debit': 38.21, 'credit': 0.0, 'amount_currency': 50, 'currency_id': self.currency_swiss_id}, - self.account_rsa_id: {'debit': 3.79, 'credit': 0.0, 'amount_currency': 0.0, 'currency_id': False}, + self.account_fx_income_id: {'debit': 3.79, 'credit': 0.0, 'amount_currency': 0.0, 'currency_id': False}, }) + + def test_balanced_exchanges_gain_loss(self): + # The point of this test is to show that we handle correctly the gain/loss exchanges during reconciliations in foreign currencies. + # For instance, with a company set in EUR, and a USD rate set to 0.033, + # the reconciliation of an invoice of 2.00 USD (60.61 EUR) and a bank statement of two lines of 1.00 USD (30.30 EUR) + # will lead to an exchange loss, that should be handled correctly within the journal items. + cr, uid = self.cr, self.uid + # We update the currency rate of the currency USD in order to force the gain/loss exchanges in next steps + self.res_currency_rate_model.create(cr, uid, { + 'name': time.strftime('%Y-%m-%d') + ' 00:00:00', + 'currency_id': self.currency_usd_id, + 'rate': 0.033, + }) + # We create a customer invoice of 2.00 USD + invoice_id = self.account_invoice_model.create(cr, uid, { + 'partner_id': self.partner_agrolait_id, + 'currency_id': self.currency_usd_id, + 'name': 'Foreign invoice with exchange gain', + 'account_id': self.account_rcv_id, + 'type': 'out_invoice', + 'date_invoice': time.strftime('%Y-%m-%d'), + 'journal_id': self.bank_journal_usd_id, + 'invoice_line': [ + (0, 0, { + 'name': 'line that will lead to an exchange gain', + 'quantity': 1, + 'price_unit': 2, + }) + ] + }) + self.registry('account.invoice').signal_workflow(cr, uid, [invoice_id], 'invoice_open') + invoice = self.account_invoice_model.browse(cr, uid, invoice_id) + # We create a bank statement with two lines of 1.00 USD each. + bank_stmt_id = self.acc_bank_stmt_model.create(cr, uid, { + 'journal_id': self.bank_journal_usd_id, + 'date': time.strftime('%Y-%m-%d'), + 'line_ids': [ + (0, 0, { + 'name': 'half payment', + 'partner_id': self.partner_agrolait_id, + 'amount': 1.0, + 'date': time.strftime('%Y-%m-%d') + }), + (0, 0, { + 'name': 'second half payment', + 'partner_id': self.partner_agrolait_id, + 'amount': 1.0, + 'date': time.strftime('%Y-%m-%d') + }) + ] + }) + + statement = self.acc_bank_stmt_model.browse(cr, uid, bank_stmt_id) + + # We process the reconciliation of the invoice line with the two bank statement lines + line_id = None + for l in invoice.move_id.line_id: + if l.account_id.id == self.account_rcv_id: + line_id = l + break + for statement_line in statement.line_ids: + self.acc_bank_stmt_line_model.process_reconciliation(cr, uid, statement_line.id, [ + {'counterpart_move_line_id': line_id.id, 'credit': 1.0, 'debit': 0.0, 'name': line_id.name} + ]) + + # The invoice should be paid, as the payments totally cover its total + self.assertEquals(invoice.state, 'paid', 'The invoice should be paid by now') + reconcile = None + for payment in invoice.payment_ids: + reconcile = payment.reconcile_id + break + # The invoice should be reconciled (entirely, not a partial reconciliation) + self.assertTrue(reconcile, 'The invoice should be totally reconciled') + result = {} + exchange_loss_line = None + for line in reconcile.line_id: + res_account = result.setdefault(line.account_id, {'debit': 0.0, 'credit': 0.0, 'count': 0}) + res_account['debit'] = res_account['debit'] + line.debit + res_account['credit'] = res_account['credit'] + line.credit + res_account['count'] += 1 + if line.credit == 0.01: + exchange_loss_line = line + # We should be able to find a move line of 0.01 EUR on the Debtors account, being the cent we lost during the currency exchange + self.assertTrue(exchange_loss_line, 'There should be one move line of 0.01 EUR in credit') + # The journal items of the reconciliation should have their debit and credit total equal + # Besides, the total debit and total credit should be 60.61 EUR (2.00 USD) + self.assertEquals(sum([res['debit'] for res in result.values()]), 60.61) + self.assertEquals(sum([res['credit'] for res in result.values()]), 60.61) + counterpart_exchange_loss_line = None + for line in exchange_loss_line.move_id.line_id: + if line.account_id.id == self.account_fx_expense_id: + counterpart_exchange_loss_line = line + # We should be able to find a move line of 0.01 EUR on the Foreign Exchange Loss account + self.assertTrue(counterpart_exchange_loss_line, 'There should be one move line of 0.01 EUR on account "Foreign Exchange Loss"') diff --git a/addons/account_analytic_analysis/account_analytic_analysis.py b/addons/account_analytic_analysis/account_analytic_analysis.py index d3f27e25569..196508cc1ae 100644 --- a/addons/account_analytic_analysis/account_analytic_analysis.py +++ b/addons/account_analytic_analysis/account_analytic_analysis.py @@ -46,7 +46,7 @@ class account_analytic_invoice_line(osv.osv): _columns = { 'product_id': fields.many2one('product.product','Product',required=True), - 'analytic_account_id': fields.many2one('account.analytic.account', 'Analytic Account'), + 'analytic_account_id': fields.many2one('account.analytic.account', 'Analytic Account', ondelete='cascade'), 'name': fields.text('Description', required=True), 'quantity': fields.float('Quantity', required=True), 'uom_id': fields.many2one('product.uom', 'Unit of Measure',required=True), diff --git a/addons/account_asset/account_asset.py b/addons/account_asset/account_asset.py index d4030efd259..c093e86c922 100644 --- a/addons/account_asset/account_asset.py +++ b/addons/account_asset/account_asset.py @@ -355,8 +355,8 @@ class AccountAssetDepreciationLine(models.Model): current_currency = line.asset_id.currency_id amount = company_currency.compute(line.amount, current_currency) sign = (line.asset_id.category_id.journal_id.type == 'purchase' or line.asset_id.category_id.journal_id.type == 'sale' and 1) or -1 - asset_name = line.asset_id.name - reference = line.name + asset_name = "/" + reference = line.asset_id.name move_vals = { 'name': asset_name, 'date': depreciation_date, diff --git a/addons/account_followup/views/report_followup.xml b/addons/account_followup/views/report_followup.xml index 98f1e7be510..622b65ee754 100644 --- a/addons/account_followup/views/report_followup.xml +++ b/addons/account_followup/views/report_followup.xml @@ -9,7 +9,7 @@
-
diff --git a/addons/account_followup/wizard/account_followup_print.py b/addons/account_followup/wizard/account_followup_print.py index 0d544e89656..6c0693e263c 100644 --- a/addons/account_followup/wizard/account_followup_print.py +++ b/addons/account_followup/wizard/account_followup_print.py @@ -31,6 +31,13 @@ class account_followup_stat_by_partner(osv.osv): _description = "Follow-up Statistics by Partner" _rec_name = 'partner_id' _auto = False + + def _get_invoice_partner_id(self, cr, uid, ids, field_name, arg, context=None): + result = {} + for rec in self.browse(cr, uid, ids, context=context): + result[rec.id] = rec.partner_id.address_get(adr_pref=['invoice']).get('invoice', rec.partner_id.id) + return result + _columns = { 'partner_id': fields.many2one('res.partner', 'Partner', readonly=True), 'date_move':fields.date('First move', readonly=True), @@ -40,6 +47,7 @@ class account_followup_stat_by_partner(osv.osv): 'Max Follow Up Level', readonly=True, ondelete="cascade"), 'balance':fields.float('Balance', readonly=True), 'company_id': fields.many2one('res.company', 'Company', readonly=True), + 'invoice_partner_id': fields.function(_get_invoice_partner_id, type='many2one', relation='res.partner', string='Invoice Address') } _depends = { diff --git a/addons/mrp/stock.py b/addons/mrp/stock.py index 77e3b0d27b6..58fc0dad0f6 100644 --- a/addons/mrp/stock.py +++ b/addons/mrp/stock.py @@ -32,7 +32,7 @@ class StockMove(osv.osv): _inherit = 'stock.move' _columns = { - 'production_id': fields.many2one('mrp.production', 'Production Order for Produced Products', select=True, copy=False), + 'production_id': fields.many2one('mrp.production', 'Production Order for Produced Products', select=True), 'raw_material_production_id': fields.many2one('mrp.production', 'Production Order for Raw Materials', select=True), 'consumed_for': fields.many2one('stock.move', 'Consumed for', help='Technical field used to make the traceability of produced products'), } diff --git a/addons/mrp_repair/mrp_repair.py b/addons/mrp_repair/mrp_repair.py index f9bac5c373d..c64cde09afe 100644 --- a/addons/mrp_repair/mrp_repair.py +++ b/addons/mrp_repair/mrp_repair.py @@ -474,7 +474,6 @@ class mrp_repair(osv.osv): 'partner_id': repair.address_id and repair.address_id.id or False, 'location_id': move.location_id.id, 'location_dest_id': move.location_dest_id.id, - 'state': 'assigned', }) move_ids.append(move_id) repair_line_obj.write(cr, uid, [move.id], {'move_id': move_id, 'state': 'done'}, context=context) diff --git a/addons/purchase/stock.py b/addons/purchase/stock.py index 04ee3db1d40..e1d966e770a 100644 --- a/addons/purchase/stock.py +++ b/addons/purchase/stock.py @@ -94,10 +94,10 @@ class stock_move(osv.osv): return invoice_line_id def _get_master_data(self, cr, uid, move, company, context=None): - if move.purchase_line_id: + if context.get('inv_type') in ('in_invoice', 'in_refund') and move.purchase_line_id: purchase_order = move.purchase_line_id.order_id return purchase_order.partner_id, purchase_order.create_uid.id, purchase_order.currency_id.id - elif move.picking_id: + elif context.get('inv_type') in ('in_invoice', 'in_refund') and move.picking_id: # In case of an extra move, it is better to use the data from the original moves for purchase_move in move.picking_id.move_lines: if purchase_move.purchase_line_id: @@ -114,18 +114,26 @@ class stock_move(osv.osv): def _get_invoice_line_vals(self, cr, uid, move, partner, inv_type, context=None): res = super(stock_move, self)._get_invoice_line_vals(cr, uid, move, partner, inv_type, context=context) - if move.purchase_line_id: + if inv_type in ('in_invoice', 'in_refund') and move.purchase_line_id: purchase_line = move.purchase_line_id res['invoice_line_tax_id'] = [(6, 0, [x.id for x in purchase_line.taxes_id])] res['price_unit'] = purchase_line.price_unit return res - def _get_moves_taxes(self, cr, uid, moves, context=None): - is_extra_move, extra_move_tax = super(stock_move, self)._get_moves_taxes(cr, uid, moves, context=context) - for move in moves: - if move.purchase_line_id: - is_extra_move[move.id] = False - extra_move_tax[move.picking_id, move.product_id] = [(6, 0, [x.id for x in move.purchase_line_id.taxes_id])] + def _get_moves_taxes(self, cr, uid, moves, inv_type, context=None): + is_extra_move, extra_move_tax = super(stock_move, self)._get_moves_taxes(cr, uid, moves, inv_type, context=context) + if inv_type == 'in_invoice': + for move in moves: + if move.purchase_line_id: + is_extra_move[move.id] = False + extra_move_tax[move.picking_id, move.product_id] = [(6, 0, [x.id for x in move.purchase_line_id.taxes_id])] + elif move.product_id.product_tmpl_id.supplier_taxes_id: + mov_id = self.search(cr, uid, [('purchase_line_id', '!=', False), ('picking_id', '=', move.picking_id.id)], limit=1, context=context) + if mov_id: + mov = self.browse(cr, uid, mov_id[0], context=context) + fp = mov.purchase_line_id.order_id.fiscal_position + res = self.pool.get("account.invoice.line").product_id_change(cr, uid, [], move.product_id.id, None, partner_id=move.picking_id.partner_id.id, fposition_id=(fp and fp.id), type='in_invoice', context=context) + extra_move_tax[0, move.product_id] = [(6, 0, res['value']['invoice_line_tax_id'])] return (is_extra_move, extra_move_tax) diff --git a/addons/sale_stock/sale_stock.py b/addons/sale_stock/sale_stock.py index c849331d5e0..d2b689af20a 100644 --- a/addons/sale_stock/sale_stock.py +++ b/addons/sale_stock/sale_stock.py @@ -376,7 +376,7 @@ class stock_move(osv.osv): def _create_invoice_line_from_vals(self, cr, uid, move, invoice_line_vals, context=None): invoice_line_id = super(stock_move, self)._create_invoice_line_from_vals(cr, uid, move, invoice_line_vals, context=context) - if move.procurement_id and move.procurement_id.sale_line_id: + if context.get('inv_type') in ('out_invoice', 'out_refund') and move.procurement_id and move.procurement_id.sale_line_id: sale_line = move.procurement_id.sale_line_id self.pool.get('sale.order.line').write(cr, uid, [sale_line.id], { 'invoice_lines': [(4, invoice_line_id)] @@ -394,7 +394,7 @@ class stock_move(osv.osv): return invoice_line_id def _get_master_data(self, cr, uid, move, company, context=None): - if move.procurement_id and move.procurement_id.sale_line_id and move.procurement_id.sale_line_id.order_id.order_policy == 'picking': + if context.get('inv_type') in ('out_invoice', 'out_refund') and move.procurement_id and move.procurement_id.sale_line_id and move.procurement_id.sale_line_id.order_id.order_policy == 'picking': sale_order = move.procurement_id.sale_line_id.order_id return sale_order.partner_invoice_id, sale_order.user_id.id, sale_order.pricelist_id.currency_id.id elif move.picking_id.sale_id and context.get('inv_type') in ('out_invoice', 'out_refund'): @@ -421,12 +421,17 @@ class stock_move(osv.osv): res['price_unit'] = res['price_unit'] / uos_coeff return res - def _get_moves_taxes(self, cr, uid, moves, context=None): - is_extra_move, extra_move_tax = super(stock_move, self)._get_moves_taxes(cr, uid, moves, context=context) - for move in moves: - if move.procurement_id and move.procurement_id.sale_line_id: - is_extra_move[move.id] = False - extra_move_tax[move.picking_id, move.product_id] = [(6, 0, [x.id for x in move.procurement_id.sale_line_id.tax_id])] + def _get_moves_taxes(self, cr, uid, moves, inv_type, context=None): + is_extra_move, extra_move_tax = super(stock_move, self)._get_moves_taxes(cr, uid, moves, inv_type, context=context) + if inv_type == 'out_invoice': + for move in moves: + if move.procurement_id and move.procurement_id.sale_line_id: + is_extra_move[move.id] = False + extra_move_tax[move.picking_id, move.product_id] = [(6, 0, [x.id for x in move.procurement_id.sale_line_id.tax_id])] + elif move.picking_id.sale_id and move.product_id.product_tmpl_id.taxes_id: + fp = move.picking_id.sale_id.fiscal_position + res = self.pool.get("account.invoice.line").product_id_change(cr, uid, [], move.product_id.id, None, partner_id=move.picking_id.partner_id.id, fposition_id=(fp and fp.id), context=context) + extra_move_tax[0, move.product_id] = [(6, 0, res['value']['invoice_line_tax_id'])] return (is_extra_move, extra_move_tax) def _get_taxes(self, cr, uid, move, context=None): diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 8a502a10b78..addb4bd7c4e 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -1059,11 +1059,20 @@ class stock_picking(osv.osv): # If we encounter an UoM that is smaller than the default UoM or the one already chosen, use the new one instead. product_uom = {} # Determines UoM used in pack operations + location_dest_id = None + location_id = None for move in [x for x in picking.move_lines if x.state not in ('done', 'cancel')]: if not product_uom.get(move.product_id.id): product_uom[move.product_id.id] = move.product_id.uom_id if move.product_uom.id != move.product_id.uom_id.id and move.product_uom.factor > product_uom[move.product_id.id].factor: product_uom[move.product_id.id] = move.product_uom + if not move.scrapped: + if location_dest_id and move.location_dest_id.id != location_dest_id: + raise UserError(_('The destination location must be the same for all the moves of the picking.')) + location_dest_id = move.location_dest_id.id + if location_id and move.location_id.id != location_id: + raise UserError(_('The source location must be the same for all the moves of the picking.')) + location_id = move.location_id.id pack_obj = self.pool.get("stock.quant.package") quant_obj = self.pool.get("stock.quant") @@ -1175,7 +1184,7 @@ class stock_picking(osv.osv): picking_quants = [] #Calculate packages, reserved quants, qtys of this picking's moves for move in picking.move_lines: - if move.state not in ('assigned', 'confirmed'): + if move.state not in ('assigned', 'confirmed', 'waiting'): continue move_quants = move.reserved_quant_ids picking_quants += move_quants @@ -1345,6 +1354,8 @@ class stock_picking(osv.osv): #HALF-UP rounding as only rounding errors will be because of propagation of error from default UoM qty = uom_obj._compute_qty_obj(cr, uid, product.uom_id, remaining_qty, op.product_uom_id, rounding_method='HALF-UP') picking = op.picking_id + ref = product.default_code + name = '[' + ref + ']' + ' ' + product.name if ref else product.name res = { 'picking_id': picking.id, 'location_id': picking.location_id.id, @@ -1352,7 +1363,7 @@ class stock_picking(osv.osv): 'product_id': product.id, 'product_uom': uom_id, 'product_uom_qty': qty, - 'name': _('Extra Move: ') + product.name, + 'name': _('Extra Move: ') + name, 'state': 'draft', } return res @@ -1856,6 +1867,13 @@ class stock_move(osv.osv): def _default_destination_address(self, cr, uid, context=None): return False + def _default_group_id(self, cr, uid, context=None): + context = context or {} + if context.get('default_picking_id', False): + picking = self.pool.get('stock.picking').browse(cr, uid, context['default_picking_id'], context=context) + return picking.group_id.id + return False + _defaults = { 'location_id': _default_location_source, 'location_dest_id': _default_location_destination, @@ -1871,6 +1889,7 @@ class stock_move(osv.osv): 'procure_method': 'make_to_stock', 'propagate': True, 'partially_available': False, + 'group_id': _default_group_id, } def _check_uom(self, cr, uid, ids, context=None): diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml index 36de197aff8..0020b7d5bb7 100644 --- a/addons/stock/stock_view.xml +++ b/addons/stock/stock_view.xml @@ -1090,6 +1090,7 @@ +