From 14a109dc87a15db0617dc0acd36347f93065ce2b Mon Sep 17 00:00:00 2001 From: Raphael Ritter Date: Fri, 16 Jul 2021 16:21:21 +0200 Subject: [PATCH] [ADD] l10n_ch_payment_slip [ADD] l10n_ch_zip [ADD] l10n_ch_bank_statement_import_postfinance --- .../COPYRIGHT | 17 + .../LICENSE | 663 + .../README.rst | 54 + .../__init__.py | 2 + .../__manifest__.py | 27 + ...n_ch_bank_statement_import_postfinance.pot | 50 + .../models/__init__.py | 2 + .../models/account_bank_statement_line.py | 45 + .../models/postfinance_file_parser.py | 161 + .../static/description/icon.png | Bin 0 -> 8885 bytes .../js/account_statement_reconciliation.js | 19 + .../src/xml/l10n_ch_statement_line_layout.xml | 15 + .../test_files/demo_pf_ch.tar.gz | Bin 0 -> 15494 bytes .../tests/__init__.py | 1 + .../tests/test_postfinance_xml.py | 141 + ...bank_statement_import_postfinance_view.xml | 14 + .../l10n_ch_account_statement_base_import.xml | 10 + .../views/statement_line_view.xml | 62 + .../wizards/__init__.py | 1 + ...count_bank_statement_import_postfinance.py | 44 + l10n_ch_payment_slip/COPYRIGHT | 19 + l10n_ch_payment_slip/LICENSE | 663 + l10n_ch_payment_slip/README.rst | 79 + l10n_ch_payment_slip/__init__.py | 4 + l10n_ch_payment_slip/__manifest__.py | 36 + l10n_ch_payment_slip/controllers/__init__.py | 1 + l10n_ch_payment_slip/controllers/web.py | 34 + l10n_ch_payment_slip/i18n/de.po | 543 + l10n_ch_payment_slip/i18n/fr.po | 521 + l10n_ch_payment_slip/i18n/it.po | 505 + .../i18n/l10n_ch_payment_slip.pot | 436 + l10n_ch_payment_slip/models/__init__.py | 5 + l10n_ch_payment_slip/models/bank.py | 18 + l10n_ch_payment_slip/models/company.py | 90 + l10n_ch_payment_slip/models/invoice.py | 194 + l10n_ch_payment_slip/models/payment_slip.py | 930 + .../models/res_config_settings.py | 48 + l10n_ch_payment_slip/report/__init__.py | 2 + l10n_ch_payment_slip/report/ir_action.py | 172 + l10n_ch_payment_slip/report/report.py | 7 + .../report/report_declaration.xml | 32 + l10n_ch_payment_slip/sample/README | 12 + .../sample/zvr_besrtechdok_fr.pdf | Bin 0 -> 506817 bytes .../security/ir.model.access.csv | 3 + .../static/description/icon.png | Bin 0 -> 13353 bytes .../static/src/font/ocrbb.ttf | Bin 0 -> 40312 bytes l10n_ch_payment_slip/static/src/img/a4.png | Bin 0 -> 8302 bytes l10n_ch_payment_slip/static/src/img/a4bvr.png | Bin 0 -> 147464 bytes l10n_ch_payment_slip/static/src/img/isr.jpg | Bin 0 -> 84008 bytes l10n_ch_payment_slip/static/src/img/isr.png | Bin 0 -> 2152910 bytes l10n_ch_payment_slip/static/src/img/white.png | Bin 0 -> 2151546 bytes .../static/src/js/qwebactionmanager.js | 37 + l10n_ch_payment_slip/tests/__init__.py | 1 + .../tests/test_payment_slip.py | 359 + .../views/account_invoice.xml | 66 + l10n_ch_payment_slip/views/bank.xml | 20 + .../views/report_xml_templates.xml | 9 + .../views/res_config_settings_views.xml | 78 + l10n_ch_payment_slip/wizard/__init__.py | 1 + .../wizard/isr_batch_print.py | 39 + .../wizard/isr_batch_print.xml | 34 + l10n_ch_qr_bill/COPYRIGHT | 16 + l10n_ch_qr_bill/LICENSE | 663 + l10n_ch_qr_bill/README.rst | 30 + l10n_ch_qr_bill/__init__.py | 2 + l10n_ch_qr_bill/__manifest__.py | 23 + l10n_ch_qr_bill/controllers/__init__.py | 1 + l10n_ch_qr_bill/controllers/main.py | 43 + l10n_ch_qr_bill/data/paperformat.xml | 19 + l10n_ch_qr_bill/i18n/de.po | 222 + l10n_ch_qr_bill/i18n/fr.po | 223 + l10n_ch_qr_bill/i18n/it.po | 218 + l10n_ch_qr_bill/i18n/l10n_ch_qr_bill.pot | 190 + l10n_ch_qr_bill/models/__init__.py | 3 + l10n_ch_qr_bill/models/account_invoice.py | 343 + l10n_ch_qr_bill/models/res_bank.py | 73 + l10n_ch_qr_bill/models/swissqr_report.py | 29 + l10n_ch_qr_bill/report/swissqr_report.xml | 166 + l10n_ch_qr_bill/security/ir.model.access.csv | 2 + l10n_ch_qr_bill/static/description/icon.png | Bin 0 -> 10448 bytes .../static/src/css/report_swissqr.css | 155 + .../static/src/img/CH-Cross_7mm.png | Bin 0 -> 14703 bytes l10n_ch_qr_bill/tests/__init__.py | 1 + l10n_ch_qr_bill/tests/test_swissqr.py | 166 + .../views/account_invoice_view.xml | 49 + l10n_ch_qr_bill/views/res_bank.xml | 13 + l10n_ch_zip/COPYRIGHT | 18 + l10n_ch_zip/LICENSE | 663 + l10n_ch_zip/README.rst | 64 + l10n_ch_zip/__init__.py | 4 + l10n_ch_zip/__manifest__.py | 27 + l10n_ch_zip/data/res.city.csv | 5029 +++ l10n_ch_zip/data/res.city.zip.csv | 5323 ++++ l10n_ch_zip/hooks.py | 20 + l10n_ch_zip/i18n/de.po | 25272 ++++++++++++++++ l10n_ch_zip/i18n/fr.po | 25259 +++++++++++++++ l10n_ch_zip/i18n/it.po | 25257 +++++++++++++++ l10n_ch_zip/i18n/l10n_ch_zip.pot | 25242 +++++++++++++++ l10n_ch_zip/models/__init__.py | 1 + l10n_ch_zip/models/city_zip.py | 73 + l10n_ch_zip/static/description/icon.png | Bin 0 -> 19295 bytes l10n_ch_zip/static/description/index.html | 451 + 102 files changed, 121679 insertions(+) create mode 100644 l10n_ch_bank_statement_import_postfinance/COPYRIGHT create mode 100644 l10n_ch_bank_statement_import_postfinance/LICENSE create mode 100644 l10n_ch_bank_statement_import_postfinance/README.rst create mode 100644 l10n_ch_bank_statement_import_postfinance/__init__.py create mode 100644 l10n_ch_bank_statement_import_postfinance/__manifest__.py create mode 100644 l10n_ch_bank_statement_import_postfinance/i18n/l10n_ch_bank_statement_import_postfinance.pot create mode 100644 l10n_ch_bank_statement_import_postfinance/models/__init__.py create mode 100644 l10n_ch_bank_statement_import_postfinance/models/account_bank_statement_line.py create mode 100644 l10n_ch_bank_statement_import_postfinance/models/postfinance_file_parser.py create mode 100644 l10n_ch_bank_statement_import_postfinance/static/description/icon.png create mode 100644 l10n_ch_bank_statement_import_postfinance/static/src/js/account_statement_reconciliation.js create mode 100644 l10n_ch_bank_statement_import_postfinance/static/src/xml/l10n_ch_statement_line_layout.xml create mode 100644 l10n_ch_bank_statement_import_postfinance/test_files/demo_pf_ch.tar.gz create mode 100644 l10n_ch_bank_statement_import_postfinance/tests/__init__.py create mode 100644 l10n_ch_bank_statement_import_postfinance/tests/test_postfinance_xml.py create mode 100644 l10n_ch_bank_statement_import_postfinance/views/account_bank_statement_import_postfinance_view.xml create mode 100644 l10n_ch_bank_statement_import_postfinance/views/l10n_ch_account_statement_base_import.xml create mode 100644 l10n_ch_bank_statement_import_postfinance/views/statement_line_view.xml create mode 100644 l10n_ch_bank_statement_import_postfinance/wizards/__init__.py create mode 100644 l10n_ch_bank_statement_import_postfinance/wizards/account_bank_statement_import_postfinance.py create mode 100644 l10n_ch_payment_slip/COPYRIGHT create mode 100644 l10n_ch_payment_slip/LICENSE create mode 100644 l10n_ch_payment_slip/README.rst create mode 100644 l10n_ch_payment_slip/__init__.py create mode 100644 l10n_ch_payment_slip/__manifest__.py create mode 100644 l10n_ch_payment_slip/controllers/__init__.py create mode 100644 l10n_ch_payment_slip/controllers/web.py create mode 100644 l10n_ch_payment_slip/i18n/de.po create mode 100644 l10n_ch_payment_slip/i18n/fr.po create mode 100644 l10n_ch_payment_slip/i18n/it.po create mode 100644 l10n_ch_payment_slip/i18n/l10n_ch_payment_slip.pot create mode 100644 l10n_ch_payment_slip/models/__init__.py create mode 100644 l10n_ch_payment_slip/models/bank.py create mode 100644 l10n_ch_payment_slip/models/company.py create mode 100644 l10n_ch_payment_slip/models/invoice.py create mode 100644 l10n_ch_payment_slip/models/payment_slip.py create mode 100644 l10n_ch_payment_slip/models/res_config_settings.py create mode 100644 l10n_ch_payment_slip/report/__init__.py create mode 100644 l10n_ch_payment_slip/report/ir_action.py create mode 100644 l10n_ch_payment_slip/report/report.py create mode 100644 l10n_ch_payment_slip/report/report_declaration.xml create mode 100644 l10n_ch_payment_slip/sample/README create mode 100644 l10n_ch_payment_slip/sample/zvr_besrtechdok_fr.pdf create mode 100644 l10n_ch_payment_slip/security/ir.model.access.csv create mode 100644 l10n_ch_payment_slip/static/description/icon.png create mode 100644 l10n_ch_payment_slip/static/src/font/ocrbb.ttf create mode 100644 l10n_ch_payment_slip/static/src/img/a4.png create mode 100644 l10n_ch_payment_slip/static/src/img/a4bvr.png create mode 100644 l10n_ch_payment_slip/static/src/img/isr.jpg create mode 100644 l10n_ch_payment_slip/static/src/img/isr.png create mode 100644 l10n_ch_payment_slip/static/src/img/white.png create mode 100644 l10n_ch_payment_slip/static/src/js/qwebactionmanager.js create mode 100644 l10n_ch_payment_slip/tests/__init__.py create mode 100644 l10n_ch_payment_slip/tests/test_payment_slip.py create mode 100644 l10n_ch_payment_slip/views/account_invoice.xml create mode 100644 l10n_ch_payment_slip/views/bank.xml create mode 100644 l10n_ch_payment_slip/views/report_xml_templates.xml create mode 100644 l10n_ch_payment_slip/views/res_config_settings_views.xml create mode 100644 l10n_ch_payment_slip/wizard/__init__.py create mode 100644 l10n_ch_payment_slip/wizard/isr_batch_print.py create mode 100644 l10n_ch_payment_slip/wizard/isr_batch_print.xml create mode 100644 l10n_ch_qr_bill/COPYRIGHT create mode 100644 l10n_ch_qr_bill/LICENSE create mode 100644 l10n_ch_qr_bill/README.rst create mode 100644 l10n_ch_qr_bill/__init__.py create mode 100644 l10n_ch_qr_bill/__manifest__.py create mode 100644 l10n_ch_qr_bill/controllers/__init__.py create mode 100644 l10n_ch_qr_bill/controllers/main.py create mode 100644 l10n_ch_qr_bill/data/paperformat.xml create mode 100644 l10n_ch_qr_bill/i18n/de.po create mode 100644 l10n_ch_qr_bill/i18n/fr.po create mode 100644 l10n_ch_qr_bill/i18n/it.po create mode 100644 l10n_ch_qr_bill/i18n/l10n_ch_qr_bill.pot create mode 100644 l10n_ch_qr_bill/models/__init__.py create mode 100644 l10n_ch_qr_bill/models/account_invoice.py create mode 100644 l10n_ch_qr_bill/models/res_bank.py create mode 100644 l10n_ch_qr_bill/models/swissqr_report.py create mode 100644 l10n_ch_qr_bill/report/swissqr_report.xml create mode 100644 l10n_ch_qr_bill/security/ir.model.access.csv create mode 100644 l10n_ch_qr_bill/static/description/icon.png create mode 100644 l10n_ch_qr_bill/static/src/css/report_swissqr.css create mode 100644 l10n_ch_qr_bill/static/src/img/CH-Cross_7mm.png create mode 100644 l10n_ch_qr_bill/tests/__init__.py create mode 100644 l10n_ch_qr_bill/tests/test_swissqr.py create mode 100644 l10n_ch_qr_bill/views/account_invoice_view.xml create mode 100644 l10n_ch_qr_bill/views/res_bank.xml create mode 100644 l10n_ch_zip/COPYRIGHT create mode 100644 l10n_ch_zip/LICENSE create mode 100644 l10n_ch_zip/README.rst create mode 100644 l10n_ch_zip/__init__.py create mode 100644 l10n_ch_zip/__manifest__.py create mode 100644 l10n_ch_zip/data/res.city.csv create mode 100644 l10n_ch_zip/data/res.city.zip.csv create mode 100644 l10n_ch_zip/hooks.py create mode 100644 l10n_ch_zip/i18n/de.po create mode 100644 l10n_ch_zip/i18n/fr.po create mode 100644 l10n_ch_zip/i18n/it.po create mode 100644 l10n_ch_zip/i18n/l10n_ch_zip.pot create mode 100644 l10n_ch_zip/models/__init__.py create mode 100644 l10n_ch_zip/models/city_zip.py create mode 100644 l10n_ch_zip/static/description/icon.png create mode 100644 l10n_ch_zip/static/description/index.html diff --git a/l10n_ch_bank_statement_import_postfinance/COPYRIGHT b/l10n_ch_bank_statement_import_postfinance/COPYRIGHT new file mode 100644 index 0000000..5e8a410 --- /dev/null +++ b/l10n_ch_bank_statement_import_postfinance/COPYRIGHT @@ -0,0 +1,17 @@ +Most of the files are + + /* Copyright 2014-2017 Compassion CH + Copyright 2015 Nicolas Bessi Camptocamp SA + Copyright 2017 Emanuel Cino + Copyright 2017-2019 Compassion CH + Copyright 2018 Flectra Community + +Many files also contain contributions from third +parties. In this case the original copyright of +the contributions can be traced through the +history of the source version control system. + +When that is not the case, the files contain a prominent +notice stating the original copyright and applicable +license, or come with their own dedicated COPYRIGHT +and/or LICENSE file. \ No newline at end of file diff --git a/l10n_ch_bank_statement_import_postfinance/LICENSE b/l10n_ch_bank_statement_import_postfinance/LICENSE new file mode 100644 index 0000000..3939cd9 --- /dev/null +++ b/l10n_ch_bank_statement_import_postfinance/LICENSE @@ -0,0 +1,663 @@ +For copyright information, please see the COPYRIGHT file. + +GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. \ No newline at end of file diff --git a/l10n_ch_bank_statement_import_postfinance/README.rst b/l10n_ch_bank_statement_import_postfinance/README.rst new file mode 100644 index 0000000..04175a9 --- /dev/null +++ b/l10n_ch_bank_statement_import_postfinance/README.rst @@ -0,0 +1,54 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +================================== +Import Postfinance bank statements +================================== + +This module allows you to import Postfinance .tar.gz bank statements +including .xml statements and pictures of the ESR payment slips. +It currently supports the following file formats : + +* XML format from Postfinance S.A. + +Warning : this module requires the python library 'xlrd'. + +Installation +============ + +To install this module, you need to add the statement import module into your +addons path, because it's based on the CAMT import module. +https://github.com/OCA/bank-statement-import + +Configuration +============= + +To configure this module, you need to ensure you have a bank account related to +your company that corresponds to imported statement. + + +If the statement is not in the same currency that company please ensure that +both journal and account have the currency (or secondary currency) properly +set to statement currency. + +Usage +===== + +To use this module, you need to: + +#. Go to *Accounting* dashboard. +#. Click on *Import statement* from any of the bank journals. +#. Select a .tar.gz file from Postfinance. +#. Press *Import*. + +Credits +======= + +Contributors +------------ + +* Nicolas Bessi +* Steve Ferry +* Emanuel Cino +* Emmanuel Mathier \ No newline at end of file diff --git a/l10n_ch_bank_statement_import_postfinance/__init__.py b/l10n_ch_bank_statement_import_postfinance/__init__.py new file mode 100644 index 0000000..aee8895 --- /dev/null +++ b/l10n_ch_bank_statement_import_postfinance/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import wizards diff --git a/l10n_ch_bank_statement_import_postfinance/__manifest__.py b/l10n_ch_bank_statement_import_postfinance/__manifest__.py new file mode 100644 index 0000000..88425d5 --- /dev/null +++ b/l10n_ch_bank_statement_import_postfinance/__manifest__.py @@ -0,0 +1,27 @@ +# Copyright 2015 Nicolas Bessi Camptocamp SA +# Copyright 2017-2019 Compassion CH +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{'name': "Swiss bank statements import", + 'version': '2.0.0.0.0', + 'author': "Compassion CH, Camptocamp, Odoo Community Association (OCA), 2BIT GmbH", + 'category': 'Finance', + 'complexity': 'normal', + 'depends': [ + 'account_bank_statement_import_camt_oca', + ], + 'external_dependencies': { + 'python': ['xlrd'], + }, + 'website': 'https://gitlab.com/flectra-community/flectra', + 'data': [ + 'views/statement_line_view.xml', + 'views/l10n_ch_account_statement_base_import.xml', + 'views/account_bank_statement_import_postfinance_view.xml', + ], + 'qweb': ['static/src/xml/l10n_ch_statement_line_layout.xml'], + 'test': [], + 'installable': True, + 'images': [], + 'auto_install': False, + 'license': 'AGPL-3'} diff --git a/l10n_ch_bank_statement_import_postfinance/i18n/l10n_ch_bank_statement_import_postfinance.pot b/l10n_ch_bank_statement_import_postfinance/i18n/l10n_ch_bank_statement_import_postfinance.pot new file mode 100644 index 0000000..fc9bbf4 --- /dev/null +++ b/l10n_ch_bank_statement_import_postfinance/i18n/l10n_ch_bank_statement_import_postfinance.pot @@ -0,0 +1,50 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * l10n_ch_bank_statement_import_postfinance +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: l10n_ch_bank_statement_import_postfinance +#: model:ir.model,name:l10n_ch_bank_statement_import_postfinance.model_account_bank_statement_line +msgid "Bank Statement Line" +msgstr "" + +#. module: l10n_ch_bank_statement_import_postfinance +#: model:ir.model.fields,field_description:l10n_ch_bank_statement_import_postfinance.field_account_bank_statement_line_datas +msgid "File Content" +msgstr "" + +#. module: l10n_ch_bank_statement_import_postfinance +#: model:ir.model.fields,field_description:l10n_ch_bank_statement_import_postfinance.field_account_bank_statement_line_file_ref +msgid "File Ref" +msgstr "" + +#. module: l10n_ch_bank_statement_import_postfinance +#: model:ir.model,name:l10n_ch_bank_statement_import_postfinance.model_account_bank_statement_import +msgid "Import Bank Statement" +msgstr "" + +#. module: l10n_ch_bank_statement_import_postfinance +#: model:ir.ui.view,arch_db:l10n_ch_bank_statement_import_postfinance.account_bank_statement_import_view +msgid "Postfinance Format (.xml, .tar.gz)" +msgstr "" + +#. module: l10n_ch_bank_statement_import_postfinance +#: model:ir.model.fields,field_description:l10n_ch_bank_statement_import_postfinance.field_account_bank_statement_line_related_file +msgid "Related file" +msgstr "" + +#. module: l10n_ch_bank_statement_import_postfinance +#: model:ir.model,name:l10n_ch_bank_statement_import_postfinance.model_account_bank_statement_import_camt_parser +msgid "account.bank.statement.import.camt.parser" +msgstr "" + diff --git a/l10n_ch_bank_statement_import_postfinance/models/__init__.py b/l10n_ch_bank_statement_import_postfinance/models/__init__.py new file mode 100644 index 0000000..72cfbe2 --- /dev/null +++ b/l10n_ch_bank_statement_import_postfinance/models/__init__.py @@ -0,0 +1,2 @@ +from . import postfinance_file_parser +from . import account_bank_statement_line diff --git a/l10n_ch_bank_statement_import_postfinance/models/account_bank_statement_line.py b/l10n_ch_bank_statement_import_postfinance/models/account_bank_statement_line.py new file mode 100644 index 0000000..c83aa98 --- /dev/null +++ b/l10n_ch_bank_statement_import_postfinance/models/account_bank_statement_line.py @@ -0,0 +1,45 @@ +# Copyright 2015 Nicolas Bessi Camptocamp SA +# Copyright 2017-2019 Compassion CH +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from flectra import models, api, fields + + +class AccountBankStatementLine(models.Model): + _inherit = 'account.bank.statement.line' + + related_file = fields.Many2one( + comodel_name='ir.attachment', + string='Related file', + readonly=True + ) + datas = fields.Binary(related='related_file.datas') + file_ref = fields.Char() + + #@api.multi + def get_statement_line_for_reconciliation_widget(self): + data = super(AccountBankStatementLine, + self).get_statement_line_for_reconciliation_widget() + if self.related_file.datas: + related_file = self.related_file + image = "data:png;base64," + related_file.datas.decode("utf-8") + data['img_src'] = ['src', image] + data['modal_id'] = ['id', 'img' + str(related_file.id)] + data['data_target'] = [ + 'data-target', '#img' + str(related_file.id)] + return data + + #@api.multi + def click_icon(self): + view_id = self.env.ref( + 'l10n_ch_bank_statement_import_postfinance.' + 'attachement_form_postfinance879').id + return { + 'type': 'ir.actions.act_window', + 'name': 'Attachment', + 'view_type': 'form', + 'view_mode': 'form', + 'res_model': 'ir.attachment', + 'view_id': view_id, + 'res_id': self.related_file.id, + 'target': 'new', + } diff --git a/l10n_ch_bank_statement_import_postfinance/models/postfinance_file_parser.py b/l10n_ch_bank_statement_import_postfinance/models/postfinance_file_parser.py new file mode 100644 index 0000000..295d1db --- /dev/null +++ b/l10n_ch_bank_statement_import_postfinance/models/postfinance_file_parser.py @@ -0,0 +1,161 @@ +# Copyright 2015 Nicolas Bessi Camptocamp SA +# Copyright 2017-2019 Compassion CH +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import logging +from PIL import Image +from os.path import splitext +from tarfile import TarFile, TarError +from lxml import etree +from xml.etree import ElementTree +from io import BytesIO, StringIO +from base64 import b64encode + +from flectra import models, fields + +_logger = logging.getLogger(__name__) + + +class XMLPFParser(models.AbstractModel): + """ + Parser for XML Postfinance Statements (can be wrapped in a tar.gz file) + """ + _inherit = 'account.bank.statement.import.camt.parser' + #tar_source = fields.Text(string = "Tar source") + #is_tar = fields.Boolean() + + def parse(self, data_file): + """ + Handle Postfinance images of payment slips. + """ + self._check_postfinance_attachments(data_file) + + currency, account_number, statements = super(XMLPFParser, self).parse( + self.data_file) + + if statements and getattr(self, 'attachments', False): + statements[0]['attachments'] = self._parse_attachments() + + return currency, account_number, statements + + def parse_transaction_details(self, ns, node, transaction): + """Add file_reference to find attached image""" + # add file_ref to link image to bank statement line + self.add_value_from_node( + ns, node, './ns:Refs//ns:Prtry/ns:Ref', transaction, 'file_ref') + super(XMLPFParser, self).parse_transaction_details( + ns, node, transaction) + + def parse_statement(self, ns, node): + """ + Find currency if not found with base parser + """ + result = super(XMLPFParser, self).parse_statement(ns, node) + if not result.get('currency'): + currency_node = node.xpath( + '//ns:Bal[1]/ns:Amt/@Ccy', namespaces={'ns': ns}) + if currency_node and len(currency_node) == 1: + result['currency'] = currency_node[0] + return result + + def _check_postfinance_attachments(self, data_file): + """ + Initialize parser and check that data_file can be parsed. + :param data_file: file data + """ + self.tar_source = data_file + self.data_file = self._get_content_from_stream() + if self.is_tar: + self.attachments = self._get_attachments_from_stream(data_file) + + def _get_content_from_stream(self): + print(" RUK "*25,self.tar_source) + """Source file can be a raw or tar file. We try to guess the + file type and return valid file content + + :return: uncompressed file content + :rtype: string + """ + # https://hg.python.org/cpython/file/6969bac411fa/Lib/tarfile.py#l2605 + self.is_tar = False + if isinstance(self.tar_source, str): + try: + # If raw string + ElementTree.fromstring(self.tar_source) + return self.tar_source + except ElementTree.ParseError: + pf_file = StringIO(self.tar_source) + else: + pf_file = BytesIO(self.tar_source) + try: + pf_file.seek(0) + with TarFile.open(fileobj=pf_file, mode="r:gz") as tar_file: + xmls = [tar_content + for tar_content in tar_file.getnames() + if tar_content.endswith('.xml')] + self.is_tar = True + self.file_name = splitext(xmls[0])[0] + return tar_file.extractfile(xmls[0]).read() + except TarError: + return self.tar_source + + def _get_attachments_from_stream(self, data_file): + """Retrieve attachment from tar file. + Return a dict containing all attachments ready to be saved + in Flectra. + + The key is the name of file without extension + The value the PNG content encoded in base64 + + :param data_file: raw statement file sent to flectra (not in b64) + :type data_file: basestring subclass + + :return: Return a dict containing all attachments ready + to be saved in Flectra. + """ + pf_file = BytesIO(data_file) + pf_file.seek(0) + try: + attachments = {} + tar_file = TarFile.open(fileobj=pf_file, mode="r:gz") + accepted_formats = ['.png', '.jpeg', '.jpg', '.tiff'] + for file_name in tar_file.getnames(): + if True in [file_name.endswith(f) for f in accepted_formats]: + key = splitext(file_name)[0] + img_data = tar_file.extractfile(file_name).read() + if file_name.endswith('.tiff'): + # Convert string containing data to tiff image + image = Image.open(BytesIO(img_data)) + + # Convert to png for viewing the image in Flectra + with BytesIO() as png_image: + image.save(png_image, format='PNG') + img_data = png_image.getvalue() + attachments[key] = b64encode(img_data) + return attachments + except TarError: + return {} + + def _parse_attachments(self): + """Parse file statement to get wich attachment to use + :return: a list of attachment tuple (name, content) + :rtype: list + """ + attachments = [('Statement File', b64encode(self.tar_source))] + if self.is_tar: + # Extract XML tree + try: + tree = etree.fromstring( + self.data_file, parser=etree.XMLParser(recover=True)) + except etree.XMLSyntaxError: + return attachments + ns = tree.tag[1:tree.tag.index("}")] # namespace + transaction_nodes = tree.xpath( + '//ns:Stmt//ns:Prtry/ns:Ref/text()', + namespaces={'ns': ns}) + for transaction in transaction_nodes: + att_name = self.file_name + '-' + transaction[:23] + att = self.attachments.get(att_name) + if att: + attachments.append((transaction, att)) + return attachments diff --git a/l10n_ch_bank_statement_import_postfinance/static/description/icon.png b/l10n_ch_bank_statement_import_postfinance/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..5175c19c7341c4dca677dcd4dcebf759ae12bebb GIT binary patch literal 8885 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') + .appendTo(this.$('thead .cell_info_popover')) + .attr("data-content", qweb.render('bank_statement_reconciliation_line_image', {'state': this._initialState})); + return this._super(); + }, + }); +}); diff --git a/l10n_ch_bank_statement_import_postfinance/static/src/xml/l10n_ch_statement_line_layout.xml b/l10n_ch_bank_statement_import_postfinance/static/src/xml/l10n_ch_statement_line_layout.xml new file mode 100644 index 0000000..003497d --- /dev/null +++ b/l10n_ch_bank_statement_import_postfinance/static/src/xml/l10n_ch_statement_line_layout.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/l10n_ch_bank_statement_import_postfinance/test_files/demo_pf_ch.tar.gz b/l10n_ch_bank_statement_import_postfinance/test_files/demo_pf_ch.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..700bd0847ca6577b70340fd369906840a7dca8ee GIT binary patch literal 15494 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 + + + +""" + self.parser._check_postfinance_attachments(raw) + self.assertEqual(self.parser.data_file, raw) + + def test_attachments_detection(self): + """Test attachments detection""" + self.parser._check_postfinance_attachments(self.data_file) + self.assertIsNotNone(self.parser.attachments) + + def test_parse(self): + """Test file is correctly parsed""" + currency_code, account_number, statements = self.parser.parse( + self.data_file) + self.assertEqual('CH0309000000250090342', account_number) + self.assertEqual('CHF', currency_code) + self.assertIsInstance(statements, list) + self.assertEqual(len(statements), 1) + self.assertTrue(all(isinstance(x, dict) for x in statements)) + statement = statements[0] + self.assertTrue( + all(isinstance(x, dict)for x in statement['transactions'])) + self.assertEqual(559026015.20, statement['balance_start']) + self.assertEqual(559048788.30, statement['balance_end_real']) + self.assertEqual(9, len(statement['transactions'])) + first_transaction = { + 'file_ref': '20160414001203000300003', + 'amount': 50.0, + 'date': '2017-03-30', + 'ref': 'CLXPMZW000000004' + } + parsed_transaction = statement['transactions'][0] + self.assertDictContainsSubset(first_transaction, parsed_transaction) + + def test_attachement_extraction(self): + """Test if scan are extracted correctly""" + attachments = self.parser.parse(self.data_file)[2][0]['attachments'] + self.assertEqual( + set(['Statement File', + '20160414001203000300003', '20160414001203000300004', + '20160414001203000300005', '20160414001203000300006']), + set([a[0] for a in attachments]) + ) + + +class PostFinanceImportTest(common.TransactionCase): + + def setUp(self): + super(PostFinanceImportTest, self).setUp() + bank = self.env['res.partner.bank'].create({ + 'acc_number': 'CH0309000000250090342', + 'partner_id': self.env.ref('base.main_partner').id, + 'company_id': self.env.ref('base.main_company').id, + 'bank_id': self.env.ref('base.res_bank_1').id, + }) + self.env['account.journal'].create({ + 'name': 'Bank Journal - (test postfinance)', + 'code': 'TBNKPFNC', + 'type': 'bank', + 'bank_account_id': bank.id, + }) + self.company_a = self.env.ref('base.main_company') + currency = self.env.ref('base.CHF') + currency.active = True + self.company_a.write( + {'currency_id': currency.id} + ) + + def test_postfinance_xml_import(self): + """Test if postfinance statement is correct""" + action = self.env['account.bank.statement.import'].create({ + 'data_file': base64.b64encode(get_file_content( + 'demo_pf_ch.tar.gz')), + }).import_file() + statements = self.env['account.bank.statement'].browse( + action['context'].get('statement_ids') + ) + self.assertEqual(len(statements), 1) + self.assertEqual(559026015.20, statements.balance_start) + self.assertEqual(559048788.30, statements.balance_end_real) + self.assertEqual(9, len(statements.line_ids)) + self.assertTrue(statements.journal_id) + self.assertEqual(4, len(statements.mapped('line_ids.related_file'))) + st_line = statements.line_ids[0] + # Read common infos of first line + self.assertEqual(st_line.date, "2017-03-31") + self.assertEqual(st_line.amount, 500.0) + self.assertEqual(st_line.name, "VIREMENT BENEFICE") + + # Test image is in reconcile view + lines_with_attach = statements.mapped('line_ids').filtered( + 'related_file') + img_data_key = ['img_src', 'modal_id', 'data_target'] + for line in lines_with_attach: + data = line.get_statement_line_for_reconciliation_widget() + for key in img_data_key: + self.assertIn(key, data.keys()) + + # Test click icon returns an action + self.assertIsInstance(lines_with_attach[0].click_icon(), dict) diff --git a/l10n_ch_bank_statement_import_postfinance/views/account_bank_statement_import_postfinance_view.xml b/l10n_ch_bank_statement_import_postfinance/views/account_bank_statement_import_postfinance_view.xml new file mode 100644 index 0000000..7d633a4 --- /dev/null +++ b/l10n_ch_bank_statement_import_postfinance/views/account_bank_statement_import_postfinance_view.xml @@ -0,0 +1,14 @@ + + + + + account.bank.statement.import + + + +
  • Postfinance Format (.xml, .tar.gz)
  • +
    +
    +
    + +
    diff --git a/l10n_ch_bank_statement_import_postfinance/views/l10n_ch_account_statement_base_import.xml b/l10n_ch_bank_statement_import_postfinance/views/l10n_ch_account_statement_base_import.xml new file mode 100644 index 0000000..d4e8486 --- /dev/null +++ b/l10n_ch_bank_statement_import_postfinance/views/l10n_ch_account_statement_base_import.xml @@ -0,0 +1,10 @@ + + + + + + diff --git a/l10n_ch_bank_statement_import_postfinance/views/statement_line_view.xml b/l10n_ch_bank_statement_import_postfinance/views/statement_line_view.xml new file mode 100644 index 0000000..29404dd --- /dev/null +++ b/l10n_ch_bank_statement_import_postfinance/views/statement_line_view.xml @@ -0,0 +1,62 @@ + + + + account_statement_l10n_ch.view_form + account.bank.statement + + + form + + + + +