commit 0b545ea47e97c6cd46040a2b52d1f333022362fd Author: data Date: Tue Feb 3 14:47:27 2026 +0100 Steuermodul erstellt diff --git a/COPYING b/COPYING new file mode 100755 index 0000000..94a0453 --- /dev/null +++ b/COPYING @@ -0,0 +1,621 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 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 General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is 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. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + 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. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + 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 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. Use with the GNU Affero General Public License. + + 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 Affero 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 special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 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 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 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 diff --git a/ChangeLog.md b/ChangeLog.md new file mode 100755 index 0000000..5c7443f --- /dev/null +++ b/ChangeLog.md @@ -0,0 +1,5 @@ +# CHANGELOG MODULE STEUER FOR [DOLIBARR ERP CRM](https://www.dolibarr.org) + +## 1.0 + +Initial version diff --git a/README.md b/README.md new file mode 100755 index 0000000..2af36db --- /dev/null +++ b/README.md @@ -0,0 +1,96 @@ +# STEUER FOR [DOLIBARR ERP & CRM](https://www.dolibarr.org) + +## Features + +Description of the module... + + + +Other external modules are available on [Dolistore.com](https://www.dolistore.com). + +## Translations + +Translations can be completed manually by editing files in the module directories under `langs`. + + + + +## Installation + +Prerequisites: You must have Dolibarr ERP & CRM software installed. You can download it from [Dolistore.org](https://www.dolibarr.org). +You can also get a ready-to-use instance in the cloud from https://saas.dolibarr.org + + +### From the ZIP file and GUI interface + +If the module is a ready-to-deploy zip file, so with a name `module_xxx-version.zip` (e.g., when downloading it from a marketplace like [Dolistore](https://www.dolistore.com)), +go to menu `Home> Setup> Modules> Deploy external module` and upload the zip file. + + + + + +### Final steps + +Using your browser: + + - Log into Dolibarr as a super-administrator + - Go to "Setup"> "Modules" + - You should now be able to find and enable the module + + + +## Licenses + +### Main code + +GPLv3 or (at your option) any later version. See file COPYING for more information. + +### Documentation + +All texts and readme's are licensed under [GFDL](https://www.gnu.org/licenses/fdl-1.3.en.html). diff --git a/admin/about.php b/admin/about.php new file mode 100755 index 0000000..2b9f9cd --- /dev/null +++ b/admin/about.php @@ -0,0 +1,118 @@ + + * Copyright (C) 2026 Eduard Wisch + * Copyright (C) 2024 Frédéric France + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file steuer/admin/about.php + * \ingroup steuer + * \brief About page of module Steuer. + */ + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) { + $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +} +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; +$tmp2 = realpath(__FILE__); +$i = strlen($tmp) - 1; +$j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { + $i--; + $j--; +} +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) { + $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +} +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) { + $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +} +// Try main.inc.php using relative path +if (!$res && file_exists("../../main.inc.php")) { + $res = @include "../../main.inc.php"; +} +if (!$res && file_exists("../../../main.inc.php")) { + $res = @include "../../../main.inc.php"; +} +if (!$res) { + die("Include of main fails"); +} + +// Libraries +require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; +require_once '../lib/steuer.lib.php'; + +/** + * @var Conf $conf + * @var DoliDB $db + * @var HookManager $hookmanager + * @var Translate $langs + * @var User $user + */ + +// Translations +$langs->loadLangs(array("errors", "admin", "steuer@steuer")); + +// Access control +if (!$user->admin) { + accessforbidden(); +} + +// Parameters +$action = GETPOST('action', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); + + +/* + * Actions + */ + +// None + + +/* + * View + */ + +$form = new Form($db); + +$help_url = ''; +$title = "SteuerSetup"; + +llxHeader('', $langs->trans($title), $help_url, '', 0, 0, '', '', '', 'mod-steuer page-admin_about'); + +// Subheader +$linkback = ''.$langs->trans("BackToModuleList").''; + +print load_fiche_titre($langs->trans($title), $linkback, 'title_setup'); + +// Configuration header +$head = steuerAdminPrepareHead(); +print dol_get_fiche_head($head, 'about', $langs->trans($title), 0, 'steuer@steuer'); + +dol_include_once('/steuer/core/modules/modSteuer.class.php'); +$tmpmodule = new modSteuer($db); +print $tmpmodule->getDescLong(); + +// Page end +print dol_get_fiche_end(); +llxFooter(); +$db->close(); diff --git a/admin/setup.php b/admin/setup.php new file mode 100755 index 0000000..0d9fc81 --- /dev/null +++ b/admin/setup.php @@ -0,0 +1,629 @@ + + * Copyright (C) 2024 Frédéric France + * Copyright (C) 2026 Eduard Wisch + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file steuer/admin/setup.php + * \ingroup steuer + * \brief Steuer setup page. + */ + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) { + $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +} +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; +$tmp2 = realpath(__FILE__); +$i = strlen($tmp) - 1; +$j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { + $i--; + $j--; +} +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) { + $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +} +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) { + $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +} +// Try main.inc.php using relative path +if (!$res && file_exists("../../main.inc.php")) { + $res = @include "../../main.inc.php"; +} +if (!$res && file_exists("../../../main.inc.php")) { + $res = @include "../../../main.inc.php"; +} +if (!$res) { + die("Include of main fails"); +} + +// Libraries +require_once DOL_DOCUMENT_ROOT."/core/lib/admin.lib.php"; +require_once '../lib/steuer.lib.php'; +//require_once "../class/myclass.class.php"; + +/** + * @var Conf $conf + * @var DoliDB $db + * @var HookManager $hookmanager + * @var Translate $langs + * @var User $user + */ + +// Translations +$langs->loadLangs(array("admin", "steuer@steuer")); + +// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context +/** @var HookManager $hookmanager */ +$hookmanager->initHooks(array('steuersetup', 'globalsetup')); + +// Parameters +$action = GETPOST('action', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); +$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php + +$value = GETPOST('value', 'alpha'); +$label = GETPOST('label', 'alpha'); +$scandir = GETPOST('scan_dir', 'alpha'); +$type = 'myobject'; + +$error = 0; +$setupnotempty = 0; + +// Access control +if (!$user->admin) { + accessforbidden(); +} + + +// Set this to 1 to use the factory to manage constants. Warning, the generated module will be compatible with version v15+ only +$useFormSetup = 1; + +if (!class_exists('FormSetup')) { + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formsetup.class.php'; +} +$formSetup = new FormSetup($db); + +// Access control +if (!$user->admin) { + accessforbidden(); +} + + +// Enter here all parameters in your setup page + +// Setup conf for selection of an URL +$item = $formSetup->newItem('STEUER_MYPARAM1'); +$item->fieldParams['isMandatory'] = 1; +$item->fieldAttr['placeholder'] = (empty($_SERVER['HTTPS']) ? 'http://' : 'https://') . $_SERVER['HTTP_HOST']; +$item->cssClass = 'minwidth500'; + +// Setup conf for selection of a simple string input +$item = $formSetup->newItem('STEUER_MYPARAM2'); +$item->defaultFieldValue = 'default value'; +$item->fieldAttr['placeholder'] = 'A placeholder here'; +$item->helpText = 'Tooltip text'; + +// Setup conf for selection of a simple textarea input but we replace the text of field title +$item = $formSetup->newItem('STEUER_MYPARAM3'); +$item->nameText = $item->getNameText().' more html text '; + +// Setup conf for a selection of a Thirdparty +$item = $formSetup->newItem('STEUER_MYPARAM4'); +$item->setAsThirdpartyType(); + +// Setup conf for a selection of a boolean +$formSetup->newItem('STEUER_MYPARAM5')->setAsYesNo(); + +// Setup conf for a selection of an Email template of type thirdparty +$formSetup->newItem('STEUER_MYPARAM6')->setAsEmailTemplate('thirdparty'); + +// Setup conf for a selection of a secured key +//$formSetup->newItem('STEUER_MYPARAM7')->setAsSecureKey(); + +// Setup conf for a selection of a Product +$formSetup->newItem('STEUER_MYPARAM8')->setAsProduct(); + +// Add a title for a new section +$formSetup->newItem('NewSection')->setAsTitle(); + +$TField = array( + 'test01' => $langs->trans('test01'), + 'test02' => $langs->trans('test02'), + 'test03' => $langs->trans('test03'), + 'test04' => $langs->trans('test04'), + 'test05' => $langs->trans('test05'), + 'test06' => $langs->trans('test06'), +); + +// Setup conf for a simple combo list +$formSetup->newItem('STEUER_MYPARAM9')->setAsSelect($TField); + +// Setup conf for a multiselect combo list +$item = $formSetup->newItem('STEUER_MYPARAM10'); +$item->setAsMultiSelect($TField); +$item->helpText = $langs->transnoentities('STEUER_MYPARAM10'); + +// Setup conf for a category selection +$formSetup->newItem('STEUER_CATEGORY_ID_XXX')->setAsCategory('product'); + +// Setup conf STEUER_MYPARAM10 +$item = $formSetup->newItem('STEUER_MYPARAM10'); +$item->setAsColor(); +$item->defaultFieldValue = '#FF0000'; +//$item->fieldValue = ''; +//$item->fieldAttr = array() ; // fields attribute only for compatible fields like input text +//$item->fieldOverride = false; // set this var to override field output will override $fieldInputOverride and $fieldOutputOverride too +//$item->fieldInputOverride = false; // set this var to override field input +//$item->fieldOutputOverride = false; // set this var to override field output + +$item = $formSetup->newItem('STEUER_MYPARAM11')->setAsHtml(); +$item->nameText = $item->getNameText().' more html text '; +$item->fieldInputOverride = ''; +$item->helpText = $langs->transnoentities('HelpMessage'); +$item->cssClass = 'minwidth500'; + +$item = $formSetup->newItem('STEUER_MYPARAM12'); +$item->fieldOverride = "Value forced, can't be modified"; +$item->cssClass = 'minwidth500'; + +//$item = $formSetup->newItem('STEUER_MYPARAM13')->setAsDate(); // Not yet implemented + +// End of definition of parameters + + +$setupnotempty += count($formSetup->items); + + +$dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']); + +$moduledir = 'steuer'; +$myTmpObjects = array(); +// TODO Scan list of objects to fill this array +$myTmpObjects['myobject'] = array('label' => 'MyObject', 'includerefgeneration' => 0, 'includedocgeneration' => 0, 'class' => 'MyObject'); + +$tmpobjectkey = GETPOST('object', 'aZ09'); +if ($tmpobjectkey && !array_key_exists($tmpobjectkey, $myTmpObjects)) { + accessforbidden('Bad value for object. Hack attempt ?'); +} + + +/* + * Actions + */ + +// For retrocompatibility Dolibarr < 15.0 +if (versioncompare(explode('.', DOL_VERSION), array(15)) < 0 && $action == 'update' && !empty($user->admin)) { + $formSetup->saveConfFromPost(); +} + +include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; + +if ($action == 'updateMask') { + $maskconst = GETPOST('maskconst', 'aZ09'); + $maskvalue = GETPOST('maskvalue', 'alpha'); + + if ($maskconst && preg_match('/_MASK$/', $maskconst)) { + $res = dolibarr_set_const($db, $maskconst, $maskvalue, 'chaine', 0, '', $conf->entity); + if (!($res > 0)) { + $error++; + } + } + + if (!$error) { + setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); + } else { + setEventMessages($langs->trans("Error"), null, 'errors'); + } +} elseif ($action == 'specimen' && $tmpobjectkey) { + $modele = GETPOST('module', 'alpha'); + + $className = $myTmpObjects[$tmpobjectkey]['class']; + $tmpobject = new $className($db); + '@phan-var-force MyObject $tmpobject'; + $tmpobject->initAsSpecimen(); + + // Search template files + $file = ''; + $className = ''; + $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']); + foreach ($dirmodels as $reldir) { + $file = dol_buildpath($reldir."core/modules/steuer/doc/pdf_".$modele."_".strtolower($tmpobjectkey).".modules.php", 0); + if (file_exists($file)) { + $className = "pdf_".$modele."_".strtolower($tmpobjectkey); + break; + } + } + + if ($className !== '') { + require_once $file; + + $module = new $className($db); + '@phan-var-force ModelePDFMyObject $module'; + + '@phan-var-force ModelePDFMyObject $module'; + + if ($module->write_file($tmpobject, $langs) > 0) { + header("Location: ".DOL_URL_ROOT."/document.php?modulepart=steuer-".strtolower($tmpobjectkey)."&file=SPECIMEN.pdf"); + return; + } else { + setEventMessages($module->error, null, 'errors'); + dol_syslog($module->error, LOG_ERR); + } + } else { + setEventMessages($langs->trans("ErrorModuleNotFound"), null, 'errors'); + dol_syslog($langs->trans("ErrorModuleNotFound"), LOG_ERR); + } +} elseif ($action == 'setmod') { + // TODO Check if numbering module chosen can be activated by calling method canBeActivated + if (!empty($tmpobjectkey)) { + $constforval = 'STEUER_'.strtoupper($tmpobjectkey)."_ADDON"; + dolibarr_set_const($db, $constforval, $value, 'chaine', 0, '', $conf->entity); + } +} elseif ($action == 'set') { + // Activate a model + $ret = addDocumentModel($value, $type, $label, $scandir); +} elseif ($action == 'del') { + $ret = delDocumentModel($value, $type); + if ($ret > 0) { + if (!empty($tmpobjectkey)) { + $constforval = 'STEUER_'.strtoupper($tmpobjectkey).'_ADDON_PDF'; + if (getDolGlobalString($constforval) == "$value") { + dolibarr_del_const($db, $constforval, $conf->entity); + } + } + } +} elseif ($action == 'setdoc') { + // Set or unset default model + if (!empty($tmpobjectkey)) { + $constforval = 'STEUER_'.strtoupper($tmpobjectkey).'_ADDON_PDF'; + if (dolibarr_set_const($db, $constforval, $value, 'chaine', 0, '', $conf->entity)) { + // The constant that was read before the new set + // We therefore requires a variable to have a coherent view + $conf->global->{$constforval} = $value; + } + + // We disable/enable the document template (into llx_document_model table) + $ret = delDocumentModel($value, $type); + if ($ret > 0) { + $ret = addDocumentModel($value, $type, $label, $scandir); + } + } +} elseif ($action == 'unsetdoc') { + if (!empty($tmpobjectkey)) { + $constforval = 'STEUER_'.strtoupper($tmpobjectkey).'_ADDON_PDF'; + dolibarr_del_const($db, $constforval, $conf->entity); + } +} + +$action = 'edit'; + + +/* + * View + */ + +$form = new Form($db); + +$help_url = ''; +$title = "SteuerSetup"; + +llxHeader('', $langs->trans($title), $help_url, '', 0, 0, '', '', '', 'mod-steuer page-admin'); + +// Subheader +$linkback = ''.$langs->trans("BackToModuleList").''; + +print load_fiche_titre($langs->trans($title), $linkback, 'title_setup'); + +// Configuration header +$head = steuerAdminPrepareHead(); +print dol_get_fiche_head($head, 'settings', $langs->trans($title), -1, "steuer@steuer"); + +// Setup page goes here +echo ''.$langs->trans("SteuerSetupPage").'

'; + + +/*if ($action == 'edit') { + print $formSetup->generateOutput(true); + print '
'; + } elseif (!empty($formSetup->items)) { + print $formSetup->generateOutput(); + print '
'; + print ''.$langs->trans("Modify").''; + print '
'; + } + */ +if (!empty($formSetup->items)) { + print $formSetup->generateOutput(true); + print '
'; +} + + +foreach ($myTmpObjects as $myTmpObjectKey => $myTmpObjectArray) { + if (!empty($myTmpObjectArray['includerefgeneration'])) { + // Numbering models + + $setupnotempty++; + + print load_fiche_titre($langs->trans("NumberingModules", $myTmpObjectArray['label']), '', ''); + + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''."\n"; + + clearstatcache(); + + foreach ($dirmodels as $reldir) { + $dir = dol_buildpath($reldir."core/modules/".$moduledir); + + if (is_dir($dir)) { + $handle = opendir($dir); + if (is_resource($handle)) { + while (($file = readdir($handle)) !== false) { + if (strpos($file, 'mod_'.strtolower($myTmpObjectKey).'_') === 0 && substr($file, dol_strlen($file) - 3, 3) == 'php') { + $file = substr($file, 0, dol_strlen($file) - 4); + + require_once $dir.'/'.$file.'.php'; + + $module = new $file($db); + '@phan-var-force ModeleNumRefMyObject $module'; + + // Show modules according to features level + if ($module->version == 'development' && getDolGlobalInt('MAIN_FEATURES_LEVEL') < 2) { + continue; + } + if ($module->version == 'experimental' && getDolGlobalInt('MAIN_FEATURES_LEVEL') < 1) { + continue; + } + + if ($module->isEnabled()) { + dol_include_once('/'.$moduledir.'/class/'.strtolower($myTmpObjectKey).'.class.php'); + + print ''; + + // Show example of numbering model + print ''."\n"; + + print ''; + + $className = $myTmpObjectArray['class']; + $mytmpinstance = new $className($db); + '@phan-var-force MyObject $mytmpinstance'; + $mytmpinstance->initAsSpecimen(); + + // Info + $htmltooltip = ''; + $htmltooltip .= ''.$langs->trans("Version").': '.$module->getVersion().'
'; + + $nextval = $module->getNextValue($mytmpinstance); + if ("$nextval" != $langs->trans("NotAvailable")) { // Keep " on nextval + $htmltooltip .= ''.$langs->trans("NextValue").': '; + if ($nextval) { + if (preg_match('/^Error/', $nextval) || $nextval == 'NotConfigured') { + $nextval = $langs->trans($nextval); + } + $htmltooltip .= $nextval.'
'; + } else { + $htmltooltip .= $langs->trans($module->error).'
'; + } + } + + print ''; + + print "\n"; + } + } + } + closedir($handle); + } + } + } + print "
'.$langs->trans("Name").''.$langs->trans("Description").''.$langs->trans("Example").''.$langs->trans("Status").''.$langs->trans("ShortInfo").'
'.$module->getName($langs)."\n"; + print $module->info($langs); + print ''; + $tmp = $module->getExample(); + if (preg_match('/^Error/', $tmp)) { + $langs->load("errors"); + print '
'.$langs->trans($tmp).'
'; + } elseif ($tmp == 'NotConfigured') { + print $langs->trans($tmp); + } else { + print $tmp; + } + print '
'; + $constforvar = 'STEUER_'.strtoupper($myTmpObjectKey).'_ADDON'; + $defaultifnotset = 'thevaluetousebydefault'; + $activenumberingmodel = getDolGlobalString($constforvar, $defaultifnotset); + if ($activenumberingmodel == $file) { + print img_picto($langs->trans("Activated"), 'switch_on'); + } else { + print ''; + print img_picto($langs->trans("Disabled"), 'switch_off'); + print ''; + } + print ''; + print $form->textwithpicto('', $htmltooltip, 1, 'info'); + print '

\n"; + } + + if (!empty($myTmpObjectArray['includedocgeneration'])) { + /* + * Document templates generators + */ + $setupnotempty++; + $type = strtolower($myTmpObjectKey); + + print load_fiche_titre($langs->trans("DocumentModules", $myTmpObjectKey), '', ''); + + // Load array def with activated templates + $def = array(); + $sql = "SELECT nom"; + $sql .= " FROM ".$db->prefix()."document_model"; + $sql .= " WHERE type = '".$db->escape($type)."'"; + $sql .= " AND entity = ".$conf->entity; + $resql = $db->query($sql); + if ($resql) { + $i = 0; + $num_rows = $db->num_rows($resql); + while ($i < $num_rows) { + $array = $db->fetch_array($resql); + array_push($def, $array[0]); + $i++; + } + } else { + dol_print_error($db); + } + + print ''."\n"; + print ''."\n"; + print ''; + print ''; + print '\n"; + print '\n"; + print ''; + print ''; + print "\n"; + + clearstatcache(); + + foreach ($dirmodels as $reldir) { + foreach (array('', '/doc') as $valdir) { + $realpath = $reldir."core/modules/".$moduledir.$valdir; + $dir = dol_buildpath($realpath); + + if (is_dir($dir)) { + $handle = opendir($dir); + if (is_resource($handle)) { + $filelist = array(); + while (($file = readdir($handle)) !== false) { + $filelist[] = $file; + } + closedir($handle); + arsort($filelist); + + foreach ($filelist as $file) { + if (preg_match('/\.modules\.php$/i', $file) && preg_match('/^(pdf_|doc_)/', $file)) { + if (file_exists($dir.'/'.$file)) { + $name = substr($file, 4, dol_strlen($file) - 16); + $className = substr($file, 0, dol_strlen($file) - 12); + + require_once $dir.'/'.$file; + $module = new $className($db); + '@phan-var-force ModelePDFMyObject $module'; + + $modulequalified = 1; + if ($module->version == 'development' && getDolGlobalInt('MAIN_FEATURES_LEVEL') < 2) { + $modulequalified = 0; + } + if ($module->version == 'experimental' && getDolGlobalInt('MAIN_FEATURES_LEVEL') < 1) { + $modulequalified = 0; + } + + if ($modulequalified) { + print ''; + + // Active + if (in_array($name, $def)) { + print ''; + } else { + print '"; + } + + // Default + print ''; + + // Info + $htmltooltip = ''.$langs->trans("Name").': '.$module->name; + $htmltooltip .= '
'.$langs->trans("Type").': '.($module->type ? $module->type : $langs->trans("Unknown")); + if ($module->type == 'pdf') { + $htmltooltip .= '
'.$langs->trans("Width").'/'.$langs->trans("Height").': '.$module->page_largeur.'/'.$module->page_hauteur; + } + $htmltooltip .= '
'.$langs->trans("Path").': '.preg_replace('/^\//', '', $realpath).'/'.$file; + + $htmltooltip .= '

'.$langs->trans("FeaturesSupported").':'; + $htmltooltip .= '
'.$langs->trans("Logo").': '.yn($module->option_logo, 1, 1); + $htmltooltip .= '
'.$langs->trans("MultiLanguage").': '.yn($module->option_multilang, 1, 1); + + print ''; + + // Preview + print ''; + + print "\n"; + } + } + } + } + } + } + } + } + + print '
'.$langs->trans("Name").''.$langs->trans("Description").''.$langs->trans("Status")."'.$langs->trans("Default")."'.$langs->trans("ShortInfo").''.$langs->trans("Preview").'
'; + print(empty($module->name) ? $name : $module->name); + print "\n"; + if (method_exists($module, 'info')) { + print $module->info($langs); // @phan-suppress-current-line PhanUndeclaredMethod + } else { + print $module->description; + } + print ''."\n"; + print ''; + print img_picto($langs->trans("Enabled"), 'switch_on'); + print ''; + print ''."\n"; + print 'scandir).'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"), 'switch_off').''; + print "'; + $constforvar = 'STEUER_'.strtoupper($myTmpObjectKey).'_ADDON_PDF'; + if (getDolGlobalString($constforvar) == $name) { + //print img_picto($langs->trans("Default"), 'on'); + // Even if choice is the default value, we allow to disable it. Replace this with previous line if you need to disable unset + print 'scandir).'&label='.urlencode($module->name).'&type='.urlencode($type).'" alt="'.$langs->trans("Disable").'">'.img_picto($langs->trans("Enabled"), 'on').''; + } else { + print 'scandir).'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"), 'off').''; + } + print ''; + print $form->textwithpicto('', $htmltooltip, 1, 'info'); + print ''; + if ($module->type == 'pdf') { + $newname = preg_replace('/_'.preg_quote(strtolower($myTmpObjectKey), '/').'/', '', $name); + print ''.img_object($langs->trans("Preview"), 'pdf').''; + } else { + print img_object($langs->transnoentitiesnoconv("PreviewNotAvailable"), 'generic'); + } + print '
'; + } +} + +if (empty($setupnotempty)) { + print '
'.$langs->trans("NothingToSetup"); +} + +// Page end +print dol_get_fiche_end(); + +llxFooter(); +$db->close(); diff --git a/buchung_card.php b/buchung_card.php new file mode 100644 index 0000000..01d8bec --- /dev/null +++ b/buchung_card.php @@ -0,0 +1,417 @@ + 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { + $i--; + $j--; +} +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) { + $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +} +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) { + $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +} +if (!$res && file_exists("../main.inc.php")) { + $res = @include "../main.inc.php"; +} +if (!$res && file_exists("../../main.inc.php")) { + $res = @include "../../main.inc.php"; +} +if (!$res && file_exists("../../../main.inc.php")) { + $res = @include "../../../main.inc.php"; +} +if (!$res) { + die("Include of main fails"); +} + +require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; +dol_include_once('/steuer/class/buchung.class.php'); + +$langs->loadLangs(array("steuer@steuer", "bills", "compta")); + +$id = GETPOSTINT('id'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'aZ09'); +$confirm = GETPOST('confirm', 'alpha'); +$cancel = GETPOST('cancel', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); + +// Objekt initialisieren +$object = new SteuerBuchung($db); + +// Laden, wenn ID oder Ref +if ($id > 0 || !empty($ref)) { + $object->fetch($id, $ref); +} + +/* + * Actions + */ + +if ($cancel) { + if (!empty($backtopage)) { + header("Location: ".$backtopage); + exit; + } + $action = ''; +} + +// Neue Buchung erstellen +if ($action == 'add' && !$cancel) { + $error = 0; + + $object->datum = dol_mktime(0, 0, 0, GETPOSTINT('datummonth'), GETPOSTINT('datumday'), GETPOSTINT('datumyear')); + $object->belegnummer = GETPOST('belegnummer', 'alpha'); + $object->beschreibung = GETPOST('beschreibung', 'alpha'); + $object->fk_konto = GETPOSTINT('fk_konto'); + $object->typ = GETPOST('typ', 'alpha'); + $object->ust_satz = GETPOSTFLOAT('ust_satz'); + $object->zahlungsart = GETPOST('zahlungsart', 'alpha'); + $object->fk_soc = GETPOSTINT('fk_soc'); + $object->note_private = GETPOST('note_private', 'restricthtml'); + + // Betrag berechnen + $betrag_eingabe = GETPOST('betrag_eingabe', 'alpha'); + $betrag = price2num(GETPOST('betrag', 'alpha')); + + if ($betrag_eingabe == 'brutto') { + $object->betrag_brutto = $betrag; + $object->betrag_netto = $betrag / (1 + $object->ust_satz / 100); + $object->betrag_ust = $object->betrag_brutto - $object->betrag_netto; + } else { + $object->betrag_netto = $betrag; + $object->betrag_ust = $betrag * $object->ust_satz / 100; + $object->betrag_brutto = $object->betrag_netto + $object->betrag_ust; + } + + // Validierung + if (empty($object->datum)) { + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesaliases("Date")), null, 'errors'); + $error++; + } + if (empty($object->beschreibung)) { + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesaliases("Description")), null, 'errors'); + $error++; + } + if (empty($object->fk_konto)) { + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesaliases("Account")), null, 'errors'); + $error++; + } + if ($betrag <= 0) { + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesaliases("Amount")), null, 'errors'); + $error++; + } + + if (!$error) { + $result = $object->create($user); + if ($result > 0) { + setEventMessages($langs->trans("BuchungCreated"), null, 'mesgs'); + header("Location: ".dol_buildpath('/steuer/buchung_card.php', 1).'?id='.$result); + exit; + } else { + setEventMessages($object->error, $object->errors, 'errors'); + $action = 'create'; + } + } else { + $action = 'create'; + } +} + +// Buchung aktualisieren +if ($action == 'update' && !$cancel) { + $error = 0; + + $object->datum = dol_mktime(0, 0, 0, GETPOSTINT('datummonth'), GETPOSTINT('datumday'), GETPOSTINT('datumyear')); + $object->belegnummer = GETPOST('belegnummer', 'alpha'); + $object->beschreibung = GETPOST('beschreibung', 'alpha'); + $object->fk_konto = GETPOSTINT('fk_konto'); + $object->typ = GETPOST('typ', 'alpha'); + $object->ust_satz = GETPOSTFLOAT('ust_satz'); + $object->zahlungsart = GETPOST('zahlungsart', 'alpha'); + $object->fk_soc = GETPOSTINT('fk_soc'); + $object->note_private = GETPOST('note_private', 'restricthtml'); + + // Betrag berechnen + $betrag_eingabe = GETPOST('betrag_eingabe', 'alpha'); + $betrag = price2num(GETPOST('betrag', 'alpha')); + + if ($betrag_eingabe == 'brutto') { + $object->betrag_brutto = $betrag; + $object->betrag_netto = $betrag / (1 + $object->ust_satz / 100); + $object->betrag_ust = $object->betrag_brutto - $object->betrag_netto; + } else { + $object->betrag_netto = $betrag; + $object->betrag_ust = $betrag * $object->ust_satz / 100; + $object->betrag_brutto = $object->betrag_netto + $object->betrag_ust; + } + + if (!$error) { + $result = $object->update($user); + if ($result > 0) { + setEventMessages($langs->trans("BuchungUpdated"), null, 'mesgs'); + header("Location: ".dol_buildpath('/steuer/buchung_card.php', 1).'?id='.$object->id); + exit; + } else { + setEventMessages($object->error, $object->errors, 'errors'); + $action = 'edit'; + } + } else { + $action = 'edit'; + } +} + +// Löschen bestätigen +if ($action == 'confirm_delete' && $confirm == 'yes') { + $result = $object->delete($user); + if ($result > 0) { + setEventMessages($langs->trans("BuchungDeleted"), null, 'mesgs'); + header("Location: ".dol_buildpath('/steuer/buchung_list.php', 1)); + exit; + } else { + setEventMessages($object->error, $object->errors, 'errors'); + } +} + +/* + * View + */ + +$form = new Form($db); + +$title = $langs->trans("Buchung"); +if ($action == 'create') { + $title = $langs->trans("NeueBuchung"); +} + +llxHeader('', $title, '', '', 0, 0, '', '', '', 'mod-steuer page-buchung-card'); + +// Konten laden +$konten_einnahmen = SteuerBuchung::getKonten($db, 'einnahme'); +$konten_ausgaben = SteuerBuchung::getKonten($db, 'ausgabe'); +$konten_alle = SteuerBuchung::getKonten($db); + +// USt-Sätze +$ust_saetze = array( + 0 => '0% (steuerfrei)', + 7 => '7% (ermäßigt)', + 19 => '19% (Regelsteuersatz)' +); + +// Zahlungsarten +$zahlungsarten = array( + 'bank' => $langs->trans("Bank"), + 'bar' => $langs->trans("Cash"), + 'paypal' => 'PayPal', + 'kreditkarte' => $langs->trans("CreditCard"), + 'lastschrift' => $langs->trans("DirectDebit"), + 'sonstige' => $langs->trans("Other") +); + +// Buchungstypen +$typen = array( + 'einnahme' => $langs->trans("Einnahme"), + 'ausgabe' => $langs->trans("Ausgabe") +); + +// Formular: Neue Buchung oder Bearbeiten +if ($action == 'create' || $action == 'edit') { + + print load_fiche_titre($action == 'create' ? $langs->trans("NeueBuchung") : $langs->trans("EditBuchung"), '', 'steuer.png@steuer'); + + print '
'; + print ''; + print ''; + if ($action == 'edit') { + print ''; + } + if ($backtopage) { + print ''; + } + + print dol_get_fiche_head(array(), '', '', 0, ''); + + print ''; + + // Typ (Einnahme/Ausgabe) + print ''; + + // Datum + print ''; + + // Belegnummer + print ''; + + // Beschreibung + print ''; + + // Konto + print ''; + + // Betrag + print ''; + + // USt-Satz + print ''; + + // Zahlungsart + print ''; + + // Kunde/Lieferant + print ''; + + // Notiz + print ''; + + print '
'.$langs->trans("Typ").''; + print $form->selectarray('typ', $typen, GETPOSTISSET('typ') ? GETPOST('typ') : $object->typ, 0, 0, 0, '', 0, 0, 0, '', 'minwidth200'); + print '
'.$langs->trans("Date").''; + print $form->selectDate(GETPOSTISSET('datumday') ? dol_mktime(0, 0, 0, GETPOSTINT('datummonth'), GETPOSTINT('datumday'), GETPOSTINT('datumyear')) : ($object->datum ? $object->datum : dol_now()), 'datum', 0, 0, 0, '', 1, 1); + print '
'.$langs->trans("Belegnummer").''; + print ''; + print '
'.$langs->trans("Description").''; + print ''; + print '
'.$langs->trans("Account").''; + print $form->selectarray('fk_konto', $konten_alle, GETPOSTISSET('fk_konto') ? GETPOSTINT('fk_konto') : $object->fk_konto, 1, 0, 0, '', 0, 0, 0, '', 'minwidth300', 1); + print '
'.$langs->trans("Amount").''; + $betrag_wert = GETPOSTISSET('betrag') ? GETPOST('betrag') : ($object->betrag_brutto > 0 ? $object->betrag_brutto : ''); + print ' EUR '; + print ''; + print '
'.$langs->trans("VATRate").''; + print $form->selectarray('ust_satz', $ust_saetze, GETPOSTISSET('ust_satz') ? GETPOST('ust_satz') : ($object->ust_satz !== null ? (int)$object->ust_satz : 19), 0, 0, 0, '', 0, 0, 0, '', 'minwidth200'); + print '
'.$langs->trans("PaymentMode").''; + print $form->selectarray('zahlungsart', $zahlungsarten, GETPOSTISSET('zahlungsart') ? GETPOST('zahlungsart') : $object->zahlungsart, 1, 0, 0, '', 0, 0, 0, '', 'minwidth200'); + print '
'.$langs->trans("ThirdParty").''; + print $form->select_company(GETPOSTISSET('fk_soc') ? GETPOSTINT('fk_soc') : $object->fk_soc, 'fk_soc', '', 1, 0, 0, array(), 0, 'minwidth300'); + print '
'.$langs->trans("Note").''; + print ''; + print '
'; + + print dol_get_fiche_end(); + + print '
'; + print ''; + print '   '; + print ''; + print '
'; + + print '
'; + +} elseif ($object->id > 0) { + // Anzeige der Buchung + + // Löschen bestätigen + if ($action == 'delete') { + print $form->formconfirm( + $_SERVER["PHP_SELF"].'?id='.$object->id, + $langs->trans("DeleteBuchung"), + $langs->trans("ConfirmDeleteBuchung"), + 'confirm_delete', + '', + 0, + 1 + ); + } + + print load_fiche_titre($langs->trans("Buchung").' '.$object->ref, '', 'steuer.png@steuer'); + + print dol_get_fiche_head(array(), '', '', 0, ''); + + print ''; + + // Referenz + print ''; + print ''; + + // Typ + print ''; + print ''; + + // Datum + print ''; + print ''; + + // Belegnummer + print ''; + print ''; + + // Beschreibung + print ''; + print ''; + + // Konto + print ''; + print ''; + + // Beträge + print ''; + print ''; + + print ''; + print ''; + + print ''; + print ''; + + // Zahlungsart + if ($object->zahlungsart) { + print ''; + print ''; + } + + // Kunde/Lieferant + if ($object->fk_soc > 0) { + $soc = new Societe($db); + $soc->fetch($object->fk_soc); + print ''; + print ''; + } + + // Notiz + if ($object->note_private) { + print ''; + print ''; + } + + // Erstellt am/von + print ''; + print ''; + + print '
'.$langs->trans("Ref").''.$object->ref.'
'.$langs->trans("Typ").''.$typen[$object->typ].'
'.$langs->trans("Date").''.dol_print_date($object->datum, 'day').'
'.$langs->trans("Belegnummer").''.$object->belegnummer.'
'.$langs->trans("Description").''.$object->beschreibung.'
'.$langs->trans("Account").''.$object->konto_nummer.' - '.$object->konto_bezeichnung.'
'.$langs->trans("AmountHT").' (Netto)'.price($object->betrag_netto, 0, $langs, 1, 2, 2, 'EUR').'
'.$langs->trans("VAT").' ('.(int)$object->ust_satz.'%)'.price($object->betrag_ust, 0, $langs, 1, 2, 2, 'EUR').'
'.$langs->trans("AmountTTC").' (Brutto)'.price($object->betrag_brutto, 0, $langs, 1, 2, 2, 'EUR').'
'.$langs->trans("PaymentMode").''.(isset($zahlungsarten[$object->zahlungsart]) ? $zahlungsarten[$object->zahlungsart] : $object->zahlungsart).'
'.$langs->trans("ThirdParty").''.$soc->getNomUrl(1).'
'.$langs->trans("Note").''.nl2br($object->note_private).'
'.$langs->trans("DateCreation").''.dol_print_date($object->date_creation, 'dayhour').'
'; + + print dol_get_fiche_end(); + + // Aktionen + print ''; + +} else { + // Keine Buchung gefunden + print $langs->trans("RecordNotFound"); + print '

'; + print '
'; + print ''.$langs->trans("Back").''; + print '
'; +} + +llxFooter(); +$db->close(); diff --git a/buchung_list.php b/buchung_list.php new file mode 100644 index 0000000..66245c2 --- /dev/null +++ b/buchung_list.php @@ -0,0 +1,345 @@ + 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { + $i--; + $j--; +} +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) { + $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +} +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) { + $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +} +if (!$res && file_exists("../main.inc.php")) { + $res = @include "../main.inc.php"; +} +if (!$res && file_exists("../../main.inc.php")) { + $res = @include "../../main.inc.php"; +} +if (!$res && file_exists("../../../main.inc.php")) { + $res = @include "../../../main.inc.php"; +} +if (!$res) { + die("Include of main fails"); +} + +require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; +dol_include_once('/steuer/class/buchung.class.php'); +dol_include_once('/steuer/class/euer.class.php'); + +$langs->loadLangs(array("steuer@steuer", "bills", "compta")); + +$action = GETPOST('action', 'aZ09'); +$massaction = GETPOST('massaction', 'alpha'); +$confirm = GETPOST('confirm', 'alpha'); +$toselect = GETPOST('toselect', 'array'); + +// Filter +$jahr = GETPOSTINT('jahr'); +if (empty($jahr)) { + $jahr = date('Y'); +} +$monat = GETPOSTINT('monat'); +$typ = GETPOST('search_typ', 'alpha'); +$search_ref = GETPOST('search_ref', 'alpha'); +$search_beschreibung = GETPOST('search_beschreibung', 'alpha'); + +// Sortierung +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); +if (empty($sortfield)) { + $sortfield = 'datum'; +} +if (empty($sortorder)) { + $sortorder = 'DESC'; +} + +// Pagination +$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit; +$page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT('page'); +if (empty($page) || $page < 0) { + $page = 0; +} +$offset = $limit * $page; + +/* + * View + */ + +$form = new Form($db); +$euer = new EUeR($db); + +llxHeader('', $langs->trans("Buchungen"), '', '', 0, 0, '', '', '', 'mod-steuer page-buchung-list'); + +print load_fiche_titre($langs->trans("Buchungen"), '', 'steuer.png@steuer'); + +// Datumsgrenzen für SQL +if ($monat > 0) { + $datum_von = $jahr.'-'.sprintf('%02d', $monat).'-01'; + $datum_bis = date('Y-m-t', strtotime($datum_von)); +} else { + $datum_von = $jahr.'-01-01'; + $datum_bis = $jahr.'-12-31'; +} + +// SQL für manuelle Buchungen +$sql = "SELECT b.rowid, b.ref, b.datum, b.belegnummer, b.beschreibung,"; +$sql .= " b.betrag_netto, b.betrag_ust, b.betrag_brutto, b.typ,"; +$sql .= " k.kontonummer, k.bezeichnung as konto_bezeichnung,"; +$sql .= " 'manuell' as quelle"; +$sql .= " FROM ".MAIN_DB_PREFIX."steuer_buchung as b"; +$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."steuer_konto as k ON b.fk_konto = k.rowid"; +$sql .= " WHERE b.entity = ".((int) $conf->entity); +$sql .= " AND b.status = 1"; +$sql .= " AND b.datum BETWEEN '".$db->escape($datum_von)."' AND '".$db->escape($datum_bis)."'"; + +if ($typ) { + $sql .= " AND b.typ = '".$db->escape($typ)."'"; +} +if ($search_ref) { + $sql .= " AND b.ref LIKE '%".$db->escape($search_ref)."%'"; +} +if ($search_beschreibung) { + $sql .= " AND b.beschreibung LIKE '%".$db->escape($search_beschreibung)."%'"; +} + +// UNION mit Rechnungen (Einnahmen) +$sql .= " UNION ALL "; +$sql .= "SELECT f.rowid, f.ref, COALESCE(pf.datep, f.datef) as datum, f.ref as belegnummer,"; +$sql .= " CONCAT('Rechnung: ', s.nom) as beschreibung,"; +$sql .= " f.total_ht as betrag_netto, f.total_tva as betrag_ust, f.total_ttc as betrag_brutto,"; +$sql .= " 'einnahme' as typ, '' as kontonummer, '' as konto_bezeichnung,"; +$sql .= " 'facture' as quelle"; +$sql .= " FROM ".MAIN_DB_PREFIX."facture as f"; +$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON f.fk_soc = s.rowid"; +$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."paiement_facture as pf ON pf.fk_facture = f.rowid"; +$sql .= " WHERE f.entity = ".((int) $conf->entity); +$sql .= " AND f.fk_statut IN (2, 3)"; +$sql .= " AND COALESCE(pf.datep, f.datef) BETWEEN '".$db->escape($datum_von)."' AND '".$db->escape($datum_bis)."'"; +if ($typ == 'ausgabe') { + $sql .= " AND 1=0"; // Keine Einnahmen bei Ausgaben-Filter +} +if ($search_beschreibung) { + $sql .= " AND s.nom LIKE '%".$db->escape($search_beschreibung)."%'"; +} +$sql .= " GROUP BY f.rowid"; + +// UNION mit Lieferantenrechnungen (Ausgaben) +$sql .= " UNION ALL "; +$sql .= "SELECT f.rowid, f.ref, COALESCE(pf.datep, f.datef) as datum, COALESCE(f.ref_supplier, f.ref) as belegnummer,"; +$sql .= " CONCAT('Lieferant: ', s.nom) as beschreibung,"; +$sql .= " f.total_ht as betrag_netto, f.total_tva as betrag_ust, f.total_ttc as betrag_brutto,"; +$sql .= " 'ausgabe' as typ, '' as kontonummer, '' as konto_bezeichnung,"; +$sql .= " 'facture_fourn' as quelle"; +$sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f"; +$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON f.fk_soc = s.rowid"; +$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."paiementfourn_facturefourn as pf ON pf.fk_facturefourn = f.rowid"; +$sql .= " WHERE f.entity = ".((int) $conf->entity); +$sql .= " AND f.fk_statut IN (2)"; +$sql .= " AND COALESCE(pf.datep, f.datef) BETWEEN '".$db->escape($datum_von)."' AND '".$db->escape($datum_bis)."'"; +if ($typ == 'einnahme') { + $sql .= " AND 1=0"; // Keine Ausgaben bei Einnahmen-Filter +} +if ($search_beschreibung) { + $sql .= " AND s.nom LIKE '%".$db->escape($search_beschreibung)."%'"; +} +$sql .= " GROUP BY f.rowid"; + +// Sortierung und Limit +$sql_count = "SELECT COUNT(*) as total FROM (".$sql.") as combined"; +$sql .= " ORDER BY ".$sortfield." ".$sortorder; +$sql .= " LIMIT ".$limit." OFFSET ".$offset; + +// Gesamtzahl ermitteln +$resql_count = $db->query($sql_count); +$nbtotalofrecords = 0; +if ($resql_count) { + $obj = $db->fetch_object($resql_count); + $nbtotalofrecords = $obj->total; +} + +// Filter-Formular +print '
'; +print ''; +print ''; +print ''; + +print '
'; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print '
'.$langs->trans("Year").''.$langs->trans("Month").''.$langs->trans("Typ").'
'; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ' '.$langs->trans("NeueBuchung").''; +print '
'; +print '
'; + +print '
'; + +// Haupttabelle +print ''; +print ''; +print_liste_field_titre("Ref", $_SERVER["PHP_SELF"], "ref", "", $param, "", $sortfield, $sortorder); +print_liste_field_titre("Date", $_SERVER["PHP_SELF"], "datum", "", $param, "", $sortfield, $sortorder); +print_liste_field_titre("Belegnummer", $_SERVER["PHP_SELF"], "belegnummer", "", $param, "", $sortfield, $sortorder); +print_liste_field_titre("Description", $_SERVER["PHP_SELF"], "beschreibung", "", $param, "", $sortfield, $sortorder); +print_liste_field_titre("Account", $_SERVER["PHP_SELF"], "kontonummer", "", $param, "", $sortfield, $sortorder); +print_liste_field_titre("Typ", $_SERVER["PHP_SELF"], "typ", "", $param, "", $sortfield, $sortorder); +print_liste_field_titre("AmountHT", $_SERVER["PHP_SELF"], "betrag_netto", "", $param, 'class="right"', $sortfield, $sortorder); +print_liste_field_titre("VAT", $_SERVER["PHP_SELF"], "betrag_ust", "", $param, 'class="right"', $sortfield, $sortorder); +print_liste_field_titre("AmountTTC", $_SERVER["PHP_SELF"], "betrag_brutto", "", $param, 'class="right"', $sortfield, $sortorder); +print ''; + +$resql = $db->query($sql); +if ($resql) { + $num = $db->num_rows($resql); + $total_einnahmen = 0; + $total_ausgaben = 0; + + while ($obj = $db->fetch_object($resql)) { + print ''; + + // Ref mit Link + print ''; + + // Datum + print ''; + + // Belegnummer + print ''; + + // Beschreibung + print ''; + + // Konto + print ''; + + // Typ + print ''; + + // Beträge + print ''; + print ''; + print ''; + + print ''; + + // Summen + if ($obj->typ == 'einnahme') { + $total_einnahmen += $obj->betrag_netto; + } else { + $total_ausgaben += $obj->betrag_netto; + } + } + + // Summenzeile + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + print '
'; + if ($obj->quelle == 'manuell') { + print ''.$obj->ref.''; + } elseif ($obj->quelle == 'facture') { + print ''.$obj->ref.''; + print ' Rechnung'; + } elseif ($obj->quelle == 'facture_fourn') { + print ''.$obj->ref.''; + print ' Lieferant'; + } + print ''.dol_print_date($db->jdate($obj->datum), 'day').''.$obj->belegnummer.''.dol_trunc($obj->beschreibung, 50).''.$obj->kontonummer.($obj->kontonummer ? ' - ' : '').$obj->konto_bezeichnung.''; + if ($obj->typ == 'einnahme') { + print ''.$langs->trans("Einnahme").''; + } else { + print ''.$langs->trans("Ausgabe").''; + } + print ''.price($obj->betrag_netto, 0, $langs, 1, 2, 2).''.price($obj->betrag_ust, 0, $langs, 1, 2, 2).''.price($obj->betrag_brutto, 0, $langs, 1, 2, 2).'
'.$langs->trans("Total").''.price($total_einnahmen - $total_ausgaben, 0, $langs, 1, 2, 2).'
'; + + // Pagination + print_barre_liste('', $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, '', 0, '', '', $limit, 0, 0, 1); + +} else { + dol_print_error($db); +} + +print '
'; + +// Zusammenfassung +print '
'; +print '
'; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +$gewinn = $total_einnahmen - $total_ausgaben; +$color = $gewinn >= 0 ? 'amountpaymentcomplete' : 'amountremaintopay'; +print ''; +print ''; +print ''; +print '
'.$langs->trans("Summary").' '.$jahr.'
'.$langs->trans("TotalEinnahmen").''.price($total_einnahmen, 0, $langs, 1, 2, 2, 'EUR').'
'.$langs->trans("TotalAusgaben").''.price($total_ausgaben, 0, $langs, 1, 2, 2, 'EUR').'
'.($gewinn >= 0 ? $langs->trans("Gewinn") : $langs->trans("Verlust")).''.price($gewinn, 0, $langs, 1, 2, 2, 'EUR').'
'; +print '
'; + +// Zurück-Button +print '
'; +print '
'; +print ''.$langs->trans("Back").''; +print '
'; + +llxFooter(); +$db->close(); diff --git a/build/buildzip.php b/build/buildzip.php new file mode 100755 index 0000000..3508bbb --- /dev/null +++ b/build/buildzip.php @@ -0,0 +1,316 @@ +#!/usr/bin/env php -d memory_limit=256M + + * + * 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 . + */ + +/* + The goal of that php CLI script is to make zip package of your module + as an alternative to web "build zip" or "perl script makepack" +*/ + +// ============================================= configuration + +/** + * list of files & dirs of your module + * + * @var string[] + */ +$listOfModuleContent = [ + 'admin', + 'ajax', + 'backport', + 'class', + 'css', + 'COPYING', + 'core', + 'img', + 'js', + 'langs', + 'lib', + 'sql', + 'tpl', + '*.md', + '*.json', + '*.php', + 'modulebuilder.txt', +]; + +/** + * if you want to exclude some files from your zip + * + * @var string[] + */ +$exclude_list = [ + '/^.git$/', + '/.*js.map/', + '/DEV.md/' +]; + +// ============================================= end of configuration + +/** + * auto detect module name and version from file name + * + * @return (string|string)[] module name and module version + */ +function detectModule() +{ + $name = $version = ""; + $tab = glob("core/modules/mod*.class.php"); + if (count($tab) == 0) { + echo "[fail] Error on auto detect data : there is no mod*.class.php file into core/modules dir\n"; + exit(-1); + } + if (count($tab) == 1) { + $file = $tab[0]; + $pattern = "/.*mod(?.*)\.class\.php/"; + if (preg_match_all($pattern, $file, $matches)) { + $name = strtolower(reset($matches['mod'])); + } + + echo "extract data from $file\n"; + if (!file_exists($file) || $name == "") { + echo "[fail] Error on auto detect data\n"; + exit(-2); + } + } else { + echo "[fail] Error there is more than one mod*.class.php file into core/modules dir\n"; + exit(-3); + } + + //extract version from file + $contents = file_get_contents($file); + $pattern = "/^.*this->version\s*=\s*'(?.*)'\s*;.*\$/m"; + + // search, and store all matching occurrences in $matches + if (preg_match_all($pattern, $contents, $matches)) { + $version = reset($matches['version']); + } + + if (version_compare($version, '0.0.1', '>=') != 1) { + echo "[fail] Error auto extract version fail\n"; + exit(-4); + } + + echo "module name = $name, version = $version\n"; + return [(string) $name, (string) $version]; +} + +/** + * delete recursively a directory + * + * @param string $dir dir path to delete + * + * @return bool true on success or false on failure. + */ +function delTree($dir) +{ + $files = array_diff(scandir($dir), array('.', '..')); + foreach ($files as $file) { + (is_dir("$dir/$file")) ? delTree("$dir/$file") : secureUnlink("$dir/$file"); + } + return rmdir($dir); +} + + +/** + * do a secure delete file/dir with double check + * (don't trust unlink return) + * + * @param string $path full path to delete + * + * @return bool true on success ($path does not exists at the end of process), else exit + */ +function secureUnlink($path) +{ + if (file_exists($path)) { + if (unlink($path)) { + //then check if really deleted + clearstatcache(); + if (file_exists($path)) { // @phpstan-ignore-line + echo "[fail] unlink of $path fail !\n"; + exit(-5); + } + } else { + echo "[fail] unlink of $path fail !\n"; + exit(-6); + } + } + return true; +} + +/** + * create a directory and check if dir exists + * + * @param string $path path to make + * + * @return bool true on success ($path exists at the end of process), else exit + */ +function mkdirAndCheck($path) +{ + if (mkdir($path)) { + clearstatcache(); + if (is_dir($path)) { + return true; + } + } + echo "[fail] Error on $path (mkdir)\n"; + exit(7); +} + +/** + * check if that filename is concerned by exclude filter + * + * @param string $filename file name to check + * + * @return bool true if file is in excluded list + */ +function is_excluded($filename) +{ + global $exclude_list; + $count = 0; + $notused = preg_filter($exclude_list, '1', $filename, -1, $count); + if ($count > 0) { + echo " - exclude $filename\n"; + return true; + } + return false; +} + +/** + * recursive copy files & dirs + * + * @param string $src source dir + * @param string $dst target dir + * + * @return bool true on success or false on failure. + */ +function rcopy($src, $dst) +{ + if (is_dir($src)) { + // Make the destination directory if not exist + mkdirAndCheck($dst); + // open the source directory + $dir = opendir($src); + + // Loop through the files in source directory + while ($file = readdir($dir)) { + if (($file != '.') && ($file != '..')) { + if (is_dir($src . '/' . $file)) { + // Recursively calling custom copy function + // for sub directory + if (!rcopy($src . '/' . $file, $dst . '/' . $file)) { + return false; + } + } else { + if (!is_excluded($file)) { + if (!copy($src . '/' . $file, $dst . '/' . $file)) { + return false; + } + } + } + } + } + closedir($dir); + } elseif (is_file($src)) { + if (!is_excluded($src)) { + if (!copy($src, $dst)) { + return false; + } + } + } + return true; +} + +/** + * build a zip file with only php code and no external depends + * on "zip" exec for example + * + * @param string $folder folder to use as zip root + * @param ZipArchive $zip zip object (ZipArchive) + * @param string $root relative root path into the zip + * + * @return bool true on success or false on failure. + */ +function zipDir($folder, &$zip, $root = "") +{ + foreach (new \DirectoryIterator($folder) as $f) { + if ($f->isDot()) { + continue; + } //skip . .. + $src = $folder . '/' . $f; + $dst = substr($f->getPathname(), strlen($root)); + if ($f->isDir()) { + if ($zip->addEmptyDir($dst)) { + if (zipDir($src, $zip, $root)) { + continue; + } else { + return false; + } + } else { + return false; + } + } + if ($f->isFile()) { + if (! $zip->addFile($src, $dst)) { + return false; + } + } + } + return true; +} + +/** + * main part of script + */ + +list($mod, $version) = detectModule(); +$outzip = sys_get_temp_dir() . "/module_" . $mod . "-" . $version . ".zip"; +if (file_exists($outzip)) { + secureUnlink($outzip); +} + +//copy all sources into system temp directory +$tmpdir = tempnam(sys_get_temp_dir(), $mod . "-module"); +secureUnlink($tmpdir); +mkdirAndCheck($tmpdir); +$dst = $tmpdir . "/" . $mod; +mkdirAndCheck($dst); + +foreach ($listOfModuleContent as $moduleContent) { + foreach (glob($moduleContent) as $entry) { + if (!rcopy($entry, $dst . '/' . $entry)) { + echo "[fail] Error on copy " . $entry . " to " . $dst . "/" . $entry . "\n"; + echo "Please take time to analyze the problem and fix the bug\n"; + exit(-8); + } + } +} + +$z = new ZipArchive(); +$z->open($outzip, ZIPARCHIVE::CREATE); +zipDir($tmpdir, $z, $tmpdir . '/'); +$z->close(); +delTree($tmpdir); +if (file_exists($outzip)) { + echo "[success] module archive is ready : $outzip ...\n"; +} else { + echo "[fail] build zip error\n"; + exit(-9); +} diff --git a/build/makepack-steuer.conf b/build/makepack-steuer.conf new file mode 100755 index 0000000..16dc1e7 --- /dev/null +++ b/build/makepack-steuer.conf @@ -0,0 +1,11 @@ +# Your module name here +# +# Goal: Goal of module +# Version: +# Author: Copyright - +# License: GPLv3 +# Install: Just unpack content of module package in Dolibarr directory. +# Setup: Go on Dolibarr setup - modules to enable module. +# +# Files in module +mymodule/ \ No newline at end of file diff --git a/class/buchung.class.php b/class/buchung.class.php new file mode 100644 index 0000000..a34c4e5 --- /dev/null +++ b/class/buchung.class.php @@ -0,0 +1,355 @@ +db = $db; + $this->entity = $conf->entity; + } + + /** + * Erstellt eine neue Buchung + * + * @param User $user Benutzer + * @param int $notrigger Keine Trigger ausführen + * @return int >0 bei Erfolg, <0 bei Fehler + */ + public function create($user, $notrigger = 0) + { + global $conf; + + $error = 0; + $now = dol_now(); + + // Standardwerte + if (empty($this->status)) { + $this->status = 1; + } + $this->entity = $conf->entity; + + // Referenz generieren + if (empty($this->ref)) { + $this->ref = $this->getNextRef(); + } + + // Brutto berechnen falls nicht gesetzt + if (empty($this->betrag_brutto)) { + $this->betrag_brutto = $this->betrag_netto + $this->betrag_ust; + } + + $this->db->begin(); + + $sql = "INSERT INTO ".MAIN_DB_PREFIX."steuer_buchung ("; + $sql .= "ref, datum, belegnummer, beschreibung, fk_konto,"; + $sql .= " betrag_netto, betrag_ust, betrag_brutto, ust_satz,"; + $sql .= " typ, zahlungsart, fk_soc, fk_facture, fk_facture_fourn,"; + $sql .= " note_private, date_creation, fk_user_creat, status, entity"; + $sql .= ") VALUES ("; + $sql .= "'".$this->db->escape($this->ref)."',"; + $sql .= "'".$this->db->escape($this->datum)."',"; + $sql .= ($this->belegnummer ? "'".$this->db->escape($this->belegnummer)."'" : "NULL").","; + $sql .= "'".$this->db->escape($this->beschreibung)."',"; + $sql .= ((int) $this->fk_konto).","; + $sql .= ((float) $this->betrag_netto).","; + $sql .= ((float) $this->betrag_ust).","; + $sql .= ((float) $this->betrag_brutto).","; + $sql .= ((float) $this->ust_satz).","; + $sql .= "'".$this->db->escape($this->typ)."',"; + $sql .= ($this->zahlungsart ? "'".$this->db->escape($this->zahlungsart)."'" : "NULL").","; + $sql .= ($this->fk_soc > 0 ? ((int) $this->fk_soc) : "NULL").","; + $sql .= ($this->fk_facture > 0 ? ((int) $this->fk_facture) : "NULL").","; + $sql .= ($this->fk_facture_fourn > 0 ? ((int) $this->fk_facture_fourn) : "NULL").","; + $sql .= ($this->note_private ? "'".$this->db->escape($this->note_private)."'" : "NULL").","; + $sql .= "'".$this->db->idate($now)."',"; + $sql .= ((int) $user->id).","; + $sql .= ((int) $this->status).","; + $sql .= ((int) $this->entity); + $sql .= ")"; + + $resql = $this->db->query($sql); + if (!$resql) { + $error++; + $this->errors[] = "Error ".$this->db->lasterror(); + } + + if (!$error) { + $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."steuer_buchung"); + } + + if (!$error) { + $this->db->commit(); + return $this->id; + } else { + $this->db->rollback(); + return -1; + } + } + + /** + * Aktualisiert eine Buchung + * + * @param User $user Benutzer + * @param int $notrigger Keine Trigger ausführen + * @return int >0 bei Erfolg, <0 bei Fehler + */ + public function update($user, $notrigger = 0) + { + $error = 0; + + // Brutto berechnen + $this->betrag_brutto = $this->betrag_netto + $this->betrag_ust; + + $this->db->begin(); + + $sql = "UPDATE ".MAIN_DB_PREFIX."steuer_buchung SET"; + $sql .= " datum = '".$this->db->escape($this->datum)."',"; + $sql .= " belegnummer = ".($this->belegnummer ? "'".$this->db->escape($this->belegnummer)."'" : "NULL").","; + $sql .= " beschreibung = '".$this->db->escape($this->beschreibung)."',"; + $sql .= " fk_konto = ".((int) $this->fk_konto).","; + $sql .= " betrag_netto = ".((float) $this->betrag_netto).","; + $sql .= " betrag_ust = ".((float) $this->betrag_ust).","; + $sql .= " betrag_brutto = ".((float) $this->betrag_brutto).","; + $sql .= " ust_satz = ".((float) $this->ust_satz).","; + $sql .= " typ = '".$this->db->escape($this->typ)."',"; + $sql .= " zahlungsart = ".($this->zahlungsart ? "'".$this->db->escape($this->zahlungsart)."'" : "NULL").","; + $sql .= " fk_soc = ".($this->fk_soc > 0 ? ((int) $this->fk_soc) : "NULL").","; + $sql .= " note_private = ".($this->note_private ? "'".$this->db->escape($this->note_private)."'" : "NULL").","; + $sql .= " fk_user_modif = ".((int) $user->id); + $sql .= " WHERE rowid = ".((int) $this->id); + + $resql = $this->db->query($sql); + if (!$resql) { + $error++; + $this->errors[] = "Error ".$this->db->lasterror(); + } + + if (!$error) { + $this->db->commit(); + return 1; + } else { + $this->db->rollback(); + return -1; + } + } + + /** + * Lädt eine Buchung + * + * @param int $id ID der Buchung + * @param string $ref Referenz der Buchung + * @return int >0 bei Erfolg, <0 bei Fehler + */ + public function fetch($id, $ref = '') + { + global $conf; + + $sql = "SELECT b.*, k.kontonummer, k.bezeichnung as konto_bezeichnung"; + $sql .= " FROM ".MAIN_DB_PREFIX."steuer_buchung as b"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."steuer_konto as k ON b.fk_konto = k.rowid"; + $sql .= " WHERE b.entity = ".((int) $conf->entity); + if ($id > 0) { + $sql .= " AND b.rowid = ".((int) $id); + } elseif ($ref) { + $sql .= " AND b.ref = '".$this->db->escape($ref)."'"; + } + + $resql = $this->db->query($sql); + if ($resql) { + if ($this->db->num_rows($resql)) { + $obj = $this->db->fetch_object($resql); + + $this->id = $obj->rowid; + $this->ref = $obj->ref; + $this->datum = $this->db->jdate($obj->datum); + $this->belegnummer = $obj->belegnummer; + $this->beschreibung = $obj->beschreibung; + $this->fk_konto = $obj->fk_konto; + $this->betrag_netto = $obj->betrag_netto; + $this->betrag_ust = $obj->betrag_ust; + $this->betrag_brutto = $obj->betrag_brutto; + $this->ust_satz = $obj->ust_satz; + $this->typ = $obj->typ; + $this->zahlungsart = $obj->zahlungsart; + $this->fk_soc = $obj->fk_soc; + $this->fk_facture = $obj->fk_facture; + $this->fk_facture_fourn = $obj->fk_facture_fourn; + $this->note_private = $obj->note_private; + $this->date_creation = $this->db->jdate($obj->date_creation); + $this->tms = $obj->tms; + $this->fk_user_creat = $obj->fk_user_creat; + $this->fk_user_modif = $obj->fk_user_modif; + $this->status = $obj->status; + $this->entity = $obj->entity; + + $this->konto_bezeichnung = $obj->konto_bezeichnung; + $this->konto_nummer = $obj->kontonummer; + + return 1; + } + return 0; + } else { + $this->error = $this->db->lasterror(); + return -1; + } + } + + /** + * Löscht eine Buchung + * + * @param User $user Benutzer + * @param int $notrigger Keine Trigger ausführen + * @return int >0 bei Erfolg, <0 bei Fehler + */ + public function delete($user, $notrigger = 0) + { + $error = 0; + + $this->db->begin(); + + $sql = "DELETE FROM ".MAIN_DB_PREFIX."steuer_buchung"; + $sql .= " WHERE rowid = ".((int) $this->id); + + $resql = $this->db->query($sql); + if (!$resql) { + $error++; + $this->errors[] = "Error ".$this->db->lasterror(); + } + + if (!$error) { + $this->db->commit(); + return 1; + } else { + $this->db->rollback(); + return -1; + } + } + + /** + * Generiert die nächste Referenznummer + * + * @return string Nächste Referenz + */ + private function getNextRef() + { + global $conf; + + $sql = "SELECT MAX(CAST(SUBSTRING(ref, 5) AS UNSIGNED)) as maxref"; + $sql .= " FROM ".MAIN_DB_PREFIX."steuer_buchung"; + $sql .= " WHERE ref LIKE 'BUC-%'"; + $sql .= " AND entity = ".((int) $conf->entity); + + $resql = $this->db->query($sql); + if ($resql) { + $obj = $this->db->fetch_object($resql); + $num = isset($obj->maxref) ? $obj->maxref + 1 : 1; + return 'BUC-'.sprintf('%06d', $num); + } + return 'BUC-000001'; + } + + /** + * Gibt den Link zur Buchung zurück + * + * @param int $withpicto Mit Piktogramm + * @param string $option Option + * @return string HTML-Link + */ + public function getNomUrl($withpicto = 0, $option = '') + { + global $langs; + + $result = ''; + $url = dol_buildpath('/steuer/buchung_card.php', 1).'?id='.$this->id; + + $label = ''.$langs->trans("Buchung").'
'; + $label .= ''.$langs->trans("Ref").': '.$this->ref; + + $linkstart = ''; + $linkend = ''; + + if ($withpicto) { + $result .= img_object($label, $this->picto, 'class="classfortooltip"'); + } + $result .= $linkstart.$this->ref.$linkend; + + return $result; + } + + /** + * Holt alle Konten für Dropdown + * + * @param string $typ Optional: 'einnahme' oder 'ausgabe' + * @return array Konten-Array + */ + public static function getKonten($db, $typ = '') + { + global $conf; + + $konten = array(); + $sql = "SELECT rowid, kontonummer, bezeichnung, kategorie"; + $sql .= " FROM ".MAIN_DB_PREFIX."steuer_konto"; + $sql .= " WHERE aktiv = 1"; + $sql .= " AND entity = ".((int) $conf->entity); + if ($typ) { + $sql .= " AND kategorie = '".$db->escape($typ)."'"; + } + $sql .= " ORDER BY kontonummer"; + + $resql = $db->query($sql); + if ($resql) { + while ($obj = $db->fetch_object($resql)) { + $konten[$obj->rowid] = $obj->kontonummer.' - '.$obj->bezeichnung; + } + } + return $konten; + } +} diff --git a/class/euer.class.php b/class/euer.class.php new file mode 100644 index 0000000..d9deba6 --- /dev/null +++ b/class/euer.class.php @@ -0,0 +1,459 @@ +db = $db; + $this->entity = $conf->entity; + } + + /** + * Berechnet die EÜR aus den Dolibarr-Buchungen + * + * @param int $jahr Steuerjahr + * @param int $monat_von Monat von (1-12, 0=ganzes Jahr) + * @param int $monat_bis Monat bis (1-12, 0=ganzes Jahr) + * @return int 0 bei Erfolg, <0 bei Fehler + */ + public function berechneAusDolibarr($jahr, $monat_von = 0, $monat_bis = 0) + { + global $conf; + + $this->jahr = $jahr; + + // Datumsgrenzen + if ($monat_von > 0 && $monat_bis > 0) { + $datum_von = $jahr.'-'.sprintf('%02d', $monat_von).'-01'; + $datum_bis = date('Y-m-t', strtotime($jahr.'-'.sprintf('%02d', $monat_bis).'-01')); + } else { + $datum_von = $jahr.'-01-01'; + $datum_bis = $jahr.'-12-31'; + } + + // Reset + $this->einnahmen = array(); + $this->ausgaben = array(); + $this->summe_einnahmen = 0; + $this->summe_ausgaben = 0; + $this->ust_summe = 0; + $this->vst_summe = 0; + + // EINNAHMEN aus Kundenrechnungen (bezahlt) + $this->berechneEinnahmenAusRechnungen($datum_von, $datum_bis); + + // AUSGABEN aus Lieferantenrechnungen (bezahlt) + $this->berechneAusgabenAusLieferantenrechnungen($datum_von, $datum_bis); + + // Manuelle Buchungen aus steuer_buchung Tabelle + $this->berechneManuelleBuchungen($datum_von, $datum_bis); + + // Gewinn berechnen + $this->gewinn = $this->summe_einnahmen - $this->summe_ausgaben; + $this->ust_zahllast = $this->ust_summe - $this->vst_summe; + + return 0; + } + + /** + * Einnahmen aus bezahlten Kundenrechnungen + */ + private function berechneEinnahmenAusRechnungen($datum_von, $datum_bis) + { + global $conf; + + // Bezahlte Rechnungen nach Zahlungsdatum (Zufluss-Prinzip!) + $sql = "SELECT f.rowid, f.ref, f.datef as rechnungsdatum,"; + $sql .= " pf.datep as zahlungsdatum, pf.amount as zahlung,"; + $sql .= " f.total_ht as netto, f.total_tva as ust, f.total_ttc as brutto,"; + $sql .= " s.nom as kunde,"; + $sql .= " fd.tva_tx as ust_satz, fd.total_ht as zeile_netto, fd.total_tva as zeile_ust"; + $sql .= " FROM ".MAIN_DB_PREFIX."facture as f"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON f.fk_soc = s.rowid"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."paiement_facture as pf ON pf.fk_facture = f.rowid"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facturedet as fd ON fd.fk_facture = f.rowid"; + $sql .= " WHERE f.entity = ".((int) $conf->entity); + $sql .= " AND f.fk_statut IN (2, 3)"; // Bezahlt oder teilbezahlt + $sql .= " AND pf.datep BETWEEN '".$this->db->escape($datum_von)."' AND '".$this->db->escape($datum_bis)."'"; + $sql .= " ORDER BY pf.datep"; + + $resql = $this->db->query($sql); + if ($resql) { + $einnahmen_details = array(); + while ($obj = $this->db->fetch_object($resql)) { + $key = 'ust_'.(int)$obj->ust_satz; + if (!isset($einnahmen_details[$key])) { + $einnahmen_details[$key] = array( + 'bezeichnung' => 'Erlöse '.(int)$obj->ust_satz.'% USt', + 'netto' => 0, + 'ust' => 0, + 'brutto' => 0, + 'ust_satz' => (int)$obj->ust_satz, + 'anzahl' => 0 + ); + } + $einnahmen_details[$key]['netto'] += $obj->zahlung / (1 + $obj->ust_satz/100); + $einnahmen_details[$key]['ust'] += $obj->zahlung - ($obj->zahlung / (1 + $obj->ust_satz/100)); + $einnahmen_details[$key]['brutto'] += $obj->zahlung; + $einnahmen_details[$key]['anzahl']++; + } + + foreach ($einnahmen_details as $key => $detail) { + $this->einnahmen[$key] = $detail; + $this->summe_einnahmen += $detail['netto']; + $this->ust_summe += $detail['ust']; + } + } + + // Alternative: Wenn keine Zahlungen verknüpft, nimm Rechnungsdatum + $sql2 = "SELECT f.rowid, f.ref, f.datef as datum,"; + $sql2 .= " f.total_ht as netto, f.total_tva as ust, f.total_ttc as brutto,"; + $sql2 .= " s.nom as kunde"; + $sql2 .= " FROM ".MAIN_DB_PREFIX."facture as f"; + $sql2 .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON f.fk_soc = s.rowid"; + $sql2 .= " LEFT JOIN ".MAIN_DB_PREFIX."paiement_facture as pf ON pf.fk_facture = f.rowid"; + $sql2 .= " WHERE f.entity = ".((int) $conf->entity); + $sql2 .= " AND f.fk_statut IN (2, 3)"; + $sql2 .= " AND f.datef BETWEEN '".$this->db->escape($datum_von)."' AND '".$this->db->escape($datum_bis)."'"; + $sql2 .= " AND pf.rowid IS NULL"; // Keine Zahlungsverknüpfung + $sql2 .= " ORDER BY f.datef"; + + $resql2 = $this->db->query($sql2); + if ($resql2) { + while ($obj = $this->db->fetch_object($resql2)) { + $key = 'einnahmen_ohne_zahlung'; + if (!isset($this->einnahmen[$key])) { + $this->einnahmen[$key] = array( + 'bezeichnung' => 'Erlöse (Rechnungsdatum)', + 'netto' => 0, + 'ust' => 0, + 'brutto' => 0, + 'anzahl' => 0 + ); + } + $this->einnahmen[$key]['netto'] += $obj->netto; + $this->einnahmen[$key]['ust'] += $obj->ust; + $this->einnahmen[$key]['brutto'] += $obj->brutto; + $this->einnahmen[$key]['anzahl']++; + $this->summe_einnahmen += $obj->netto; + $this->ust_summe += $obj->ust; + } + } + } + + /** + * Ausgaben aus bezahlten Lieferantenrechnungen + */ + private function berechneAusgabenAusLieferantenrechnungen($datum_von, $datum_bis) + { + global $conf; + + // Bezahlte Lieferantenrechnungen nach Zahlungsdatum (Abfluss-Prinzip!) + $sql = "SELECT f.rowid, f.ref, f.ref_supplier, f.datef as rechnungsdatum,"; + $sql .= " pf.datep as zahlungsdatum, pf.amount as zahlung,"; + $sql .= " f.total_ht as netto, f.total_tva as vst, f.total_ttc as brutto,"; + $sql .= " s.nom as lieferant,"; + $sql .= " fd.tva_tx as vst_satz"; + $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON f.fk_soc = s.rowid"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."paiementfourn_facturefourn as pf ON pf.fk_facturefourn = f.rowid"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."facture_fourn_det as fd ON fd.fk_facture_fourn = f.rowid"; + $sql .= " WHERE f.entity = ".((int) $conf->entity); + $sql .= " AND f.fk_statut IN (2)"; // Bezahlt + $sql .= " AND pf.datep BETWEEN '".$this->db->escape($datum_von)."' AND '".$this->db->escape($datum_bis)."'"; + $sql .= " ORDER BY pf.datep"; + + $resql = $this->db->query($sql); + if ($resql) { + $ausgaben_details = array(); + while ($obj = $this->db->fetch_object($resql)) { + $vst_satz = isset($obj->vst_satz) ? (int)$obj->vst_satz : 19; + $key = 'vst_'.$vst_satz; + if (!isset($ausgaben_details[$key])) { + $ausgaben_details[$key] = array( + 'bezeichnung' => 'Betriebsausgaben '.$vst_satz.'% VSt', + 'netto' => 0, + 'vst' => 0, + 'brutto' => 0, + 'vst_satz' => $vst_satz, + 'anzahl' => 0 + ); + } + $ausgaben_details[$key]['brutto'] += $obj->zahlung; + $ausgaben_details[$key]['netto'] += $obj->zahlung / (1 + $vst_satz/100); + $ausgaben_details[$key]['vst'] += $obj->zahlung - ($obj->zahlung / (1 + $vst_satz/100)); + $ausgaben_details[$key]['anzahl']++; + } + + foreach ($ausgaben_details as $key => $detail) { + $this->ausgaben[$key] = $detail; + $this->summe_ausgaben += $detail['netto']; + $this->vst_summe += $detail['vst']; + } + } + + // Alternative: Ohne Zahlungsverknüpfung + $sql2 = "SELECT f.rowid, f.ref, f.datef as datum,"; + $sql2 .= " f.total_ht as netto, f.total_tva as vst, f.total_ttc as brutto,"; + $sql2 .= " s.nom as lieferant"; + $sql2 .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f"; + $sql2 .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON f.fk_soc = s.rowid"; + $sql2 .= " LEFT JOIN ".MAIN_DB_PREFIX."paiementfourn_facturefourn as pf ON pf.fk_facturefourn = f.rowid"; + $sql2 .= " WHERE f.entity = ".((int) $conf->entity); + $sql2 .= " AND f.fk_statut IN (2)"; + $sql2 .= " AND f.datef BETWEEN '".$this->db->escape($datum_von)."' AND '".$this->db->escape($datum_bis)."'"; + $sql2 .= " AND pf.rowid IS NULL"; + $sql2 .= " ORDER BY f.datef"; + + $resql2 = $this->db->query($sql2); + if ($resql2) { + while ($obj = $this->db->fetch_object($resql2)) { + $key = 'ausgaben_ohne_zahlung'; + if (!isset($this->ausgaben[$key])) { + $this->ausgaben[$key] = array( + 'bezeichnung' => 'Betriebsausgaben (Rechnungsdatum)', + 'netto' => 0, + 'vst' => 0, + 'brutto' => 0, + 'anzahl' => 0 + ); + } + $this->ausgaben[$key]['netto'] += $obj->netto; + $this->ausgaben[$key]['vst'] += $obj->vst; + $this->ausgaben[$key]['brutto'] += $obj->brutto; + $this->ausgaben[$key]['anzahl']++; + $this->summe_ausgaben += $obj->netto; + $this->vst_summe += $obj->vst; + } + } + } + + /** + * Manuelle Buchungen aus steuer_buchung Tabelle + */ + private function berechneManuelleBuchungen($datum_von, $datum_bis) + { + global $conf; + + $sql = "SELECT b.*, k.kontonummer, k.bezeichnung as konto_bezeichnung, k.kategorie"; + $sql .= " FROM ".MAIN_DB_PREFIX."steuer_buchung as b"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."steuer_konto as k ON b.fk_konto = k.rowid"; + $sql .= " WHERE b.entity = ".((int) $conf->entity); + $sql .= " AND b.status = 1"; + $sql .= " AND b.datum BETWEEN '".$this->db->escape($datum_von)."' AND '".$this->db->escape($datum_bis)."'"; + $sql .= " ORDER BY b.datum"; + + $resql = $this->db->query($sql); + if ($resql) { + while ($obj = $this->db->fetch_object($resql)) { + $key = 'manuell_'.$obj->kontonummer; + + if ($obj->typ == 'einnahme') { + if (!isset($this->einnahmen[$key])) { + $this->einnahmen[$key] = array( + 'bezeichnung' => $obj->konto_bezeichnung, + 'kontonummer' => $obj->kontonummer, + 'netto' => 0, + 'ust' => 0, + 'brutto' => 0, + 'ust_satz' => (int)$obj->ust_satz, + 'anzahl' => 0 + ); + } + $this->einnahmen[$key]['netto'] += $obj->betrag_netto; + $this->einnahmen[$key]['ust'] += $obj->betrag_ust; + $this->einnahmen[$key]['brutto'] += $obj->betrag_brutto; + $this->einnahmen[$key]['anzahl']++; + $this->summe_einnahmen += $obj->betrag_netto; + $this->ust_summe += $obj->betrag_ust; + } else { + if (!isset($this->ausgaben[$key])) { + $this->ausgaben[$key] = array( + 'bezeichnung' => $obj->konto_bezeichnung, + 'kontonummer' => $obj->kontonummer, + 'netto' => 0, + 'vst' => 0, + 'brutto' => 0, + 'vst_satz' => (int)$obj->ust_satz, + 'anzahl' => 0 + ); + } + $this->ausgaben[$key]['netto'] += $obj->betrag_netto; + $this->ausgaben[$key]['vst'] += $obj->betrag_ust; + $this->ausgaben[$key]['brutto'] += $obj->betrag_brutto; + $this->ausgaben[$key]['anzahl']++; + $this->summe_ausgaben += $obj->betrag_netto; + $this->vst_summe += $obj->betrag_ust; + } + } + } + } + + /** + * Holt detaillierte Buchungsliste für einen Zeitraum + * + * @param string $datum_von Von-Datum + * @param string $datum_bis Bis-Datum + * @param string $typ 'einnahme', 'ausgabe' oder 'alle' + * @return array Buchungsliste + */ + public function getBuchungsliste($datum_von, $datum_bis, $typ = 'alle') + { + global $conf; + $buchungen = array(); + + // Kundenrechnungen (Einnahmen) + if ($typ == 'alle' || $typ == 'einnahme') { + $sql = "SELECT 'einnahme' as buchungstyp, f.rowid, f.ref,"; + $sql .= " COALESCE(pf.datep, f.datef) as datum,"; + $sql .= " CONCAT('Rechnung ', f.ref, ' - ', s.nom) as beschreibung,"; + $sql .= " f.total_ht as netto, f.total_tva as steuer, f.total_ttc as brutto,"; + $sql .= " s.nom as partner, 'facture' as quelle"; + $sql .= " FROM ".MAIN_DB_PREFIX."facture as f"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON f.fk_soc = s.rowid"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."paiement_facture as pf ON pf.fk_facture = f.rowid"; + $sql .= " WHERE f.entity = ".((int) $conf->entity); + $sql .= " AND f.fk_statut IN (2, 3)"; + $sql .= " AND COALESCE(pf.datep, f.datef) BETWEEN '".$this->db->escape($datum_von)."' AND '".$this->db->escape($datum_bis)."'"; + $sql .= " GROUP BY f.rowid"; + $sql .= " ORDER BY datum"; + + $resql = $this->db->query($sql); + if ($resql) { + while ($obj = $this->db->fetch_object($resql)) { + $buchungen[] = (array)$obj; + } + } + } + + // Lieferantenrechnungen (Ausgaben) + if ($typ == 'alle' || $typ == 'ausgabe') { + $sql = "SELECT 'ausgabe' as buchungstyp, f.rowid, f.ref,"; + $sql .= " COALESCE(pf.datep, f.datef) as datum,"; + $sql .= " CONCAT('Lieferantenrechnung ', COALESCE(f.ref_supplier, f.ref), ' - ', s.nom) as beschreibung,"; + $sql .= " f.total_ht as netto, f.total_tva as steuer, f.total_ttc as brutto,"; + $sql .= " s.nom as partner, 'facture_fourn' as quelle"; + $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON f.fk_soc = s.rowid"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."paiementfourn_facturefourn as pf ON pf.fk_facturefourn = f.rowid"; + $sql .= " WHERE f.entity = ".((int) $conf->entity); + $sql .= " AND f.fk_statut IN (2)"; + $sql .= " AND COALESCE(pf.datep, f.datef) BETWEEN '".$this->db->escape($datum_von)."' AND '".$this->db->escape($datum_bis)."'"; + $sql .= " GROUP BY f.rowid"; + $sql .= " ORDER BY datum"; + + $resql = $this->db->query($sql); + if ($resql) { + while ($obj = $this->db->fetch_object($resql)) { + $buchungen[] = (array)$obj; + } + } + } + + // Manuelle Buchungen + $sql = "SELECT b.typ as buchungstyp, b.rowid, b.ref,"; + $sql .= " b.datum, b.beschreibung,"; + $sql .= " b.betrag_netto as netto, b.betrag_ust as steuer, b.betrag_brutto as brutto,"; + $sql .= " COALESCE(s.nom, '') as partner, 'manuell' as quelle"; + $sql .= " FROM ".MAIN_DB_PREFIX."steuer_buchung as b"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON b.fk_soc = s.rowid"; + $sql .= " WHERE b.entity = ".((int) $conf->entity); + $sql .= " AND b.status = 1"; + if ($typ != 'alle') { + $sql .= " AND b.typ = '".$this->db->escape($typ)."'"; + } + $sql .= " AND b.datum BETWEEN '".$this->db->escape($datum_von)."' AND '".$this->db->escape($datum_bis)."'"; + $sql .= " ORDER BY b.datum"; + + $resql = $this->db->query($sql); + if ($resql) { + while ($obj = $this->db->fetch_object($resql)) { + $buchungen[] = (array)$obj; + } + } + + // Nach Datum sortieren + usort($buchungen, function($a, $b) { + return strcmp($a['datum'], $b['datum']); + }); + + return $buchungen; + } + + /** + * Generiert das EÜR-Format für die Anlage EÜR + * + * @return array EÜR-Zeilen + */ + public function getAnlageEUeR() + { + $zeilen = array(); + + // EINNAHMEN + $zeilen[10] = array('zeile' => 10, 'bezeichnung' => 'Steuerfreie Betriebseinnahmen', 'betrag' => 0); + $zeilen[11] = array('zeile' => 11, 'bezeichnung' => 'Innergemeinschaftliche Lieferungen', 'betrag' => 0); + $zeilen[12] = array('zeile' => 12, 'bezeichnung' => 'Ausfuhrlieferungen', 'betrag' => 0); + $zeilen[14] = array('zeile' => 14, 'bezeichnung' => 'Umsatzsteuerpflichtige Betriebseinnahmen', 'betrag' => $this->summe_einnahmen); + $zeilen[16] = array('zeile' => 16, 'bezeichnung' => 'Sonstige Betriebseinnahmen', 'betrag' => 0); + $zeilen[19] = array('zeile' => 19, 'bezeichnung' => 'Private Kfz-/Telefonnutzung', 'betrag' => 0); + + // Summe Einnahmen + $zeilen[22] = array('zeile' => 22, 'bezeichnung' => 'Summe Betriebseinnahmen', 'betrag' => $this->summe_einnahmen, 'summe' => true); + + // AUSGABEN + $zeilen[26] = array('zeile' => 26, 'bezeichnung' => 'Waren, Roh- und Hilfsstoffe', 'betrag' => 0); + $zeilen[31] = array('zeile' => 31, 'bezeichnung' => 'Löhne und Gehälter', 'betrag' => 0); + $zeilen[32] = array('zeile' => 32, 'bezeichnung' => 'Gesetzliche Sozialaufwendungen', 'betrag' => 0); + $zeilen[34] = array('zeile' => 34, 'bezeichnung' => 'Raumkosten', 'betrag' => 0); + $zeilen[36] = array('zeile' => 36, 'bezeichnung' => 'AfA auf Sachanlagen', 'betrag' => 0); + $zeilen[38] = array('zeile' => 38, 'bezeichnung' => 'Leasing, GWG', 'betrag' => 0); + $zeilen[45] = array('zeile' => 45, 'bezeichnung' => 'Schuldzinsen', 'betrag' => 0); + $zeilen[49] = array('zeile' => 49, 'bezeichnung' => 'Übrige Betriebsausgaben', 'betrag' => $this->summe_ausgaben); + $zeilen[51] = array('zeile' => 51, 'bezeichnung' => 'Fahrzeugkosten', 'betrag' => 0); + + // Summe Ausgaben + $zeilen[67] = array('zeile' => 67, 'bezeichnung' => 'Summe Betriebsausgaben', 'betrag' => $this->summe_ausgaben, 'summe' => true); + + // GEWINN + $zeilen[87] = array('zeile' => 87, 'bezeichnung' => 'Gewinn/Verlust', 'betrag' => $this->gewinn, 'ergebnis' => true); + + return $zeilen; + } +} diff --git a/core/modules/modSteuer.class.php b/core/modules/modSteuer.class.php new file mode 100755 index 0000000..899a4ec --- /dev/null +++ b/core/modules/modSteuer.class.php @@ -0,0 +1,620 @@ + + * Copyright (C) 2018-2019 Nicolas ZABOURI + * Copyright (C) 2019-2024 Frédéric France + * Copyright (C) 2026 Eduard Wisch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \defgroup steuer Module Steuer + * \brief Steuer module descriptor. + * + * \file htdocs/steuer/core/modules/modSteuer.class.php + * \ingroup steuer + * \brief Description and activation file for module Steuer + */ +include_once DOL_DOCUMENT_ROOT.'/core/modules/DolibarrModules.class.php'; + + +/** + * Description and activation class for module Steuer + */ +class modSteuer extends DolibarrModules +{ + /** + * Constructor. Define names, constants, directories, boxes, permissions + * + * @param DoliDB $db Database handler + */ + public function __construct($db) + { + global $conf, $langs; + + $this->db = $db; + + // Id for module (must be unique). + // Use here a free id (See in Home -> System information -> Dolibarr for list of used modules id). + $this->numero = 500000; // TODO Go on page https://wiki.dolibarr.org/index.php/List_of_modules_id to reserve an id number for your module + + // Key text used to identify module (for permissions, menus, etc...) + $this->rights_class = 'steuer'; + + // Family can be 'base' (core modules),'crm','financial','hr','projects','products','ecm','technic' (transverse modules),'interface' (link with external tools),'other','...' + // It is used to group modules by family in module setup page + $this->family = "financial"; + + // Module position in the family on 2 digits ('01', '10', '20', ...) + $this->module_position = '90'; + + // Gives the possibility for the module, to provide his own family info and position of this family (Overwrite $this->family and $this->module_position. Avoid this) + //$this->familyinfo = array('myownfamily' => array('position' => '01', 'label' => $langs->trans("MyOwnFamily"))); + // Module label (no space allowed), used if translation string 'ModuleSteuerName' not found (Steuer is name of module). + $this->name = preg_replace('/^mod/i', '', get_class($this)); + + // DESCRIPTION_FLAG + // Module description, used if translation string 'ModuleSteuerDesc' not found (Steuer is name of module). + $this->description = "EÜR Modul für Deutschland - Einnahmen-Überschuss-Rechnung, USt-Voranmeldung, Gewerbesteuer"; + // Used only if file README.md and README-LL.md not found. + $this->descriptionlong = "Komplettes EÜR-Modul für deutsche Unternehmen: Einnahmen-Überschuss-Rechnung (Anlage EÜR), Umsatzsteuer-Voranmeldung (UStVA), Gewerbesteuer-Berechnung, WISO Steuer Export. Unterstützt SKR03 Kontenrahmen und Steuerjahr 2025."; + + // Author + $this->editor_name = 'Alles Watt läuft (Testsystem)'; + $this->editor_url = ''; // Must be an external online web site + $this->editor_squarred_logo = ''; // Must be image filename into the module/img directory followed with @modulename. Example: 'myimage.png@steuer' + + // Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated', 'experimental_deprecated' or a version string like 'x.y.z' + $this->version = '1.0'; + // Url to the file with your last numberversion of this module + //$this->url_last_version = 'http://www.example.com/versionmodule.txt'; + + // Key used in llx_const table to save module status enabled/disabled (where STEUER is value of property name of module in uppercase) + $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); + + // Name of image file used for this module. + // If file is in theme/yourtheme/img directory under name object_pictovalue.png, use this->picto='pictovalue' + // If file is in module/img directory under name object_pictovalue.png, use this->picto='pictovalue@module' + // To use a supported fa-xxx css style of font awesome, use this->picto='xxx' + $this->picto = 'fa-calculator'; + + // Define some features supported by module (triggers, login, substitutions, menus, css, etc...) + $this->module_parts = array( + // Set this to 1 if module has its own trigger directory (core/triggers) + 'triggers' => 0, + // Set this to 1 if module has its own login method file (core/login) + 'login' => 0, + // Set this to 1 if module has its own substitution function file (core/substitutions) + 'substitutions' => 0, + // Set this to 1 if module has its own menus handler directory (core/menus) + 'menus' => 0, + // Set this to 1 if module overwrite template dir (core/tpl) + 'tpl' => 0, + // Set this to 1 if module has its own barcode directory (core/modules/barcode) + 'barcode' => 0, + // Set this to 1 if module has its own models directory (core/modules/xxx) + 'models' => 0, + // Set this to 1 if module has its own printing directory (core/modules/printing) + 'printing' => 0, + // Set this to 1 if module has its own theme directory (theme) + 'theme' => 0, + // Set this to relative path of css file if module has its own css file + 'css' => array( + // '/steuer/css/steuer.css.php', + ), + // Set this to relative path of js file if module must load a js on all pages + 'js' => array( + // '/steuer/js/steuer.js.php', + ), + // Set here all hooks context managed by module. To find available hook context, make a "grep -r '>initHooks(' *" on source code. You can also set hook context to 'all' + /* BEGIN MODULEBUILDER HOOKSCONTEXTS */ + 'hooks' => array( + // 'data' => array( + // 'hookcontext1', + // 'hookcontext2', + // ), + // 'entity' => '0', + ), + /* END MODULEBUILDER HOOKSCONTEXTS */ + // Set this to 1 if features of module are opened to external users + 'moduleforexternal' => 0, + // Set this to 1 if the module provides a website template into doctemplates/websites/website_template-mytemplate + 'websitetemplates' => 0, + // Set this to 1 if the module provides a captcha driver + 'captcha' => 0 + ); + + // Data directories to create when module is enabled. + // Example: this->dirs = array("/steuer/temp","/steuer/subdir"); + $this->dirs = array("/steuer/temp"); + + // Config pages. Put here list of php page, stored into steuer/admin directory, to use to setup module. + $this->config_page_url = array("setup.php@steuer"); + + // Dependencies + // A condition to hide module + $this->hidden = getDolGlobalInt('MODULE_STEUER_DISABLED'); // A condition to disable module; + // List of module class names that must be enabled if this module is enabled. Example: array('always'=>array('modModuleToEnable1','modModuleToEnable2'), 'FR'=>array('modModuleToEnableFR')...) + $this->depends = array(); + // List of module class names to disable if this one is disabled. Example: array('modModuleToDisable1', ...) + $this->requiredby = array(); + // List of module class names this module is in conflict with. Example: array('modModuleToDisable1', ...) + $this->conflictwith = array(); + + // The language file dedicated to your module + $this->langfiles = array("steuer@steuer"); + + // Prerequisites + $this->phpmin = array(7, 1); // Minimum version of PHP required by module + // $this->phpmax = array(8, 0); // Maximum version of PHP required by module + $this->need_dolibarr_version = array(19, -3); // Minimum version of Dolibarr required by module + // $this->max_dolibarr_version = array(19, -3); // Maximum version of Dolibarr required by module + $this->need_javascript_ajax = 0; + + // Messages at activation + $this->warnings_activation = array(); // Warning to show when we activate module. array('always'='text') or array('FR'='textfr','MX'='textmx'...) + $this->warnings_activation_ext = array(); // Warning to show when we activate an external module. array('always'='text') or array('FR'='textfr','MX'='textmx'...) + //$this->automatic_activation = array('FR'=>'SteuerWasAutomaticallyActivatedBecauseOfYourCountryChoice'); + //$this->always_enabled = true; // If true, can't be disabled + + // Constants + // List of particular constants to add when module is enabled (key, 'chaine', value, desc, visible, 'current' or 'allentities', deleteonunactive) + // Example: $this->const=array(1 => array('STEUER_MYNEWCONST1', 'chaine', 'myvalue', 'This is a constant to add', 1), + // 2 => array('STEUER_MYNEWCONST2', 'chaine', 'myvalue', 'This is another constant to add', 0, 'current', 1) + // ); + $this->const = array(); + + // Some keys to add into the overwriting translation tables + /*$this->overwrite_translation = array( + 'en_US:ParentCompany'=>'Parent company or reseller', + 'fr_FR:ParentCompany'=>'Maison mère ou revendeur' + )*/ + + if (!isModEnabled("steuer")) { + $conf->steuer = new stdClass(); + $conf->steuer->enabled = 0; + } + + // Array to add new pages in new tabs + /* BEGIN MODULEBUILDER TABS */ + $this->tabs = array(); + /* END MODULEBUILDER TABS */ + // Example: + // To add a new tab identified by code tabname1 + // $this->tabs[] = array('data' => 'objecttype:+tabname1:Title1:mylangfile@steuer:$user->hasRight(\'steuer\', \'read\'):/steuer/mynewtab1.php?id=__ID__'); + // To add another new tab identified by code tabname2. Label will be result of calling all substitution functions on 'Title2' key. + // $this->tabs[] = array('data' => 'objecttype:+tabname2:SUBSTITUTION_Title2:mylangfile@steuer:$user->hasRight(\'othermodule\', \'read\'):/steuer/mynewtab2.php?id=__ID__', + // To remove an existing tab identified by code tabname + // $this->tabs[] = array('data' => 'objecttype:-tabname:NU:conditiontoremove'); + // + // Where objecttype can be + // 'categories_x' to add a tab in category view (replace 'x' by type of category (0=product, 1=supplier, 2=customer, 3=member) + // 'contact' to add a tab in contact view + // 'contract' to add a tab in contract view + // 'delivery' to add a tab in delivery view + // 'group' to add a tab in group view + // 'intervention' to add a tab in intervention view + // 'invoice' to add a tab in customer invoice view + // 'supplier_invoice' to add a tab in supplier invoice view + // 'member' to add a tab in foundation member view + // 'opensurveypoll' to add a tab in opensurvey poll view + // 'order' to add a tab in sale order view + // 'supplier_order' to add a tab in supplier order view + // 'payment' to add a tab in payment view + // 'supplier_payment' to add a tab in supplier payment view + // 'product' to add a tab in product view + // 'propal' to add a tab in propal view + // 'project' to add a tab in project view + // 'stock' to add a tab in stock view + // 'thirdparty' to add a tab in third party view + // 'user' to add a tab in user view + + + // Dictionaries + /* Example: + $this->dictionaries=array( + 'langs' => 'steuer@steuer', + // List of tables we want to see into dictionary editor + 'tabname' => array("table1", "table2", "table3"), + // Label of tables + 'tablib' => array("Table1", "Table2", "Table3"), + // Request to select fields + 'tabsql' => array('SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.$this->db->prefix().'table1 as f', 'SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.$this->db->prefix().'table2 as f', 'SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.$this->db->prefix().'table3 as f'), + // Sort order + 'tabsqlsort' => array("label ASC", "label ASC", "label ASC"), + // List of fields (result of select to show dictionary) + 'tabfield' => array("code,label", "code,label", "code,label"), + // List of fields (list of fields to edit a record) + 'tabfieldvalue' => array("code,label", "code,label", "code,label"), + // List of fields (list of fields for insert) + 'tabfieldinsert' => array("code,label", "code,label", "code,label"), + // Name of columns with primary key (try to always name it 'rowid') + 'tabrowid' => array("rowid", "rowid", "rowid"), + // Condition to show each dictionary + 'tabcond' => array(isModEnabled('steuer'), isModEnabled('steuer'), isModEnabled('steuer')), + // Tooltip for every fields of dictionaries: DO NOT PUT AN EMPTY ARRAY + 'tabhelp' => array(array('code' => $langs->trans('CodeTooltipHelp'), 'field2' => 'field2tooltip'), array('code' => $langs->trans('CodeTooltipHelp'), 'field2' => 'field2tooltip'), ...), + ); + */ + /* BEGIN MODULEBUILDER DICTIONARIES */ + $this->dictionaries = array(); + /* END MODULEBUILDER DICTIONARIES */ + + // Boxes/Widgets + // Add here list of php file(s) stored in steuer/core/boxes that contains a class to show a widget. + /* BEGIN MODULEBUILDER WIDGETS */ + $this->boxes = array( + // 0 => array( + // 'file' => 'steuerwidget1.php@steuer', + // 'note' => 'Widget provided by Steuer', + // 'enabledbydefaulton' => 'Home', + // ), + // ... + ); + /* END MODULEBUILDER WIDGETS */ + + // Cronjobs (List of cron jobs entries to add when module is enabled) + // unit_frequency must be 60 for minute, 3600 for hour, 86400 for day, 604800 for week + /* BEGIN MODULEBUILDER CRON */ + $this->cronjobs = array( + // 0 => array( + // 'label' => 'MyJob label', + // 'jobtype' => 'method', + // 'class' => '/steuer/class/myobject.class.php', + // 'objectname' => 'MyObject', + // 'method' => 'doScheduledJob', + // 'parameters' => '', + // 'comment' => 'Comment', + // 'frequency' => 2, + // 'unitfrequency' => 3600, + // 'status' => 0, + // 'test' => 'isModEnabled("steuer")', + // 'priority' => 50, + // ), + ); + /* END MODULEBUILDER CRON */ + // Example: $this->cronjobs=array( + // 0=>array('label'=>'My label', 'jobtype'=>'method', 'class'=>'/dir/class/file.class.php', 'objectname'=>'MyClass', 'method'=>'myMethod', 'parameters'=>'param1, param2', 'comment'=>'Comment', 'frequency'=>2, 'unitfrequency'=>3600, 'status'=>0, 'test'=>'isModEnabled("steuer")', 'priority'=>50), + // 1=>array('label'=>'My label', 'jobtype'=>'command', 'command'=>'', 'parameters'=>'param1, param2', 'comment'=>'Comment', 'frequency'=>1, 'unitfrequency'=>3600*24, 'status'=>0, 'test'=>'isModEnabled("steuer")', 'priority'=>50) + // ); + + // Permissions provided by this module + $this->rights = array(); + $r = 0; + // Add here entries to declare new permissions + /* BEGIN MODULEBUILDER PERMISSIONS */ + /* + $o = 1; + $this->rights[$r][0] = $this->numero . sprintf("%02d", ($o * 10) + 1); // Permission id (must not be already used) + $this->rights[$r][1] = 'Read objects of Steuer'; // Permission label + $this->rights[$r][4] = 'myobject'; + $this->rights[$r][5] = 'read'; // In php code, permission will be checked by test if ($user->hasRight('steuer', 'myobject', 'read')) + $r++; + $this->rights[$r][0] = $this->numero . sprintf("%02d", ($o * 10) + 2); // Permission id (must not be already used) + $this->rights[$r][1] = 'Create/Update objects of Steuer'; // Permission label + $this->rights[$r][4] = 'myobject'; + $this->rights[$r][5] = 'write'; // In php code, permission will be checked by test if ($user->hasRight('steuer', 'myobject', 'write')) + $r++; + $this->rights[$r][0] = $this->numero . sprintf("%02d", ($o * 10) + 3); // Permission id (must not be already used) + $this->rights[$r][1] = 'Delete objects of Steuer'; // Permission label + $this->rights[$r][4] = 'myobject'; + $this->rights[$r][5] = 'delete'; // In php code, permission will be checked by test if ($user->hasRight('steuer', 'myobject', 'delete')) + $r++; + */ + /* END MODULEBUILDER PERMISSIONS */ + + + // Main menu entries to add + $this->menu = array(); + $r = 0; + // Add here entries to declare new menus + /* BEGIN MODULEBUILDER TOPMENU */ + $this->menu[$r++] = array( + 'fk_menu' => '', // Will be stored into mainmenu + leftmenu. Use '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'type' => 'top', // This is a Top menu entry + 'titre' => 'ModuleSteuerName', + 'prefix' => img_picto('', $this->picto, 'class="pictofixedwidth valignmiddle"'), + 'mainmenu' => 'steuer', + 'leftmenu' => '', + 'url' => '/steuer/steuerindex.php', + 'langs' => 'steuer@steuer', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position' => 1000 + $r, + 'enabled' => 'isModEnabled("steuer")', // Define condition to show or hide menu entry. Use 'isModEnabled("steuer")' if entry must be visible if module is enabled. + 'perms' => '1', // Use 'perms'=>'$user->hasRight("steuer", "myobject", "read")' if you want your menu with a permission rules + 'target' => '', + 'user' => 2, // 0=Menu for internal users, 1=external users, 2=both + ); + /* END MODULEBUILDER TOPMENU */ + + /* BEGIN MODULEBUILDER LEFTMENU */ + // EÜR Übersicht + $this->menu[$r++] = array( + 'fk_menu' => 'fk_mainmenu=steuer', + 'type' => 'left', + 'titre' => 'EUeRUebersicht', + 'prefix' => img_picto('', 'fa-chart-pie', 'class="pictofixedwidth"'), + 'mainmenu' => 'steuer', + 'leftmenu' => 'euer_uebersicht', + 'url' => '/steuer/steuerindex.php', + 'langs' => 'steuer@steuer', + 'position' => 1000 + $r, + 'enabled' => 'isModEnabled("steuer")', + 'perms' => '1', + 'target' => '', + 'user' => 2, + ); + // Buchungen + $this->menu[$r++] = array( + 'fk_menu' => 'fk_mainmenu=steuer', + 'type' => 'left', + 'titre' => 'Buchungen', + 'prefix' => img_picto('', 'fa-list', 'class="pictofixedwidth"'), + 'mainmenu' => 'steuer', + 'leftmenu' => 'buchungen', + 'url' => '/steuer/buchung_list.php', + 'langs' => 'steuer@steuer', + 'position' => 1000 + $r, + 'enabled' => 'isModEnabled("steuer")', + 'perms' => '1', + 'target' => '', + 'user' => 2, + ); + // Neue Buchung + $this->menu[$r++] = array( + 'fk_menu' => 'fk_mainmenu=steuer,fk_leftmenu=buchungen', + 'type' => 'left', + 'titre' => 'NeueBuchung', + 'mainmenu' => 'steuer', + 'leftmenu' => 'neue_buchung', + 'url' => '/steuer/buchung_card.php?action=create', + 'langs' => 'steuer@steuer', + 'position' => 1000 + $r, + 'enabled' => 'isModEnabled("steuer")', + 'perms' => '1', + 'target' => '', + 'user' => 2, + ); + // Anlage EÜR + $this->menu[$r++] = array( + 'fk_menu' => 'fk_mainmenu=steuer', + 'type' => 'left', + 'titre' => 'AnlageEUeR', + 'prefix' => img_picto('', 'fa-file-alt', 'class="pictofixedwidth"'), + 'mainmenu' => 'steuer', + 'leftmenu' => 'anlage_euer', + 'url' => '/steuer/euer_bericht.php', + 'langs' => 'steuer@steuer', + 'position' => 1000 + $r, + 'enabled' => 'isModEnabled("steuer")', + 'perms' => '1', + 'target' => '', + 'user' => 2, + ); + // UStVA + $this->menu[$r++] = array( + 'fk_menu' => 'fk_mainmenu=steuer', + 'type' => 'left', + 'titre' => 'UStVA', + 'prefix' => img_picto('', 'fa-percent', 'class="pictofixedwidth"'), + 'mainmenu' => 'steuer', + 'leftmenu' => 'ustva', + 'url' => '/steuer/ustva.php', + 'langs' => 'steuer@steuer', + 'position' => 1000 + $r, + 'enabled' => 'isModEnabled("steuer")', + 'perms' => '1', + 'target' => '', + 'user' => 2, + ); + // Gewerbesteuer + $this->menu[$r++] = array( + 'fk_menu' => 'fk_mainmenu=steuer', + 'type' => 'left', + 'titre' => 'Gewerbesteuer', + 'prefix' => img_picto('', 'fa-building', 'class="pictofixedwidth"'), + 'mainmenu' => 'steuer', + 'leftmenu' => 'gewerbesteuer', + 'url' => '/steuer/gewerbesteuer.php', + 'langs' => 'steuer@steuer', + 'position' => 1000 + $r, + 'enabled' => 'isModEnabled("steuer")', + 'perms' => '1', + 'target' => '', + 'user' => 2, + ); + // WISO Export + $this->menu[$r++] = array( + 'fk_menu' => 'fk_mainmenu=steuer', + 'type' => 'left', + 'titre' => 'WISOExport', + 'prefix' => img_picto('', 'fa-download', 'class="pictofixedwidth"'), + 'mainmenu' => 'steuer', + 'leftmenu' => 'wiso_export', + 'url' => '/steuer/export_wiso.php', + 'langs' => 'steuer@steuer', + 'position' => 1000 + $r, + 'enabled' => 'isModEnabled("steuer")', + 'perms' => '1', + 'target' => '', + 'user' => 2, + ); + // Kontenplan + $this->menu[$r++] = array( + 'fk_menu' => 'fk_mainmenu=steuer', + 'type' => 'left', + 'titre' => 'Kontenplan', + 'prefix' => img_picto('', 'fa-sitemap', 'class="pictofixedwidth"'), + 'mainmenu' => 'steuer', + 'leftmenu' => 'kontenplan', + 'url' => '/steuer/konten.php', + 'langs' => 'steuer@steuer', + 'position' => 1000 + $r, + 'enabled' => 'isModEnabled("steuer")', + 'perms' => '1', + 'target' => '', + 'user' => 2, + ); + /* END MODULEBUILDER LEFTMENU */ + + + // Exports profiles provided by this module + $r = 0; + /* BEGIN MODULEBUILDER EXPORT MYOBJECT */ + /* + $langs->load("steuer@steuer"); + $this->export_code[$r] = $this->rights_class.'_'.$r; + $this->export_label[$r] = 'MyObjectLines'; // Translation key (used only if key ExportDataset_xxx_z not found) + $this->export_icon[$r] = $this->picto; + // Define $this->export_fields_array, $this->export_TypeFields_array and $this->export_entities_array + $keyforclass = 'MyObject'; $keyforclassfile='/steuer/class/myobject.class.php'; $keyforelement='myobject@steuer'; + include DOL_DOCUMENT_ROOT.'/core/commonfieldsinexport.inc.php'; + //$this->export_fields_array[$r]['t.fieldtoadd']='FieldToAdd'; $this->export_TypeFields_array[$r]['t.fieldtoadd']='Text'; + //unset($this->export_fields_array[$r]['t.fieldtoremove']); + //$keyforclass = 'MyObjectLine'; $keyforclassfile='/steuer/class/myobject.class.php'; $keyforelement='myobjectline@steuer'; $keyforalias='tl'; + //include DOL_DOCUMENT_ROOT.'/core/commonfieldsinexport.inc.php'; + $keyforselect='myobject'; $keyforaliasextra='extra'; $keyforelement='myobject@steuer'; + include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; + //$keyforselect='myobjectline'; $keyforaliasextra='extraline'; $keyforelement='myobjectline@steuer'; + //include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; + //$this->export_dependencies_array[$r] = array('myobjectline' => array('tl.rowid','tl.ref')); // To force to activate one or several fields if we select some fields that need same (like to select a unique key if we ask a field of a child to avoid the DISTINCT to discard them, or for computed field than need several other fields) + //$this->export_special_array[$r] = array('t.field' => '...'); + //$this->export_examplevalues_array[$r] = array('t.field' => 'Example'); + //$this->export_help_array[$r] = array('t.field' => 'FieldDescHelp'); + $this->export_sql_start[$r]='SELECT DISTINCT '; + $this->export_sql_end[$r] =' FROM '.$this->db->prefix().'steuer_myobject as t'; + //$this->export_sql_end[$r] .=' LEFT JOIN '.$this->db->prefix().'steuer_myobject_line as tl ON tl.fk_myobject = t.rowid'; + $this->export_sql_end[$r] .=' WHERE 1 = 1'; + $this->export_sql_end[$r] .=' AND t.entity IN ('.getEntity('myobject').')'; + $r++; */ + /* END MODULEBUILDER EXPORT MYOBJECT */ + + // Imports profiles provided by this module + $r = 0; + /* BEGIN MODULEBUILDER IMPORT MYOBJECT */ + /* + $langs->load("steuer@steuer"); + $this->import_code[$r] = $this->rights_class.'_'.$r; + $this->import_label[$r] = 'MyObjectLines'; // Translation key (used only if key ExportDataset_xxx_z not found) + $this->import_icon[$r] = $this->picto; + $this->import_tables_array[$r] = array('t' => $this->db->prefix().'steuer_myobject', 'extra' => $this->db->prefix().'steuer_myobject_extrafields'); + $this->import_tables_creator_array[$r] = array('t' => 'fk_user_author'); // Fields to store import user id + $import_sample = array(); + $keyforclass = 'MyObject'; $keyforclassfile='/steuer/class/myobject.class.php'; $keyforelement='myobject@steuer'; + include DOL_DOCUMENT_ROOT.'/core/commonfieldsinimport.inc.php'; + $import_extrafield_sample = array(); + $keyforselect='myobject'; $keyforaliasextra='extra'; $keyforelement='myobject@steuer'; + include DOL_DOCUMENT_ROOT.'/core/extrafieldsinimport.inc.php'; + $this->import_fieldshidden_array[$r] = array('extra.fk_object' => 'lastrowid-'.$this->db->prefix().'steuer_myobject'); + $this->import_regex_array[$r] = array(); + $this->import_examplevalues_array[$r] = array_merge($import_sample, $import_extrafield_sample); + $this->import_updatekeys_array[$r] = array('t.ref' => 'Ref'); + $this->import_convertvalue_array[$r] = array( + 't.ref' => array( + 'rule'=>'getrefifauto', + 'class'=>(!getDolGlobalString('STEUER_MYOBJECT_ADDON') ? 'mod_myobject_standard' : getDolGlobalString('STEUER_MYOBJECT_ADDON')), + 'path'=>"/core/modules/steuer/".(!getDolGlobalString('STEUER_MYOBJECT_ADDON') ? 'mod_myobject_standard' : getDolGlobalString('STEUER_MYOBJECT_ADDON')).'.php', + 'classobject'=>'MyObject', + 'pathobject'=>'/steuer/class/myobject.class.php', + ), + 't.fk_soc' => array('rule' => 'fetchidfromref', 'file' => '/societe/class/societe.class.php', 'class' => 'Societe', 'method' => 'fetch', 'element' => 'ThirdParty'), + 't.fk_user_valid' => array('rule' => 'fetchidfromref', 'file' => '/user/class/user.class.php', 'class' => 'User', 'method' => 'fetch', 'element' => 'user'), + 't.fk_mode_reglement' => array('rule' => 'fetchidfromcodeorlabel', 'file' => '/compta/paiement/class/cpaiement.class.php', 'class' => 'Cpaiement', 'method' => 'fetch', 'element' => 'cpayment'), + ); + $this->import_run_sql_after_array[$r] = array(); + $r++; */ + /* END MODULEBUILDER IMPORT MYOBJECT */ + } + + /** + * Function called when module is enabled. + * The init function add constants, boxes, permissions and menus (defined in constructor) into Dolibarr database. + * It also creates data directories + * + * @param string $options Options when enabling module ('', 'noboxes') + * @return int<-1,1> 1 if OK, <=0 if KO + */ + public function init($options = '') + { + global $conf, $langs; + + // Create tables of module at module activation + //$result = $this->_load_tables('/install/mysql/', 'steuer'); + $result = $this->_load_tables('/steuer/sql/'); + if ($result < 0) { + return -1; // Do not activate module if error 'not allowed' returned when loading module SQL queries (the _load_table run sql with run_sql with the error allowed parameter set to 'default') + } + + // Create extrafields during init + //include_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; + //$extrafields = new ExtraFields($this->db); + //$result0=$extrafields->addExtraField('steuer_separator1', "Separator 1", 'separator', 1, 0, 'thirdparty', 0, 0, '', array('options'=>array(1=>1)), 1, '', 1, 0, '', '', 'steuer@steuer', 'isModEnabled("steuer")'); + //$result1=$extrafields->addExtraField('steuer_myattr1', "New Attr 1 label", 'boolean', 1, 3, 'thirdparty', 0, 0, '', '', 1, '', -1, 0, '', '', 'steuer@steuer', 'isModEnabled("steuer")'); + //$result2=$extrafields->addExtraField('steuer_myattr2', "New Attr 2 label", 'varchar', 1, 10, 'project', 0, 0, '', '', 1, '', -1, 0, '', '', 'steuer@steuer', 'isModEnabled("steuer")'); + //$result3=$extrafields->addExtraField('steuer_myattr3', "New Attr 3 label", 'varchar', 1, 10, 'bank_account', 0, 0, '', '', 1, '', -1, 0, '', '', 'steuer@steuer', 'isModEnabled("steuer")'); + //$result4=$extrafields->addExtraField('steuer_myattr4', "New Attr 4 label", 'select', 1, 3, 'thirdparty', 0, 1, '', array('options'=>array('code1'=>'Val1','code2'=>'Val2','code3'=>'Val3')), 1,'', -1, 0, '', '', 'steuer@steuer', 'isModEnabled("steuer")'); + //$result5=$extrafields->addExtraField('steuer_myattr5', "New Attr 5 label", 'text', 1, 10, 'user', 0, 0, '', '', 1, '', -1, 0, '', '', 'steuer@steuer', 'isModEnabled("steuer")'); + + // Permissions + $this->remove($options); + + $sql = array(); + + // Document templates + $moduledir = dol_sanitizeFileName('steuer'); + $myTmpObjects = array(); + $myTmpObjects['MyObject'] = array('includerefgeneration' => 0, 'includedocgeneration' => 0); + + foreach ($myTmpObjects as $myTmpObjectKey => $myTmpObjectArray) { + if ($myTmpObjectArray['includerefgeneration']) { + $src = DOL_DOCUMENT_ROOT.'/install/doctemplates/'.$moduledir.'/template_myobjects.odt'; + $dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/'.$moduledir; + $dest = $dirodt.'/template_myobjects.odt'; + + if (file_exists($src) && !file_exists($dest)) { + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + dol_mkdir($dirodt); + $result = dol_copy($src, $dest, '0', 0); + if ($result < 0) { + $langs->load("errors"); + $this->error = $langs->trans('ErrorFailToCopyFile', $src, $dest); + return 0; + } + } + + $sql = array_merge($sql, array( + "DELETE FROM ".$this->db->prefix()."document_model WHERE nom = 'standard_".strtolower($myTmpObjectKey)."' AND type = '".$this->db->escape(strtolower($myTmpObjectKey))."' AND entity = ".((int) $conf->entity), + "INSERT INTO ".$this->db->prefix()."document_model (nom, type, entity) VALUES('standard_".strtolower($myTmpObjectKey)."', '".$this->db->escape(strtolower($myTmpObjectKey))."', ".((int) $conf->entity).")", + "DELETE FROM ".$this->db->prefix()."document_model WHERE nom = 'generic_".strtolower($myTmpObjectKey)."_odt' AND type = '".$this->db->escape(strtolower($myTmpObjectKey))."' AND entity = ".((int) $conf->entity), + "INSERT INTO ".$this->db->prefix()."document_model (nom, type, entity) VALUES('generic_".strtolower($myTmpObjectKey)."_odt', '".$this->db->escape(strtolower($myTmpObjectKey))."', ".((int) $conf->entity).")" + )); + } + } + + return $this->_init($sql, $options); + } + + /** + * Function called when module is disabled. + * Remove from database constants, boxes and permissions from Dolibarr database. + * Data directories are not deleted + * + * @param string $options Options when enabling module ('', 'noboxes') + * @return int<-1,1> 1 if OK, <=0 if KO + */ + public function remove($options = '') + { + $sql = array(); + return $this->_remove($sql, $options); + } +} diff --git a/euer_bericht.php b/euer_bericht.php new file mode 100644 index 0000000..0c7f891 --- /dev/null +++ b/euer_bericht.php @@ -0,0 +1,333 @@ + 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { + $i--; + $j--; +} +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) { + $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +} +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) { + $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +} +if (!$res && file_exists("../main.inc.php")) { + $res = @include "../main.inc.php"; +} +if (!$res && file_exists("../../main.inc.php")) { + $res = @include "../../main.inc.php"; +} +if (!$res && file_exists("../../../main.inc.php")) { + $res = @include "../../../main.inc.php"; +} +if (!$res) { + die("Include of main fails"); +} + +require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; +dol_include_once('/steuer/class/euer.class.php'); + +$langs->loadLangs(array("steuer@steuer", "bills", "compta")); + +$jahr = GETPOSTINT('jahr'); +if (empty($jahr)) { + $jahr = date('Y'); +} + +/* + * View + */ + +$form = new Form($db); +$euer = new EUeR($db); +$euer->berechneAusDolibarr($jahr); + +llxHeader('', $langs->trans("AnlageEUeR"), '', '', 0, 0, '', '', '', 'mod-steuer page-euer-bericht'); + +print load_fiche_titre($langs->trans("AnlageEUeR")." ".$jahr, '', 'steuer.png@steuer'); + +// Jahr-Auswahl +print '
'; +print ''; +print '
'; +print ''; +print ' '; +print ' '.$langs->trans("ExportCSV").''; +print '
'; +print '
'; + +print '

'; + +// Anlage EÜR Format +print '
'; +print ''; + +// Header +print ''; +print ''; +print ''; +print ''; +print ''; + +// ============ BETRIEBSEINNAHMEN ============ +print ''; +print ''; +print ''; + +// Zeile 10-12: Steuerfreie Einnahmen +$zeile10 = 0; // Steuerfreie Betriebseinnahmen +$zeile11 = 0; // Innergemeinschaftliche Lieferungen +$zeile12 = 0; // Ausfuhrlieferungen + +print ''; +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; +print ''; + +// Zeile 14: Umsatzsteuerpflichtige Einnahmen +print ''; +print ''; +print ''; +print ''; +print ''; + +// Zeile 16: Vom Finanzamt erstattete USt +print ''; +print ''; +print ''; +print ''; +print ''; + +// Zeile 18: Veräußerungsgewinne +print ''; +print ''; +print ''; +print ''; +print ''; + +// Zeile 19: Private Nutzung +print ''; +print ''; +print ''; +print ''; +print ''; + +// Zeile 20: Auflösung Rücklagen +print ''; +print ''; +print ''; +print ''; +print ''; + +// Zwischensumme Einnahmen +$summe_einnahmen = $zeile10 + $zeile11 + $zeile12 + $euer->summe_einnahmen; +print ''; +print ''; +print ''; +print ''; +print ''; + +// ============ BETRIEBSAUSGABEN ============ +print ''; +print ''; +print ''; + +// Wareneinkauf +print ''; +print ''; +print ''; +print ''; +print ''; + +// Fremdleistungen +print ''; +print ''; +print ''; +print ''; +print ''; + +// Personal +print ''; +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; +print ''; + +// Raumkosten +print ''; +print ''; +print ''; +print ''; +print ''; + +// AfA +print ''; +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; +print ''; + +// Sonstige Ausgaben +print ''; +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; +print ''; + +// Übrige Betriebsausgaben (enthält alle Ausgaben aus Dolibarr) +print ''; +print ''; +print ''; +print ''; +print ''; + +// Fahrzeugkosten +print ''; +print ''; +print ''; +print ''; +print ''; + +// Bewirtung +print ''; +print ''; +print ''; +print ''; +print ''; + +// Verpflegungsmehraufwand +print ''; +print ''; +print ''; +print ''; +print ''; + +// Häusliches Arbeitszimmer +print ''; +print ''; +print ''; +print ''; +print ''; + +// USt gezahlt +print ''; +print ''; +print ''; +print ''; +print ''; + +// Summe Ausgaben +$summe_ausgaben = $euer->summe_ausgaben; +print ''; +print ''; +print ''; +print ''; +print ''; + +// ============ GEWINNERMITTLUNG ============ +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; +print ''; + +// Gewinn/Verlust +$gewinn = $summe_einnahmen - $summe_ausgaben; +$color = $gewinn >= 0 ? 'amountpaymentcomplete' : 'amountremaintopay'; +print ''; +print ''; +print ''; +print ''; +print ''; + +print '
'.$langs->trans("Zeile").''.$langs->trans("Bezeichnung").''.$langs->trans("Betrag").' EUR
A. Betriebseinnahmen
10Steuerfreie Betriebseinnahmen nach § 4 Nr. 8 bis 28 UStG'.price($zeile10, 0, $langs, 1, 2, 2).'
11Innergemeinschaftliche Lieferungen (§ 4 Nr. 1 Buchst. b UStG)'.price($zeile11, 0, $langs, 1, 2, 2).'
12Steuerfreie Ausfuhrlieferungen (§ 4 Nr. 1 Buchst. a UStG)'.price($zeile12, 0, $langs, 1, 2, 2).'
14Umsatzsteuerpflichtige Betriebseinnahmen'.price($euer->summe_einnahmen, 0, $langs, 1, 2, 2).'
16Vom Finanzamt erstattete und ggf. verrechnete Umsatzsteuer'.price(0, 0, $langs, 1, 2, 2).'
18Veräußerung/Entnahme von Anlagevermögen'.price(0, 0, $langs, 1, 2, 2).'
19Private Kfz-Nutzung, Sach-, Nutzungs- und Leistungsentnahmen'.price(0, 0, $langs, 1, 2, 2).'
20Auflösung von Rücklagen und Ausgleichsposten (§ 6c EStG)'.price(0, 0, $langs, 1, 2, 2).'
22Summe Betriebseinnahmen'.price($summe_einnahmen, 0, $langs, 1, 2, 2).'
B. Betriebsausgaben
26Waren, Roh- und Hilfsstoffe einschl. der Nebenkosten'.price(0, 0, $langs, 1, 2, 2).'
27Bezogene Fremdleistungen'.price(0, 0, $langs, 1, 2, 2).'
31Löhne und Gehälter'.price(0, 0, $langs, 1, 2, 2).'
32Gesetzliche Sozialaufwendungen'.price(0, 0, $langs, 1, 2, 2).'
34Raumkosten und sonstige Grundstücksaufwendungen'.price(0, 0, $langs, 1, 2, 2).'
36AfA auf unbewegliche Wirtschaftsgüter'.price(0, 0, $langs, 1, 2, 2).'
37AfA auf bewegliche Wirtschaftsgüter'.price(0, 0, $langs, 1, 2, 2).'
38AfA auf geringwertige Wirtschaftsgüter'.price(0, 0, $langs, 1, 2, 2).'
45Schuldzinsen zur Finanzierung von Anschaffungs-/Herstellungskosten'.price(0, 0, $langs, 1, 2, 2).'
46Übrige Schuldzinsen'.price(0, 0, $langs, 1, 2, 2).'
48Geschenke'.price(0, 0, $langs, 1, 2, 2).'
49Übrige unbeschränkt abziehbare Betriebsausgaben'.price($euer->summe_ausgaben, 0, $langs, 1, 2, 2).'
51Aufwendungen für ein zum Betriebsvermögen gehörendes Kfz'.price(0, 0, $langs, 1, 2, 2).'
53Beschränkt abziehbare Bewirtungsaufwendungen (70%)'.price(0, 0, $langs, 1, 2, 2).'
54Pauschbeträge für Verpflegungsmehraufwand'.price(0, 0, $langs, 1, 2, 2).'
56Aufwendungen für ein häusliches Arbeitszimmer'.price(0, 0, $langs, 1, 2, 2).'
64An das Finanzamt gezahlte und ggf. verrechnete Umsatzsteuer'.price($euer->ust_zahllast > 0 ? $euer->ust_zahllast : 0, 0, $langs, 1, 2, 2).'
67Summe Betriebsausgaben'.price($summe_ausgaben, 0, $langs, 1, 2, 2).'
C. Gewinnermittlung
71Betriebseinnahmen (aus Zeile 22)'.price($summe_einnahmen, 0, $langs, 1, 2, 2).'
72Betriebsausgaben (aus Zeile 67)'.price($summe_ausgaben, 0, $langs, 1, 2, 2).'
87'.($gewinn >= 0 ? $langs->trans("Gewinn") : $langs->trans("Verlust")).''.price($gewinn, 0, $langs, 1, 2, 2).'
'; +print '
'; + +// Hinweise +print '
'; +print '
'; +print ''.$langs->trans("Hinweis").':
'; +print '- '.$langs->trans("EUeRHinweis1").'
'; +print '- '.$langs->trans("EUeRHinweis2").'
'; +print '- '.$langs->trans("EUeRHinweis3").'
'; +print '
'; + +// Zurück-Button +print '
'; +print '
'; +print ''.$langs->trans("Back").''; +print '
'; + +llxFooter(); +$db->close(); diff --git a/export_wiso.php b/export_wiso.php new file mode 100644 index 0000000..96701f7 --- /dev/null +++ b/export_wiso.php @@ -0,0 +1,369 @@ + 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { + $i--; + $j--; +} +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) { + $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +} +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) { + $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +} +if (!$res && file_exists("../main.inc.php")) { + $res = @include "../main.inc.php"; +} +if (!$res && file_exists("../../main.inc.php")) { + $res = @include "../../main.inc.php"; +} +if (!$res && file_exists("../../../main.inc.php")) { + $res = @include "../../../main.inc.php"; +} +if (!$res) { + die("Include of main fails"); +} + +require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; +dol_include_once('/steuer/class/euer.class.php'); + +$langs->loadLangs(array("steuer@steuer", "bills", "compta", "exports")); + +$jahr = GETPOSTINT('jahr'); +if (empty($jahr)) { + $jahr = date('Y'); +} +$action = GETPOST('action', 'aZ09'); +$format = GETPOST('format', 'alpha'); +if (empty($format)) { + $format = 'wiso_euer'; +} + +/* + * Actions + */ + +// Export durchführen +if ($action == 'export') { + $euer = new EUeR($db); + $buchungen = $euer->getBuchungsliste($jahr.'-01-01', $jahr.'-12-31', 'alle'); + + if ($format == 'wiso_euer') { + // WISO EÜR Format (CSV) + $filename = 'euer_export_'.$jahr.'_'.date('Ymd').'.csv'; + + header('Content-Type: text/csv; charset=utf-8'); + header('Content-Disposition: attachment; filename="'.$filename.'"'); + header('Cache-Control: no-cache, no-store, must-revalidate'); + + $output = fopen('php://output', 'w'); + + // BOM für Excel UTF-8 + fprintf($output, chr(0xEF).chr(0xBB).chr(0xBF)); + + // Header + fputcsv($output, array( + 'Datum', + 'Belegnummer', + 'Beschreibung', + 'Einnahme/Ausgabe', + 'Netto', + 'USt/VSt', + 'Brutto', + 'USt-Satz', + 'Kontonummer', + 'Partner' + ), ';'); + + // Daten + foreach ($buchungen as $buchung) { + fputcsv($output, array( + date('d.m.Y', strtotime($buchung['datum'])), + $buchung['ref'], + $buchung['beschreibung'], + $buchung['buchungstyp'] == 'einnahme' ? 'Einnahme' : 'Ausgabe', + number_format($buchung['netto'], 2, ',', ''), + number_format($buchung['steuer'], 2, ',', ''), + number_format($buchung['brutto'], 2, ',', ''), + '19', // Standard, könnte erweitert werden + '', // Kontonummer + $buchung['partner'] + ), ';'); + } + + fclose($output); + exit; + + } elseif ($format == 'datev') { + // DATEV-Format (vereinfacht) + $filename = 'datev_export_'.$jahr.'_'.date('Ymd').'.csv'; + + header('Content-Type: text/csv; charset=utf-8'); + header('Content-Disposition: attachment; filename="'.$filename.'"'); + header('Cache-Control: no-cache, no-store, must-revalidate'); + + $output = fopen('php://output', 'w'); + + // BOM für Excel UTF-8 + fprintf($output, chr(0xEF).chr(0xBB).chr(0xBF)); + + // DATEV Header (vereinfacht) + fputcsv($output, array( + 'Umsatz', + 'Soll/Haben', + 'Konto', + 'Gegenkonto', + 'BU-Schlüssel', + 'Belegdatum', + 'Belegfeld 1', + 'Buchungstext' + ), ';'); + + foreach ($buchungen as $buchung) { + $soll_haben = $buchung['buchungstyp'] == 'einnahme' ? 'H' : 'S'; + $konto = $buchung['buchungstyp'] == 'einnahme' ? '8400' : '4900'; + $gegenkonto = '1200'; // Bank + + fputcsv($output, array( + number_format($buchung['brutto'], 2, ',', ''), + $soll_haben, + $konto, + $gegenkonto, + '', // BU-Schlüssel + date('dm', strtotime($buchung['datum'])), + $buchung['ref'], + $buchung['beschreibung'] + ), ';'); + } + + fclose($output); + exit; + + } elseif ($format == 'ustva_csv') { + // UStVA Werte als CSV + $filename = 'ustva_'.$jahr.'_'.date('Ymd').'.csv'; + + header('Content-Type: text/csv; charset=utf-8'); + header('Content-Disposition: attachment; filename="'.$filename.'"'); + header('Cache-Control: no-cache, no-store, must-revalidate'); + + $output = fopen('php://output', 'w'); + fprintf($output, chr(0xEF).chr(0xBB).chr(0xBF)); + + // Header + fputcsv($output, array( + 'Monat', + 'Kz81 (Umsätze 19%)', + 'Kz86 (Umsätze 7%)', + 'USt 19%', + 'USt 7%', + 'Kz66 (Vorsteuer)', + 'Zahllast' + ), ';'); + + // Monatliche Werte + for ($m = 1; $m <= 12; $m++) { + $euer->berechneAusDolibarr($jahr, $m, $m); + + $kz81 = 0; + $kz86 = 0; + $ust19 = 0; + $ust7 = 0; + + foreach ($euer->einnahmen as $einnahme) { + $ust_satz = isset($einnahme['ust_satz']) ? $einnahme['ust_satz'] : 19; + if ($ust_satz == 19) { + $kz81 += $einnahme['netto']; + $ust19 += isset($einnahme['ust']) ? $einnahme['ust'] : 0; + } elseif ($ust_satz == 7) { + $kz86 += $einnahme['netto']; + $ust7 += isset($einnahme['ust']) ? $einnahme['ust'] : 0; + } + } + + $zahllast = ($ust19 + $ust7) - $euer->vst_summe; + + fputcsv($output, array( + date('F', mktime(0, 0, 0, $m, 1, $jahr)), + number_format(round($kz81), 0, ',', ''), + number_format(round($kz86), 0, ',', ''), + number_format($ust19, 2, ',', ''), + number_format($ust7, 2, ',', ''), + number_format($euer->vst_summe, 2, ',', ''), + number_format($zahllast, 2, ',', '') + ), ';'); + } + + fclose($output); + exit; + } +} + +/* + * View + */ + +$form = new Form($db); + +llxHeader('', $langs->trans("WISOExport"), '', '', 0, 0, '', '', '', 'mod-steuer page-export-wiso'); + +print load_fiche_titre($langs->trans("WISOExport"), '', 'steuer.png@steuer'); + +// Export-Formular +print '
'; +print ''; +print ''; + +print '
'; +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; + +print '
'.$langs->trans("ExportSettings").'
'.$langs->trans("Year").''; +print ''; +print '
'.$langs->trans("ExportFormat").''; +print ''; +print '
'; +print ''; +print '
'; +print '
'; + +print '
'; + +print '
'; + +// Format-Beschreibungen +print '
'; +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; + +print '
'.$langs->trans("ExportFormatInfo").'
'.$langs->trans("WISOEUeRFormat").''.$langs->trans("WISOEUeRFormatDesc").'
'.$langs->trans("DATEVFormat").''.$langs->trans("DATEVFormatDesc").'
'.$langs->trans("UStVACSV").''.$langs->trans("UStVACSVDesc").'
'; +print '
'; + +// Vorschau +print '
'; +print '

'.$langs->trans("PreviewData").' '.$jahr.'

'; + +$euer = new EUeR($db); +$buchungen = $euer->getBuchungsliste($jahr.'-01-01', $jahr.'-12-31', 'alle'); + +print '
'; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +$count = 0; +$max_preview = 20; +foreach ($buchungen as $buchung) { + if ($count >= $max_preview) { + print ''; + break; + } + + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + $count++; +} + +print ''; +print ''; +print ''; +print ''; + +print '
'.$langs->trans("Date").''.$langs->trans("Ref").''.$langs->trans("Description").''.$langs->trans("Typ").''.$langs->trans("Netto").''.$langs->trans("VAT").''.$langs->trans("Brutto").'
... '.$langs->trans("AndMore", count($buchungen) - $max_preview).'
'.dol_print_date(strtotime($buchung['datum']), 'day').''.$buchung['ref'].''.dol_trunc($buchung['beschreibung'], 40).''; + if ($buchung['buchungstyp'] == 'einnahme') { + print ''.$langs->trans("Einnahme").''; + } else { + print ''.$langs->trans("Ausgabe").''; + } + print ''.price($buchung['netto'], 0, $langs, 1, 2, 2).''.price($buchung['steuer'], 0, $langs, 1, 2, 2).''.price($buchung['brutto'], 0, $langs, 1, 2, 2).'
'.$langs->trans("Total").': '.count($buchungen).' '.$langs->trans("Buchungen").'
'; +print '
'; + +// Hinweise +print '
'; +print '
'; +print ''.$langs->trans("ExportHinweise").':
'; +print '- '.$langs->trans("ExportHinweis1").'
'; +print '- '.$langs->trans("ExportHinweis2").'
'; +print '- '.$langs->trans("ExportHinweis3").'
'; +print '
'; + +// Zurück-Button +print '
'; +print '
'; +print ''.$langs->trans("Back").''; +print '
'; + +llxFooter(); +$db->close(); diff --git a/gewerbesteuer.php b/gewerbesteuer.php new file mode 100644 index 0000000..8551e41 --- /dev/null +++ b/gewerbesteuer.php @@ -0,0 +1,285 @@ + 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { + $i--; + $j--; +} +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) { + $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +} +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) { + $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +} +if (!$res && file_exists("../main.inc.php")) { + $res = @include "../main.inc.php"; +} +if (!$res && file_exists("../../main.inc.php")) { + $res = @include "../../main.inc.php"; +} +if (!$res && file_exists("../../../main.inc.php")) { + $res = @include "../../../main.inc.php"; +} +if (!$res) { + die("Include of main fails"); +} + +require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; +dol_include_once('/steuer/class/euer.class.php'); + +$langs->loadLangs(array("steuer@steuer", "bills", "compta")); + +$jahr = GETPOSTINT('jahr'); +if (empty($jahr)) { + $jahr = date('Y'); +} + +$action = GETPOST('action', 'aZ09'); + +// Einstellbare Parameter +$hebesatz = GETPOSTFLOAT('hebesatz'); +if (empty($hebesatz)) { + $hebesatz = getDolGlobalString('STEUER_GEWERBE_HEBESATZ', 400); +} +$hinzurechnungen = GETPOSTFLOAT('hinzurechnungen'); +$kuerzungen = GETPOSTFLOAT('kuerzungen'); + +/* + * View + */ + +$form = new Form($db); +$euer = new EUeR($db); +$euer->berechneAusDolibarr($jahr); + +// Gewerbesteuer-Berechnung +$gewinn_euer = $euer->gewinn; +$freibetrag = 24500; // Freibetrag für Einzelunternehmen/Personengesellschaften + +// Gewerbeertrag berechnen +$gewerbeertrag_vor_freibetrag = $gewinn_euer + $hinzurechnungen - $kuerzungen; +$gewerbeertrag = max(0, $gewerbeertrag_vor_freibetrag - $freibetrag); + +// Steuermessbetrag (3,5% vom Gewerbeertrag) +$steuermesszahl = 3.5; +$steuermessbetrag = $gewerbeertrag * $steuermesszahl / 100; + +// Gewerbesteuer +$gewerbesteuer = $steuermessbetrag * $hebesatz / 100; + +// Anrechnung auf ESt (max. das 4-fache des Steuermessbetrags, § 35 EStG) +$anrechnung_est = min($gewerbesteuer, $steuermessbetrag * 4); + +// Effektive Gewerbesteuer nach Anrechnung +$gewerbesteuer_effektiv = $gewerbesteuer - $anrechnung_est; + +llxHeader('', $langs->trans("Gewerbesteuer"), '', '', 0, 0, '', '', '', 'mod-steuer page-gewerbesteuer'); + +print load_fiche_titre($langs->trans("Gewerbesteuer")." ".$jahr, '', 'steuer.png@steuer'); + +// Formular +print '
'; +print ''; +print ''; + +print '
'; +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; + +print '
'.$langs->trans("Parameter").'
'.$langs->trans("Year").''; +print ''; +print '
'.$langs->trans("Hebesatz").' (%)'; +print ''; +print ' '.$langs->trans("HebesatzHinweis").''; +print '
'.$langs->trans("Hinzurechnungen").' (§ 8 GewStG)'; +print ''; +print ' EUR '.$langs->trans("HinzurechnungenHinweis").''; +print '
'.$langs->trans("Kuerzungen").' (§ 9 GewStG)'; +print ''; +print ' EUR '.$langs->trans("KuerzungenHinweis").''; +print '
'; +print ''; +print '
'; +print '
'; + +print '
'; + +print '
'; + +// Berechnungstabelle +print '
'; +print ''; +print ''; +print ''; +print ''; +print ''; + +// Gewinn aus EÜR +print ''; +print ''; +print ''; +$color = $gewinn_euer >= 0 ? '' : 'amountremaintopay'; +print ''; +print ''; + +// Hinzurechnungen +print ''; +print ''; +print ''; +print ''; +print ''; + +// Kürzungen +print ''; +print ''; +print ''; +print ''; +print ''; + +// Gewerbeertrag vor Freibetrag +print ''; +print ''; +print ''; +print ''; +print ''; + +// Freibetrag +print ''; +print ''; +print ''; +print ''; +print ''; + +// Gewerbeertrag +print ''; +print ''; +print ''; +print ''; +print ''; + +// Steuermessbetrag +print ''; +print ''; +print ''; +print ''; +print ''; + +// Hebesatz +print ''; +print ''; +print ''; +print ''; +print ''; + +// Gewerbesteuer +print ''; +print ''; +print ''; +print ''; +print ''; + +print '
'.$langs->trans("GewerbesteuerBerechnung").' '.$jahr.''.$langs->trans("Betrag").' EUR
1.'.$langs->trans("GewinnAusEUeR").''.price($gewinn_euer, 0, $langs, 1, 2, 2).'
2.'.$langs->trans("Hinzurechnungen").' (§ 8 GewStG)
z.B. Zinsen, Mieten, Pachten, Lizenzen (anteilig)
+ '.price($hinzurechnungen, 0, $langs, 1, 2, 2).'
3.'.$langs->trans("Kuerzungen").' (§ 9 GewStG)
z.B. 1,2% des Einheitswerts bei Grundstücken
- '.price($kuerzungen, 0, $langs, 1, 2, 2).'
4.'.$langs->trans("GewerbeertragVorFreibetrag").''.price($gewerbeertrag_vor_freibetrag, 0, $langs, 1, 2, 2).'
5.'.$langs->trans("Freibetrag").'
'.$langs->trans("FreibetragHinweis").'
- '.price($freibetrag, 0, $langs, 1, 2, 2).'
6.'.$langs->trans("Gewerbeertrag").''.price($gewerbeertrag, 0, $langs, 1, 2, 2).'
7.'.$langs->trans("Steuermessbetrag").' ('.$steuermesszahl.'%)'.price($steuermessbetrag, 0, $langs, 1, 2, 2).'
8.'.$langs->trans("Hebesatz").' der Gemeinde'.$hebesatz.' %
9.'.$langs->trans("Gewerbesteuer").' (Zeile 7 x Zeile 8 / 100)'.price($gewerbesteuer, 0, $langs, 1, 2, 2).'
'; +print '
'; + +print '
'; + +// Anrechnung auf Einkommensteuer +print '
'; +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +$effektiv_color = $gewerbesteuer_effektiv > 0 ? '' : 'amountpaymentcomplete'; +print ''; +print ''; + +print '
'.$langs->trans("AnrechnungESt").' (§ 35 EStG)
'.$langs->trans("Steuermessbetrag").' x 4 (maximale Anrechnung)'.price($steuermessbetrag * 4, 0, $langs, 1, 2, 2).' EUR
'.$langs->trans("TatsaechlicheGewerbesteuer").''.price($gewerbesteuer, 0, $langs, 1, 2, 2).' EUR
'.$langs->trans("AnrechenbareGewerbesteuer").'
(der niedrigere Betrag)
'.price($anrechnung_est, 0, $langs, 1, 2, 2).' EUR
'.$langs->trans("EffektiveGewerbesteuer").'
(Gewerbesteuer - Anrechnung)
'.price($gewerbesteuer_effektiv, 0, $langs, 1, 2, 2).' EUR
'; +print '
'; + +// Hinweise +print '
'; +print '
'; +print ''.$langs->trans("Hinweise").':
'; +print '- '.$langs->trans("GewerbesteuerHinweis1").'
'; +print '- '.$langs->trans("GewerbesteuerHinweis2").'
'; +print '- '.$langs->trans("GewerbesteuerHinweis3").'
'; +print '- '.$langs->trans("GewerbesteuerHinweis4").'
'; +print '
'; + +// Info-Box Hebesätze +print '
'; +print '
'; +print ''.$langs->trans("HebesaetzeInfo").':
'; +print $langs->trans("HebesaetzeInfoText"); +print '
'; + +// Zurück-Button +print '
'; +print '
'; +print ''.$langs->trans("Back").''; +print '
'; + +llxFooter(); +$db->close(); diff --git a/img/README.md b/img/README.md new file mode 100755 index 0000000..0767634 --- /dev/null +++ b/img/README.md @@ -0,0 +1,14 @@ + +Directory for module image files +-------------------------------- + +You can put here the .png files of your module: + + +If the picto of your module is an image (property $picto has been set to 'steuer.png@steuer', you can put into this +directory a .png file called *object_steuer.png* (16x16 or 32x32 pixels) + + +If the picto of an object is an image (property $picto of the object.class.php has been set to 'myobject.png@steuer', then you can put into this +directory a .png file called *object_myobject.png* (16x16 or 32x32 pixels) + diff --git a/konten.php b/konten.php new file mode 100644 index 0000000..0d7ef3f --- /dev/null +++ b/konten.php @@ -0,0 +1,164 @@ + 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { + $i--; + $j--; +} +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) { + $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +} +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) { + $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +} +if (!$res && file_exists("../main.inc.php")) { + $res = @include "../main.inc.php"; +} +if (!$res && file_exists("../../main.inc.php")) { + $res = @include "../../main.inc.php"; +} +if (!$res && file_exists("../../../main.inc.php")) { + $res = @include "../../../main.inc.php"; +} +if (!$res) { + die("Include of main fails"); +} + +require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php'; + +$langs->loadLangs(array("steuer@steuer", "bills", "compta")); + +$action = GETPOST('action', 'aZ09'); +$kategorie = GETPOST('kategorie', 'alpha'); + +/* + * View + */ + +$form = new Form($db); + +llxHeader('', $langs->trans("Kontenplan"), '', '', 0, 0, '', '', '', 'mod-steuer page-konten'); + +print load_fiche_titre($langs->trans("Kontenplan").' (SKR03)', '', 'steuer.png@steuer'); + +// Filter +print '
'; +print ''; +print '
'; +print ''; +print ' '; +print '
'; +print '
'; + +print '
'; + +// Konten-Tabelle +print '
'; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +$sql = "SELECT rowid, kontonummer, bezeichnung, kategorie, euer_zeile, ust_kennzeichen, aktiv"; +$sql .= " FROM ".MAIN_DB_PREFIX."steuer_konto"; +$sql .= " WHERE entity = ".((int) $conf->entity); +if ($kategorie) { + $sql .= " AND kategorie = '".$db->escape($kategorie)."'"; +} +$sql .= " ORDER BY kontonummer"; + +$resql = $db->query($sql); +if ($resql) { + $num = $db->num_rows($resql); + + if ($num > 0) { + $last_kategorie = ''; + while ($obj = $db->fetch_object($resql)) { + // Zwischenüberschrift bei Kategoriewechsel + if ($obj->kategorie != $last_kategorie && empty($kategorie)) { + print ''; + print ''; + print ''; + $last_kategorie = $obj->kategorie; + } + + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + } + } else { + print ''; + print ''; + print ''; + } +} else { + dol_print_error($db); +} + +print '
'.$langs->trans("Kontonummer").''.$langs->trans("Bezeichnung").''.$langs->trans("Kategorie").''.$langs->trans("EUeRZeile").''.$langs->trans("UStKz").''.$langs->trans("Status").'
'.($obj->kategorie == 'einnahme' ? $langs->trans("Einnahmekonten") : $langs->trans("Ausgabekonten")).'
'.$obj->kontonummer.''.$obj->bezeichnung.''; + if ($obj->kategorie == 'einnahme') { + print ''.$langs->trans("Einnahme").''; + } else { + print ''.$langs->trans("Ausgabe").''; + } + print ''.($obj->euer_zeile ? $obj->euer_zeile : '-').''.($obj->ust_kennzeichen ? 'Kz '.$obj->ust_kennzeichen : '-').''; + if ($obj->aktiv) { + print ''.$langs->trans("Active").''; + } else { + print ''.$langs->trans("Inactive").''; + } + print '
'.$langs->trans("NoRecordFound").'
'; +print '
'; + +// Legende +print '
'; +print '
'; +print ''.$langs->trans("Legende").':
'; +print ''; +print ''; +print ''; +print '
'.$langs->trans("EUeRZeile").':'.$langs->trans("EUeRZeileDesc").'
'.$langs->trans("UStKz").':'.$langs->trans("UStKzDesc").'
'; +print '
'; + +// SKR03 Info +print '
'; +print '
'; +print ''.$langs->trans("SKR03Info").':
'; +print $langs->trans("SKR03InfoText"); +print '
'; + +// Zurück-Button +print '
'; +print '
'; +print ''.$langs->trans("Back").''; +print '
'; + +llxFooter(); +$db->close(); diff --git a/langs/de_DE/steuer.lang b/langs/de_DE/steuer.lang new file mode 100644 index 0000000..2408541 --- /dev/null +++ b/langs/de_DE/steuer.lang @@ -0,0 +1,170 @@ +# Copyright (C) 2026 Eduard Wisch +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Deutsche Sprachdatei für EÜR Modul + +# +# Modul +# +ModuleSteuerName = EÜR Deutschland +ModuleSteuerDesc = Einnahmen-Überschuss-Rechnung für Deutschland - Steuerjahr 2025 + +# +# Admin/Setup +# +SteuerSetup = EÜR Einstellungen +SteuerAbout = Über EÜR Modul +Settings = Einstellungen + +# +# Hauptnavigation +# +EUeRUebersicht = EÜR Übersicht +Buchungen = Buchungen +NeueBuchung = Neue Buchung +AnlageEUeR = Anlage EÜR +UStVA = USt-Voranmeldung +Gewerbesteuer = Gewerbesteuer +WISOExport = WISO Export +Kontenplan = Kontenplan + +# +# Allgemein +# +Period = Zeitraum +SelectPeriod = Zeitraum wählen +WholeYear = Ganzes Jahr +QuickAccess = Schnellzugriff +Year = Jahr +Month = Monat +Summary = Zusammenfassung +Total = Summe +Amount = Betrag +Status = Status +Draft = Entwurf +Active = Aktiv +Inactive = Inaktiv +Calculate = Berechnen +Filter = Filtern +Export = Exportieren +PreviewData = Datenvorschau + +# +# EÜR spezifisch +# +Einnahmen = Betriebseinnahmen +Ausgaben = Betriebsausgaben +Einnahme = Einnahme +Ausgabe = Ausgabe +TotalEinnahmen = Summe Einnahmen +TotalAusgaben = Summe Ausgaben +Gewinn = Gewinn +Verlust = Verlust +ErgebnisEUeR = EÜR Ergebnis +GewinnAusEUeR = Gewinn aus EÜR + +# +# Buchungen +# +Buchung = Buchung +EditBuchung = Buchung bearbeiten +DeleteBuchung = Buchung löschen +ConfirmDeleteBuchung = Möchten Sie diese Buchung wirklich löschen? +BuchungCreated = Buchung wurde erstellt +BuchungUpdated = Buchung wurde aktualisiert +BuchungDeleted = Buchung wurde gelöscht +Belegnummer = Belegnummer +Typ = Art/Typ +Netto = Netto +Brutto = Brutto + +# +# Umsatzsteuer +# +UmsatzsteuerVorsteuer = Umsatzsteuer / Vorsteuer +UmsatzsteuerGesamt = Umsatzsteuer gesamt +VorsteuerGesamt = Vorsteuer gesamt +Zahllast = USt-Zahllast +Erstattung = USt-Erstattung +Kz81 = Kz 81 +Kz86 = Kz 86 +Kz66 = Kz 66 +USt19 = USt 19% +USt7 = USt 7% +UStVASummary = UStVA Zusammenfassung +KennzahlenErklaerung = Kennzahlen-Erklärung + +# +# Gewerbesteuer +# +GewerbesteuerBerechnung = Gewerbesteuer-Berechnung +Hebesatz = Hebesatz +HebesatzHinweis = Gemeinde-Hebesatz (z.B. 400 für 400%) +Hinzurechnungen = Hinzurechnungen +HinzurechnungenHinweis = z.B. 25% der Zinsen, Mieten, Pachten, Lizenzen +Kuerzungen = Kürzungen +KuerzungenHinweis = z.B. 1,2% des Einheitswerts für Grundstücke +GewerbeertragVorFreibetrag = Gewerbeertrag vor Freibetrag +Freibetrag = Freibetrag +FreibetragHinweis = 24.500 EUR für Einzelunternehmen und Personengesellschaften +Gewerbeertrag = Gewerbeertrag +Steuermessbetrag = Steuermessbetrag +AnrechnungESt = Anrechnung auf Einkommensteuer +AnrechenbareGewerbesteuer = Anrechenbare Gewerbesteuer +TatsaechlicheGewerbesteuer = Tatsächliche Gewerbesteuer +EffektiveGewerbesteuer = Effektive Gewerbesteuer +Hinweise = Hinweise +GewerbesteuerHinweis1 = Der Freibetrag von 24.500 EUR gilt für Einzelunternehmen und Personengesellschaften +GewerbesteuerHinweis2 = Die Steuermesszahl beträgt einheitlich 3,5% +GewerbesteuerHinweis3 = Die Anrechnung auf die ESt ist auf das 4-fache des Steuermessbetrags begrenzt (§ 35 EStG) +GewerbesteuerHinweis4 = Der individuelle Hebesatz kann bei Ihrer Gemeinde erfragt werden +HebesaetzeInfo = Informationen zu Hebesätzen +HebesaetzeInfoText = Die Hebesätze variieren je nach Gemeinde. Typische Werte: Großstädte 400-500%, ländliche Gemeinden 300-400%. Den genauen Hebesatz Ihrer Gemeinde finden Sie im Grundsteuerbescheid oder direkt bei der Gemeinde. + +# +# Anlage EÜR +# +Zeile = Zeile +Bezeichnung = Bezeichnung +Hinweis = Hinweis +EUeRHinweis1 = Die Beträge werden automatisch aus Ihren Dolibarr-Buchungen berechnet +EUeRHinweis2 = Für die offizielle Anlage EÜR prüfen Sie bitte alle Werte sorgfältig +EUeRHinweis3 = Exportieren Sie die Daten für WISO Steuer über den WISO Export + +# +# WISO Export +# +ExportSettings = Export-Einstellungen +ExportFormat = Export-Format +ExportFormatInfo = Informationen zu den Export-Formaten +WISOEUeRFormat = WISO EÜR Format (CSV) +WISOEUeRFormatDesc = CSV-Datei mit allen Buchungen, kompatibel mit WISO Steuer für den Import der EÜR-Daten +DATEVFormat = DATEV Format (CSV) +DATEVFormatDesc = Vereinfachtes DATEV-Format für den Import in Buchhaltungssoftware +UStVACSV = UStVA Werte (CSV) +UStVACSVDesc = Monatliche UStVA-Kennzahlen als CSV für die manuelle Eingabe in ELSTER oder WISO +AndMore = und %s weitere +ExportHinweise = Export-Hinweise +ExportHinweis1 = Die exportierten Daten dienen als Grundlage für Ihre Steuersoftware +ExportHinweis2 = Prüfen Sie alle Werte vor der Übernahme in WISO Steuer +ExportHinweis3 = Bei Fragen wenden Sie sich an Ihren Steuerberater +WISOHinweis = ELSTER/WISO Hinweis +WISOExportHinweis = Für die elektronische Übermittlung der UStVA verwenden Sie bitte WISO Steuer oder Elster Online. Die hier angezeigten Werte können Sie in WISO Steuer übernehmen. + +# +# Kontenplan +# +Kontonummer = Kontonummer +EUeRZeile = EÜR-Zeile +UStKz = USt-Kz +Einnahmekonten = Einnahmekonten +Ausgabekonten = Ausgabekonten +Legende = Legende +EUeRZeileDesc = Zeile in der offiziellen Anlage EÜR +UStKzDesc = Kennzahl für die Umsatzsteuer-Voranmeldung +SKR03Info = Über den Kontenrahmen +SKR03InfoText = Dieses Modul verwendet einen vereinfachten SKR03-Kontenrahmen, der für die EÜR optimiert ist. Die Konten sind den entsprechenden Zeilen der Anlage EÜR und den UStVA-Kennzahlen zugeordnet. diff --git a/langs/en_US/steuer.lang b/langs/en_US/steuer.lang new file mode 100755 index 0000000..c7237f1 --- /dev/null +++ b/langs/en_US/steuer.lang @@ -0,0 +1,170 @@ +# Copyright (C) 2026 Eduard Wisch +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# English language file for EÜR Module (German Tax) + +# +# Module +# +ModuleSteuerName = EÜR Germany +ModuleSteuerDesc = Income-Surplus Calculation for Germany - Tax Year 2025 + +# +# Admin/Setup +# +SteuerSetup = EÜR Settings +SteuerAbout = About EÜR Module +Settings = Settings + +# +# Main Navigation +# +EUeRUebersicht = EÜR Overview +Buchungen = Transactions +NeueBuchung = New Transaction +AnlageEUeR = EÜR Report +UStVA = VAT Return +Gewerbesteuer = Trade Tax +WISOExport = WISO Export +Kontenplan = Chart of Accounts + +# +# General +# +Period = Period +SelectPeriod = Select Period +WholeYear = Whole Year +QuickAccess = Quick Access +Year = Year +Month = Month +Summary = Summary +Total = Total +Amount = Amount +Status = Status +Draft = Draft +Active = Active +Inactive = Inactive +Calculate = Calculate +Filter = Filter +Export = Export +PreviewData = Data Preview + +# +# EÜR specific +# +Einnahmen = Business Income +Ausgaben = Business Expenses +Einnahme = Income +Ausgabe = Expense +TotalEinnahmen = Total Income +TotalAusgaben = Total Expenses +Gewinn = Profit +Verlust = Loss +ErgebnisEUeR = EÜR Result +GewinnAusEUeR = Profit from EÜR + +# +# Transactions +# +Buchung = Transaction +EditBuchung = Edit Transaction +DeleteBuchung = Delete Transaction +ConfirmDeleteBuchung = Do you really want to delete this transaction? +BuchungCreated = Transaction created +BuchungUpdated = Transaction updated +BuchungDeleted = Transaction deleted +Belegnummer = Receipt Number +Typ = Type +Netto = Net +Brutto = Gross + +# +# VAT +# +UmsatzsteuerVorsteuer = VAT / Input Tax +UmsatzsteuerGesamt = Total VAT +VorsteuerGesamt = Total Input Tax +Zahllast = VAT Payable +Erstattung = VAT Refund +Kz81 = Kz 81 +Kz86 = Kz 86 +Kz66 = Kz 66 +USt19 = VAT 19% +USt7 = VAT 7% +UStVASummary = VAT Return Summary +KennzahlenErklaerung = Key Figures Explanation + +# +# Trade Tax +# +GewerbesteuerBerechnung = Trade Tax Calculation +Hebesatz = Assessment Rate +HebesatzHinweis = Municipal rate (e.g. 400 for 400%) +Hinzurechnungen = Add-backs +HinzurechnungenHinweis = e.g. 25% of interest, rent, royalties +Kuerzungen = Deductions +KuerzungenHinweis = e.g. 1.2% of property value +GewerbeertragVorFreibetrag = Trade Income before Allowance +Freibetrag = Allowance +FreibetragHinweis = EUR 24,500 for sole proprietors and partnerships +Gewerbeertrag = Trade Income +Steuermessbetrag = Tax Base Amount +AnrechnungESt = Credit against Income Tax +AnrechenbareGewerbesteuer = Creditable Trade Tax +TatsaechlicheGewerbesteuer = Actual Trade Tax +EffektiveGewerbesteuer = Effective Trade Tax +Hinweise = Notes +GewerbesteuerHinweis1 = The EUR 24,500 allowance applies to sole proprietors and partnerships +GewerbesteuerHinweis2 = The tax multiplier is uniformly 3.5% +GewerbesteuerHinweis3 = Income tax credit is limited to 4x the tax base amount (§ 35 EStG) +GewerbesteuerHinweis4 = The specific assessment rate can be obtained from your municipality +HebesaetzeInfo = Assessment Rate Information +HebesaetzeInfoText = Assessment rates vary by municipality. Typical values: major cities 400-500%, rural municipalities 300-400%. Find your exact rate in your property tax notice or contact your municipality. + +# +# EÜR Report +# +Zeile = Line +Bezeichnung = Description +Hinweis = Note +EUeRHinweis1 = Amounts are automatically calculated from your Dolibarr transactions +EUeRHinweis2 = Please verify all values carefully for the official EÜR report +EUeRHinweis3 = Export data for WISO Steuer via the WISO Export + +# +# WISO Export +# +ExportSettings = Export Settings +ExportFormat = Export Format +ExportFormatInfo = Export Format Information +WISOEUeRFormat = WISO EÜR Format (CSV) +WISOEUeRFormatDesc = CSV file with all transactions, compatible with WISO Steuer for EÜR data import +DATEVFormat = DATEV Format (CSV) +DATEVFormatDesc = Simplified DATEV format for import into accounting software +UStVACSV = VAT Return Values (CSV) +UStVACSVDesc = Monthly VAT return key figures as CSV for manual entry in ELSTER or WISO +AndMore = and %s more +ExportHinweise = Export Notes +ExportHinweis1 = The exported data serves as a basis for your tax software +ExportHinweis2 = Verify all values before importing into WISO Steuer +ExportHinweis3 = Consult your tax advisor for questions +WISOHinweis = ELSTER/WISO Note +WISOExportHinweis = For electronic VAT return submission, please use WISO Steuer or Elster Online. The values shown here can be imported into WISO Steuer. + +# +# Chart of Accounts +# +Kontonummer = Account Number +EUeRZeile = EÜR Line +UStKz = VAT Code +Einnahmekonten = Income Accounts +Ausgabekonten = Expense Accounts +Legende = Legend +EUeRZeileDesc = Line in the official EÜR report +UStKzDesc = Key figure for VAT return +SKR03Info = About the Chart of Accounts +SKR03InfoText = This module uses a simplified SKR03 chart of accounts optimized for EÜR. Accounts are assigned to the corresponding EÜR report lines and VAT return key figures. diff --git a/lib/steuer.lib.php b/lib/steuer.lib.php new file mode 100755 index 0000000..fa685f5 --- /dev/null +++ b/lib/steuer.lib.php @@ -0,0 +1,85 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file steuer/lib/steuer.lib.php + * \ingroup steuer + * \brief Library files with common functions for Steuer + */ + +/** + * Prepare admin pages header + * + * @return array + */ +function steuerAdminPrepareHead() +{ + global $langs, $conf; + + // global $db; + // $extrafields = new ExtraFields($db); + // $extrafields->fetch_name_optionals_label('myobject'); + + $langs->load("steuer@steuer"); + + $h = 0; + $head = array(); + + $head[$h][0] = dol_buildpath("/steuer/admin/setup.php", 1); + $head[$h][1] = $langs->trans("Settings"); + $head[$h][2] = 'settings'; + $h++; + + /* + $head[$h][0] = dol_buildpath("/steuer/admin/myobject_extrafields.php", 1); + $head[$h][1] = $langs->trans("ExtraFields"); + $nbExtrafields = (isset($extrafields->attributes['myobject']['label']) && is_countable($extrafields->attributes['myobject']['label'])) ? count($extrafields->attributes['myobject']['label']) : 0; + if ($nbExtrafields > 0) { + $head[$h][1] .= '' . $nbExtrafields . ''; + } + $head[$h][2] = 'myobject_extrafields'; + $h++; + + $head[$h][0] = dol_buildpath("/steuer/admin/myobjectline_extrafields.php", 1); + $head[$h][1] = $langs->trans("ExtraFieldsLines"); + $nbExtrafields = (isset($extrafields->attributes['myobjectline']['label']) && is_countable($extrafields->attributes['myobjectline']['label'])) ? count($extrafields->attributes['myobject']['label']) : 0; + if ($nbExtrafields > 0) { + $head[$h][1] .= '' . $nbExtrafields . ''; + } + $head[$h][2] = 'myobject_extrafieldsline'; + $h++; + */ + + $head[$h][0] = dol_buildpath("/steuer/admin/about.php", 1); + $head[$h][1] = $langs->trans("About"); + $head[$h][2] = 'about'; + $h++; + + // Show more tabs from modules + // Entries must be declared in modules descriptor with line + //$this->tabs = array( + // 'entity:+tabname:Title:@steuer:/steuer/mypage.php?id=__ID__' + //); // to add new tab + //$this->tabs = array( + // 'entity:-tabname:Title:@steuer:/steuer/mypage.php?id=__ID__' + //); // to remove a tab + complete_head_from_modules($conf, $langs, null, $head, $h, 'steuer@steuer'); + + complete_head_from_modules($conf, $langs, null, $head, $h, 'steuer@steuer', 'remove'); + + return $head; +} diff --git a/modulebuilder.txt b/modulebuilder.txt new file mode 100755 index 0000000..670a177 --- /dev/null +++ b/modulebuilder.txt @@ -0,0 +1,3 @@ +# DO NOT DELETE THIS FILE MANUALLY +# File to flag module built using official module template. +# When this file is present into a module directory, you can edit it with the module builder tool. \ No newline at end of file diff --git a/sql/data.sql b/sql/data.sql new file mode 100644 index 0000000..e849ca5 --- /dev/null +++ b/sql/data.sql @@ -0,0 +1,83 @@ +-- Copyright (C) 2026 Eduard Wisch +-- Standard EÜR-Konten nach SKR03 + +-- EINNAHMEN +INSERT IGNORE INTO llx_steuer_konto (kontonummer, bezeichnung, kategorie, euer_zeile, ust_kennzeichen, entity) VALUES +('8400', 'Erlöse 19% USt', 'einnahme', 14, '81', 1), +('8300', 'Erlöse 7% USt', 'einnahme', 14, '86', 1), +('8100', 'Steuerfreie Umsätze Inland', 'einnahme', 10, NULL, 1), +('8120', 'Steuerfreie igL', 'einnahme', 11, '41', 1), +('8150', 'Steuerfreie Ausfuhrlieferungen', 'einnahme', 12, '44', 1), +('8200', 'Erlöse ohne USt §19', 'einnahme', 14, NULL, 1), +('8500', 'Provisionserlöse', 'einnahme', 14, '81', 1), +('8600', 'Sonstige Erlöse', 'einnahme', 16, '81', 1), +('8700', 'Erlöse aus VuV', 'einnahme', 17, NULL, 1), +('8800', 'Zinserträge', 'einnahme', 18, NULL, 1), +('8900', 'Privatentnahmen Sachen', 'einnahme', 19, '81', 1), +('8910', 'Private Kfz-Nutzung', 'einnahme', 19, '81', 1), +('8920', 'Private Telefonnutzung', 'einnahme', 19, '81', 1); + +-- AUSGABEN - Wareneinkauf +INSERT IGNORE INTO llx_steuer_konto (kontonummer, bezeichnung, kategorie, euer_zeile, ust_kennzeichen, entity) VALUES +('3400', 'Wareneingang 19% VSt', 'ausgabe', 26, '66', 1), +('3300', 'Wareneingang 7% VSt', 'ausgabe', 26, '66', 1), +('3100', 'Wareneingang steuerfrei', 'ausgabe', 26, NULL, 1); + +-- AUSGABEN - Personal +INSERT IGNORE INTO llx_steuer_konto (kontonummer, bezeichnung, kategorie, euer_zeile, ust_kennzeichen, entity) VALUES +('4100', 'Löhne und Gehälter', 'ausgabe', 31, NULL, 1), +('4130', 'Gesetzliche Sozialaufwendungen', 'ausgabe', 32, NULL, 1), +('4140', 'Freiwillige Sozialaufwendungen', 'ausgabe', 33, NULL, 1); + +-- AUSGABEN - Raumkosten +INSERT IGNORE INTO llx_steuer_konto (kontonummer, bezeichnung, kategorie, euer_zeile, ust_kennzeichen, entity) VALUES +('4200', 'Raumkosten/Miete', 'ausgabe', 34, '66', 1), +('4210', 'Miete Geschäftsräume', 'ausgabe', 34, '66', 1), +('4230', 'Heizung', 'ausgabe', 34, '66', 1), +('4240', 'Gas, Strom, Wasser', 'ausgabe', 34, '66', 1), +('4250', 'Reinigung', 'ausgabe', 34, '66', 1), +('4260', 'Instandhaltung Räume', 'ausgabe', 34, '66', 1); + +-- AUSGABEN - Sonstige Betriebsausgaben +INSERT IGNORE INTO llx_steuer_konto (kontonummer, bezeichnung, kategorie, euer_zeile, ust_kennzeichen, entity) VALUES +('4500', 'Fahrzeugkosten', 'ausgabe', 51, '66', 1), +('4510', 'Kfz-Steuer', 'ausgabe', 51, NULL, 1), +('4520', 'Kfz-Versicherung', 'ausgabe', 51, NULL, 1), +('4530', 'Kraftstoff', 'ausgabe', 51, '66', 1), +('4540', 'Kfz-Reparaturen', 'ausgabe', 51, '66', 1), +('4580', 'Sonstige Kfz-Kosten', 'ausgabe', 51, '66', 1), +('4600', 'Werbekosten', 'ausgabe', 53, '66', 1), +('4610', 'Geschenke abzugsfähig', 'ausgabe', 54, '66', 1), +('4630', 'Geschenke nicht abzugsfähig', 'ausgabe', 55, '66', 1), +('4650', 'Bewirtungskosten 70%', 'ausgabe', 56, '66', 1), +('4660', 'Reisekosten Unternehmer', 'ausgabe', 57, NULL, 1), +('4670', 'Reisekosten Arbeitnehmer', 'ausgabe', 58, '66', 1), +('4700', 'Porto', 'ausgabe', 49, '66', 1), +('4710', 'Telefon', 'ausgabe', 49, '66', 1), +('4750', 'Bürobedarf', 'ausgabe', 49, '66', 1), +('4780', 'Fremdleistungen', 'ausgabe', 49, '66', 1), +('4790', 'Sonstige Betriebsausgaben', 'ausgabe', 49, '66', 1), +('4800', 'Reparatur/Instandhaltung', 'ausgabe', 39, '66', 1), +('4830', 'Versicherungen', 'ausgabe', 46, NULL, 1), +('4840', 'Beiträge IHK/Verbände', 'ausgabe', 47, NULL, 1), +('4850', 'Fortbildungskosten', 'ausgabe', 48, '66', 1), +('4900', 'Rechts- und Beratungskosten', 'ausgabe', 50, '66', 1), +('4910', 'Buchführungskosten', 'ausgabe', 50, '66', 1), +('4920', 'Jahresabschlusskosten', 'ausgabe', 50, '66', 1), +('4940', 'Bankgebühren', 'ausgabe', 48, NULL, 1), +('4950', 'Nebenkosten Geldverkehr', 'ausgabe', 48, NULL, 1), +('4960', 'Miete für Einrichtungen', 'ausgabe', 38, '66', 1), +('4970', 'Leasing', 'ausgabe', 38, '66', 1), +('4980', 'Software/Lizenzen', 'ausgabe', 39, '66', 1); + +-- AUSGABEN - AfA +INSERT IGNORE INTO llx_steuer_konto (kontonummer, bezeichnung, kategorie, euer_zeile, ust_kennzeichen, entity) VALUES +('4820', 'AfA Sachanlagen', 'ausgabe', 36, NULL, 1), +('4822', 'AfA immaterielle WG', 'ausgabe', 37, NULL, 1), +('4824', 'AfA GWG', 'ausgabe', 38, NULL, 1), +('4826', 'Sonderabschreibungen', 'ausgabe', 38, NULL, 1); + +-- AUSGABEN - Zinsen +INSERT IGNORE INTO llx_steuer_konto (kontonummer, bezeichnung, kategorie, euer_zeile, ust_kennzeichen, entity) VALUES +('2100', 'Zinsaufwendungen', 'ausgabe', 45, NULL, 1), +('2110', 'Zinsen langfristige Darlehen', 'ausgabe', 45, NULL, 1); diff --git a/sql/dolibarr_allversions.sql b/sql/dolibarr_allversions.sql new file mode 100755 index 0000000..6e680f2 --- /dev/null +++ b/sql/dolibarr_allversions.sql @@ -0,0 +1,202 @@ +-- +-- Script run when an upgrade of Dolibarr is done. Whatever is the Dolibarr version. +-- EÜR Modul für Deutschland 2025 +-- + +-- ============================================================================ +-- Kontenrahmen (SKR03 basiert für EÜR) +-- ============================================================================ +CREATE TABLE IF NOT EXISTS llx_steuer_konto ( + rowid INTEGER AUTO_INCREMENT PRIMARY KEY, + kontonummer VARCHAR(10) NOT NULL, + bezeichnung VARCHAR(255) NOT NULL, + kategorie VARCHAR(50) NOT NULL, -- 'einnahme', 'ausgabe', 'ust', 'vorsteuer' + euer_zeile INTEGER DEFAULT NULL, -- Zeile in Anlage EÜR + ust_kennzeichen VARCHAR(10) DEFAULT NULL, -- USt-Kennzeichen für UStVA + aktiv TINYINT(1) DEFAULT 1, + entity INTEGER DEFAULT 1, + UNIQUE KEY uk_konto_nummer (kontonummer, entity) +) ENGINE=InnoDB; + +-- ============================================================================ +-- EÜR Buchungen +-- ============================================================================ +CREATE TABLE IF NOT EXISTS llx_steuer_buchung ( + rowid INTEGER AUTO_INCREMENT PRIMARY KEY, + ref VARCHAR(30) NOT NULL, -- Buchungsnummer + datum DATE NOT NULL, -- Belegdatum + belegnummer VARCHAR(50) DEFAULT NULL, -- Externe Belegnummer + beschreibung VARCHAR(255) NOT NULL, + fk_konto INTEGER NOT NULL, -- Verweis auf llx_steuer_konto + betrag_netto DOUBLE(24,8) DEFAULT 0, + betrag_ust DOUBLE(24,8) DEFAULT 0, -- USt/VSt Betrag + betrag_brutto DOUBLE(24,8) DEFAULT 0, + ust_satz DOUBLE(5,2) DEFAULT 0, -- 0, 7, 19 + typ VARCHAR(20) NOT NULL, -- 'einnahme', 'ausgabe' + zahlungsart VARCHAR(30) DEFAULT NULL, -- 'bar', 'bank', 'paypal', etc. + fk_soc INTEGER DEFAULT NULL, -- Verknüpfung zu Kunde/Lieferant + fk_facture INTEGER DEFAULT NULL, -- Verknüpfung zu Rechnung + fk_facture_fourn INTEGER DEFAULT NULL, -- Verknüpfung zu Lieferantenrechnung + note_private TEXT, + date_creation DATETIME, + tms TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + fk_user_creat INTEGER, + fk_user_modif INTEGER, + status TINYINT(4) DEFAULT 1, -- 0=Entwurf, 1=Gebucht + entity INTEGER DEFAULT 1, + INDEX idx_buchung_datum (datum), + INDEX idx_buchung_konto (fk_konto), + INDEX idx_buchung_typ (typ), + INDEX idx_buchung_ref (ref) +) ENGINE=InnoDB; + +-- ============================================================================ +-- USt-Voranmeldung Perioden +-- ============================================================================ +CREATE TABLE IF NOT EXISTS llx_steuer_ustva ( + rowid INTEGER AUTO_INCREMENT PRIMARY KEY, + jahr INTEGER NOT NULL, + periode VARCHAR(10) NOT NULL, -- '01'-'12' für Monat, 'Q1'-'Q4' für Quartal + periode_typ VARCHAR(10) NOT NULL, -- 'monat' oder 'quartal' + + -- Lieferungen und Leistungen + kz81 DOUBLE(24,8) DEFAULT 0, -- Steuerpfl. Umsätze 19% + kz86 DOUBLE(24,8) DEFAULT 0, -- Steuerpfl. Umsätze 7% + kz35 DOUBLE(24,8) DEFAULT 0, -- Steuerpfl. Umsätze andere Sätze + kz36 DOUBLE(24,8) DEFAULT 0, -- USt auf Kz35 + + -- Steuerfreie Umsätze + kz41 DOUBLE(24,8) DEFAULT 0, -- Innergemeinschaftl. Lieferungen + kz44 DOUBLE(24,8) DEFAULT 0, -- Steuerfreie Ausfuhrlieferungen + + -- Vorsteuer + kz66 DOUBLE(24,8) DEFAULT 0, -- Vorsteuer aus Rechnungen + kz61 DOUBLE(24,8) DEFAULT 0, -- Vorsteuer aus igE + kz67 DOUBLE(24,8) DEFAULT 0, -- Vorsteuer nach § 13b + + -- Berechnung + ust_summe DOUBLE(24,8) DEFAULT 0, -- Summe USt + vst_summe DOUBLE(24,8) DEFAULT 0, -- Summe VSt + zahllast DOUBLE(24,8) DEFAULT 0, -- USt - VSt (positiv = Zahllast) + + status TINYINT(4) DEFAULT 0, -- 0=Entwurf, 1=Berechnet, 2=Übermittelt + uebermittelt_am DATE DEFAULT NULL, + note_private TEXT, + date_creation DATETIME, + tms TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + fk_user_creat INTEGER, + entity INTEGER DEFAULT 1, + UNIQUE KEY uk_periode (jahr, periode, entity) +) ENGINE=InnoDB; + +-- ============================================================================ +-- Gewerbesteuer +-- ============================================================================ +CREATE TABLE IF NOT EXISTS llx_steuer_gewerbe ( + rowid INTEGER AUTO_INCREMENT PRIMARY KEY, + jahr INTEGER NOT NULL, + gewinn_euer DOUBLE(24,8) DEFAULT 0, -- Gewinn aus EÜR + hinzurechnungen DOUBLE(24,8) DEFAULT 0, -- § 8 GewStG + kuerzungen DOUBLE(24,8) DEFAULT 0, -- § 9 GewStG + gewerbeertrag DOUBLE(24,8) DEFAULT 0, -- Nach Freibetrag + freibetrag DOUBLE(24,8) DEFAULT 24500, -- Freibetrag Einzelunternehmen + hebesatz DOUBLE(5,2) DEFAULT 400, -- Gemeinde-Hebesatz in % + steuermessbetrag DOUBLE(24,8) DEFAULT 0, + gewerbesteuer DOUBLE(24,8) DEFAULT 0, + anrechnung_est DOUBLE(24,8) DEFAULT 0, -- Anrechnung auf ESt + status TINYINT(4) DEFAULT 0, + note_private TEXT, + date_creation DATETIME, + tms TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + fk_user_creat INTEGER, + entity INTEGER DEFAULT 1, + UNIQUE KEY uk_jahr (jahr, entity) +) ENGINE=InnoDB; + +-- ============================================================================ +-- Standard EÜR-Konten nach SKR03 einfügen +-- ============================================================================ + +-- EINNAHMEN +INSERT IGNORE INTO llx_steuer_konto (kontonummer, bezeichnung, kategorie, euer_zeile, ust_kennzeichen) VALUES +('8400', 'Erlöse 19% USt', 'einnahme', 14, '81'), +('8300', 'Erlöse 7% USt', 'einnahme', 14, '86'), +('8100', 'Steuerfreie Umsätze Inland', 'einnahme', 10, NULL), +('8120', 'Steuerfreie igL', 'einnahme', 11, '41'), +('8150', 'Steuerfreie Ausfuhrlieferungen', 'einnahme', 12, '44'), +('8200', 'Erlöse ohne USt §19', 'einnahme', 14, NULL), +('8500', 'Provisionserlöse', 'einnahme', 14, '81'), +('8600', 'Sonstige Erlöse', 'einnahme', 16, '81'), +('8700', 'Erlöse aus VuV', 'einnahme', 17, NULL), +('8800', 'Zinserträge', 'einnahme', 18, NULL), +('8900', 'Privatentnahmen Sachen', 'einnahme', 19, '81'), +('8910', 'Private Kfz-Nutzung', 'einnahme', 19, '81'), +('8920', 'Private Telefonnutzung', 'einnahme', 19, '81'); + +-- AUSGABEN - Wareneinkauf +INSERT IGNORE INTO llx_steuer_konto (kontonummer, bezeichnung, kategorie, euer_zeile, ust_kennzeichen) VALUES +('3400', 'Wareneingang 19% VSt', 'ausgabe', 26, '66'), +('3300', 'Wareneingang 7% VSt', 'ausgabe', 26, '66'), +('3100', 'Wareneingang steuerfrei', 'ausgabe', 26, NULL); + +-- AUSGABEN - Personal +INSERT IGNORE INTO llx_steuer_konto (kontonummer, bezeichnung, kategorie, euer_zeile, ust_kennzeichen) VALUES +('4100', 'Löhne und Gehälter', 'ausgabe', 31, NULL), +('4130', 'Gesetzliche Sozialaufwendungen', 'ausgabe', 32, NULL), +('4140', 'Freiwillige Sozialaufwendungen', 'ausgabe', 33, NULL); + +-- AUSGABEN - Raumkosten +INSERT IGNORE INTO llx_steuer_konto (kontonummer, bezeichnung, kategorie, euer_zeile, ust_kennzeichen) VALUES +('4200', 'Raumkosten/Miete', 'ausgabe', 34, '66'), +('4210', 'Miete Geschäftsräume', 'ausgabe', 34, '66'), +('4230', 'Heizung', 'ausgabe', 34, '66'), +('4240', 'Gas, Strom, Wasser', 'ausgabe', 34, '66'), +('4250', 'Reinigung', 'ausgabe', 34, '66'), +('4260', 'Instandhaltung Räume', 'ausgabe', 34, '66'); + +-- AUSGABEN - Sonstige Betriebsausgaben +INSERT IGNORE INTO llx_steuer_konto (kontonummer, bezeichnung, kategorie, euer_zeile, ust_kennzeichen) VALUES +('4500', 'Fahrzeugkosten', 'ausgabe', 51, '66'), +('4510', 'Kfz-Steuer', 'ausgabe', 51, NULL), +('4520', 'Kfz-Versicherung', 'ausgabe', 51, NULL), +('4530', 'Kraftstoff', 'ausgabe', 51, '66'), +('4540', 'Kfz-Reparaturen', 'ausgabe', 51, '66'), +('4580', 'Sonstige Kfz-Kosten', 'ausgabe', 51, '66'), + +('4600', 'Werbekosten', 'ausgabe', 53, '66'), +('4610', 'Geschenke abzugsfähig', 'ausgabe', 54, '66'), +('4630', 'Geschenke nicht abzugsfähig', 'ausgabe', 55, '66'), +('4650', 'Bewirtungskosten 70%', 'ausgabe', 56, '66'), +('4660', 'Reisekosten Unternehmer', 'ausgabe', 57, NULL), +('4670', 'Reisekosten Arbeitnehmer', 'ausgabe', 58, '66'), + +('4700', 'Porto', 'ausgabe', 49, '66'), +('4710', 'Telefon', 'ausgabe', 49, '66'), +('4750', 'Bürobedarf', 'ausgabe', 49, '66'), +('4780', 'Fremdleistungen', 'ausgabe', 49, '66'), +('4790', 'Sonstige Betriebsausgaben', 'ausgabe', 49, '66'), + +('4800', 'Reparatur/Instandhaltung', 'ausgabe', 39, '66'), +('4830', 'Versicherungen', 'ausgabe', 46, NULL), +('4840', 'Beiträge IHK/Verbände', 'ausgabe', 47, NULL), +('4850', 'Fortbildungskosten', 'ausgabe', 48, '66'), +('4900', 'Rechts- und Beratungskosten', 'ausgabe', 50, '66'), +('4910', 'Buchführungskosten', 'ausgabe', 50, '66'), +('4920', 'Jahresabschlusskosten', 'ausgabe', 50, '66'), +('4940', 'Bankgebühren', 'ausgabe', 48, NULL), +('4950', 'Nebenkosten Geldverkehr', 'ausgabe', 48, NULL), +('4960', 'Miete für Einrichtungen', 'ausgabe', 38, '66'), +('4970', 'Leasing', 'ausgabe', 38, '66'), +('4980', 'Software/Lizenzen', 'ausgabe', 39, '66'); + +-- AUSGABEN - AfA +INSERT IGNORE INTO llx_steuer_konto (kontonummer, bezeichnung, kategorie, euer_zeile, ust_kennzeichen) VALUES +('4820', 'AfA Sachanlagen', 'ausgabe', 36, NULL), +('4822', 'AfA immaterielle WG', 'ausgabe', 37, NULL), +('4824', 'AfA GWG', 'ausgabe', 38, NULL), +('4826', 'Sonderabschreibungen', 'ausgabe', 38, NULL); + +-- AUSGABEN - Zinsen +INSERT IGNORE INTO llx_steuer_konto (kontonummer, bezeichnung, kategorie, euer_zeile, ust_kennzeichen) VALUES +('2100', 'Zinsaufwendungen', 'ausgabe', 45, NULL), +('2110', 'Zinsen langfristige Darlehen', 'ausgabe', 45, NULL); diff --git a/sql/llx_steuer_buchung.key.sql b/sql/llx_steuer_buchung.key.sql new file mode 100644 index 0000000..2432829 --- /dev/null +++ b/sql/llx_steuer_buchung.key.sql @@ -0,0 +1,7 @@ +-- Copyright (C) 2026 Eduard Wisch +-- Keys/Indexes for llx_steuer_buchung + +ALTER TABLE llx_steuer_buchung ADD INDEX idx_buchung_datum (datum); +ALTER TABLE llx_steuer_buchung ADD INDEX idx_buchung_konto (fk_konto); +ALTER TABLE llx_steuer_buchung ADD INDEX idx_buchung_typ (typ); +ALTER TABLE llx_steuer_buchung ADD INDEX idx_buchung_ref (ref); diff --git a/sql/llx_steuer_buchung.sql b/sql/llx_steuer_buchung.sql new file mode 100644 index 0000000..f345ed0 --- /dev/null +++ b/sql/llx_steuer_buchung.sql @@ -0,0 +1,27 @@ +-- Copyright (C) 2026 Eduard Wisch +-- Table for EÜR Buchungen + +CREATE TABLE IF NOT EXISTS llx_steuer_buchung ( + rowid INTEGER AUTO_INCREMENT PRIMARY KEY, + ref VARCHAR(30) NOT NULL, + datum DATE NOT NULL, + belegnummer VARCHAR(50) DEFAULT NULL, + beschreibung VARCHAR(255) NOT NULL, + fk_konto INTEGER NOT NULL, + betrag_netto DOUBLE(24,8) DEFAULT 0, + betrag_ust DOUBLE(24,8) DEFAULT 0, + betrag_brutto DOUBLE(24,8) DEFAULT 0, + ust_satz DOUBLE(5,2) DEFAULT 0, + typ VARCHAR(20) NOT NULL, + zahlungsart VARCHAR(30) DEFAULT NULL, + fk_soc INTEGER DEFAULT NULL, + fk_facture INTEGER DEFAULT NULL, + fk_facture_fourn INTEGER DEFAULT NULL, + note_private TEXT, + date_creation DATETIME, + tms TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + fk_user_creat INTEGER, + fk_user_modif INTEGER, + status TINYINT(4) DEFAULT 1, + entity INTEGER DEFAULT 1 +) ENGINE=InnoDB; diff --git a/sql/llx_steuer_gewerbe.sql b/sql/llx_steuer_gewerbe.sql new file mode 100644 index 0000000..9372413 --- /dev/null +++ b/sql/llx_steuer_gewerbe.sql @@ -0,0 +1,23 @@ +-- Copyright (C) 2026 Eduard Wisch +-- Table for Gewerbesteuer + +CREATE TABLE IF NOT EXISTS llx_steuer_gewerbe ( + rowid INTEGER AUTO_INCREMENT PRIMARY KEY, + jahr INTEGER NOT NULL, + gewinn_euer DOUBLE(24,8) DEFAULT 0, + hinzurechnungen DOUBLE(24,8) DEFAULT 0, + kuerzungen DOUBLE(24,8) DEFAULT 0, + gewerbeertrag DOUBLE(24,8) DEFAULT 0, + freibetrag DOUBLE(24,8) DEFAULT 24500, + hebesatz DOUBLE(5,2) DEFAULT 400, + steuermessbetrag DOUBLE(24,8) DEFAULT 0, + gewerbesteuer DOUBLE(24,8) DEFAULT 0, + anrechnung_est DOUBLE(24,8) DEFAULT 0, + status TINYINT(4) DEFAULT 0, + note_private TEXT, + date_creation DATETIME, + tms TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + fk_user_creat INTEGER, + entity INTEGER DEFAULT 1, + UNIQUE KEY uk_jahr (jahr, entity) +) ENGINE=InnoDB; diff --git a/sql/llx_steuer_konto.key.sql b/sql/llx_steuer_konto.key.sql new file mode 100644 index 0000000..16ac1c7 --- /dev/null +++ b/sql/llx_steuer_konto.key.sql @@ -0,0 +1,2 @@ +-- Copyright (C) 2026 Eduard Wisch +-- Keys/Indexes for llx_steuer_konto (none additional needed) diff --git a/sql/llx_steuer_konto.sql b/sql/llx_steuer_konto.sql new file mode 100644 index 0000000..78528df --- /dev/null +++ b/sql/llx_steuer_konto.sql @@ -0,0 +1,14 @@ +-- Copyright (C) 2026 Eduard Wisch +-- Table for EÜR Kontenrahmen (SKR03) + +CREATE TABLE IF NOT EXISTS llx_steuer_konto ( + rowid INTEGER AUTO_INCREMENT PRIMARY KEY, + kontonummer VARCHAR(10) NOT NULL, + bezeichnung VARCHAR(255) NOT NULL, + kategorie VARCHAR(50) NOT NULL, + euer_zeile INTEGER DEFAULT NULL, + ust_kennzeichen VARCHAR(10) DEFAULT NULL, + aktiv TINYINT(1) DEFAULT 1, + entity INTEGER DEFAULT 1, + UNIQUE KEY uk_konto_nummer (kontonummer, entity) +) ENGINE=InnoDB; diff --git a/sql/llx_steuer_ustva.sql b/sql/llx_steuer_ustva.sql new file mode 100644 index 0000000..0edfa12 --- /dev/null +++ b/sql/llx_steuer_ustva.sql @@ -0,0 +1,29 @@ +-- Copyright (C) 2026 Eduard Wisch +-- Table for USt-Voranmeldung Perioden + +CREATE TABLE IF NOT EXISTS llx_steuer_ustva ( + rowid INTEGER AUTO_INCREMENT PRIMARY KEY, + jahr INTEGER NOT NULL, + periode VARCHAR(10) NOT NULL, + periode_typ VARCHAR(10) NOT NULL, + kz81 DOUBLE(24,8) DEFAULT 0, + kz86 DOUBLE(24,8) DEFAULT 0, + kz35 DOUBLE(24,8) DEFAULT 0, + kz36 DOUBLE(24,8) DEFAULT 0, + kz41 DOUBLE(24,8) DEFAULT 0, + kz44 DOUBLE(24,8) DEFAULT 0, + kz66 DOUBLE(24,8) DEFAULT 0, + kz61 DOUBLE(24,8) DEFAULT 0, + kz67 DOUBLE(24,8) DEFAULT 0, + ust_summe DOUBLE(24,8) DEFAULT 0, + vst_summe DOUBLE(24,8) DEFAULT 0, + zahllast DOUBLE(24,8) DEFAULT 0, + status TINYINT(4) DEFAULT 0, + uebermittelt_am DATE DEFAULT NULL, + note_private TEXT, + date_creation DATETIME, + tms TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + fk_user_creat INTEGER, + entity INTEGER DEFAULT 1, + UNIQUE KEY uk_periode (jahr, periode, entity) +) ENGINE=InnoDB; diff --git a/steuerindex.php b/steuerindex.php new file mode 100755 index 0000000..68db0e1 --- /dev/null +++ b/steuerindex.php @@ -0,0 +1,279 @@ + + * Copyright (C) 2004-2015 Laurent Destailleur + * Copyright (C) 2005-2012 Regis Houssin + * Copyright (C) 2015 Jean-François Ferry + * Copyright (C) 2024 Frédéric France + * Copyright (C) 2026 Eduard Wisch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file steuer/steuerindex.php + * \ingroup steuer + * \brief EÜR Übersicht - Einnahmen-Überschuss-Rechnung für Deutschland + */ + +// Load Dolibarr environment +$res = 0; +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) { + $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +} +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; +$tmp2 = realpath(__FILE__); +$i = strlen($tmp) - 1; +$j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { + $i--; + $j--; +} +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) { + $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +} +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) { + $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +} +if (!$res && file_exists("../main.inc.php")) { + $res = @include "../main.inc.php"; +} +if (!$res && file_exists("../../main.inc.php")) { + $res = @include "../../main.inc.php"; +} +if (!$res && file_exists("../../../main.inc.php")) { + $res = @include "../../../main.inc.php"; +} +if (!$res) { + die("Include of main fails"); +} + +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; +dol_include_once('/steuer/class/euer.class.php'); + +/** + * @var Conf $conf + * @var DoliDB $db + * @var HookManager $hookmanager + * @var Translate $langs + * @var User $user + */ + +// Load translation files required by the page +$langs->loadLangs(array("steuer@steuer", "bills", "compta")); + +$action = GETPOST('action', 'aZ09'); +$jahr = GETPOSTINT('jahr'); +if (empty($jahr)) { + $jahr = date('Y'); +} +$monat = GETPOSTINT('monat'); + +$now = dol_now(); + +// Security check +$socid = GETPOSTINT('socid'); +if (!empty($user->socid) && $user->socid > 0) { + $action = ''; + $socid = $user->socid; +} + +/* + * Actions + */ + +// None + +/* + * View + */ + +$form = new Form($db); +$formfile = new FormFile($db); +$euer = new EUeR($db); + +// Berechne EÜR +if ($monat > 0) { + $euer->berechneAusDolibarr($jahr, $monat, $monat); + $periode_text = $langs->trans("Month")." ".dol_print_date(mktime(0, 0, 0, $monat, 1, $jahr), '%B %Y'); +} else { + $euer->berechneAusDolibarr($jahr); + $periode_text = $langs->trans("Year")." ".$jahr; +} + +llxHeader("", $langs->trans("EUeRUebersicht"), '', '', 0, 0, '', '', '', 'mod-steuer page-index'); + +print load_fiche_titre($langs->trans("EUeRUebersicht")." - ".$periode_text, '', 'steuer.png@steuer'); + +// Filter-Formular +print '
'; +print ''; +print '
'; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print '
'.$langs->trans("Period").''.$langs->trans("Year").''.$langs->trans("Month").'
'.$langs->trans("SelectPeriod").''; +print ''; +print ''; +print ''; +print ''; +print ''; +print '
'; +print '
'; +print '
'; + +print '
'; + +// Schnellzugriff-Links +print '
'; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print '
'.$langs->trans("QuickAccess").'
'.$langs->trans("Buchungen").''.$langs->trans("NeueBuchung").''.$langs->trans("AnlageEUeR").''.$langs->trans("UStVA").'
'.$langs->trans("Gewerbesteuer").''.$langs->trans("WISOExport").''.$langs->trans("Kontenplan").'
'; +print '
'; + +print '
'; + +print '
'; + +// EÜR Übersicht - Einnahmen +print ''; +print ''; +print ''; +print ''; +print ''; + +if (!empty($euer->einnahmen)) { + foreach ($euer->einnahmen as $key => $einnahme) { + print ''; + print ''; + print ''; + print ''; + } +} + +print ''; +print ''; +print ''; +print ''; +print '
'.$langs->trans("Einnahmen").''.$langs->trans("Amount").'
'.$einnahme['bezeichnung'].''.price($einnahme['netto'], 0, $langs, 1, 2, 2, 'EUR').'
'.$langs->trans("TotalEinnahmen").''.price($euer->summe_einnahmen, 0, $langs, 1, 2, 2, 'EUR').'
'; + +print '
'; + +// USt/VSt Übersicht +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +$zahllast = $euer->ust_summe - $euer->vst_summe; +$color = $zahllast >= 0 ? '' : 'amountremaintopay'; +print ''; +print ''; +print '
'.$langs->trans("UmsatzsteuerVorsteuer").'
'.$langs->trans("UmsatzsteuerGesamt").''.price($euer->ust_summe, 0, $langs, 1, 2, 2, 'EUR').'
'.$langs->trans("VorsteuerGesamt").''.price($euer->vst_summe, 0, $langs, 1, 2, 2, 'EUR').'
'.$langs->trans("Zahllast").''.price($zahllast, 0, $langs, 1, 2, 2, 'EUR').'
'; + +print '
'; + +// EÜR Übersicht - Ausgaben +print ''; +print ''; +print ''; +print ''; +print ''; + +if (!empty($euer->ausgaben)) { + foreach ($euer->ausgaben as $key => $ausgabe) { + print ''; + print ''; + print ''; + print ''; + } +} + +print ''; +print ''; +print ''; +print ''; +print '
'.$langs->trans("Ausgaben").''.$langs->trans("Amount").'
'.$ausgabe['bezeichnung'].''.price($ausgabe['netto'], 0, $langs, 1, 2, 2, 'EUR').'
'.$langs->trans("TotalAusgaben").''.price($euer->summe_ausgaben, 0, $langs, 1, 2, 2, 'EUR').'
'; + +print '
'; + +// Gewinn/Verlust Box +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +$color = $euer->gewinn >= 0 ? 'amountpaymentcomplete' : 'amountremaintopay'; +print ''; +print ''; +print ''; +print '
'.$langs->trans("ErgebnisEUeR").'
'.$langs->trans("Einnahmen").''.price($euer->summe_einnahmen, 0, $langs, 1, 2, 2, 'EUR').'
'.$langs->trans("Ausgaben").'- '.price($euer->summe_ausgaben, 0, $langs, 1, 2, 2, 'EUR').'
'.($euer->gewinn >= 0 ? $langs->trans("Gewinn") : $langs->trans("Verlust")).''.price($euer->gewinn, 0, $langs, 1, 2, 2, 'EUR').'
'; + +print '
'; + +print '
'; + +// End of page +llxFooter(); +$db->close(); diff --git a/ustva.php b/ustva.php new file mode 100644 index 0000000..f7e8cd8 --- /dev/null +++ b/ustva.php @@ -0,0 +1,398 @@ + 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { + $i--; + $j--; +} +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) { + $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +} +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) { + $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +} +if (!$res && file_exists("../main.inc.php")) { + $res = @include "../main.inc.php"; +} +if (!$res && file_exists("../../main.inc.php")) { + $res = @include "../../main.inc.php"; +} +if (!$res && file_exists("../../../main.inc.php")) { + $res = @include "../../../main.inc.php"; +} +if (!$res) { + die("Include of main fails"); +} + +require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; +dol_include_once('/steuer/class/euer.class.php'); + +$langs->loadLangs(array("steuer@steuer", "bills", "compta")); + +$jahr = GETPOSTINT('jahr'); +if (empty($jahr)) { + $jahr = date('Y'); +} +$ansicht = GETPOST('ansicht', 'alpha'); +if (empty($ansicht)) { + $ansicht = 'monat'; +} +$monat = GETPOSTINT('monat'); +if (empty($monat)) { + $monat = date('n'); +} + +/* + * View + */ + +$form = new Form($db); +$euer = new EUeR($db); + +llxHeader('', $langs->trans("UStVA"), '', '', 0, 0, '', '', '', 'mod-steuer page-ustva'); + +print load_fiche_titre($langs->trans("UStVA")." ".$jahr, '', 'fa-percent'); + +// Filter +print '
'; +print ''; +print '
'; +print ''; +print ' '; +print ''; +print ' '; +print ''; +print ' '; +print '
'; +print '
'; + +print '
'; + +// ============================================================================ +// ELSTER FORMULAR - Für manuellen Übertrag +// ============================================================================ +print '

ELSTER/WISO Formular - '.dol_print_date(mktime(0, 0, 0, $monat, 1, $jahr), '%B %Y').'

'; + +// Daten für gewählten Monat berechnen +$euer->berechneAusDolibarr($jahr, $monat, $monat); + +// Berechne Werte für UStVA +$kz81 = 0; // Bemessungsgrundlage 19% +$kz81_steuer = 0; // Steuer darauf +$kz86 = 0; // Bemessungsgrundlage 7% +$kz86_steuer = 0; // Steuer darauf +$kz66 = $euer->vst_summe; // Vorsteuer + +// Einnahmen nach USt-Satz aufteilen +foreach ($euer->einnahmen as $einnahme) { + $ust_satz = isset($einnahme['ust_satz']) ? $einnahme['ust_satz'] : 19; + if ($ust_satz == 19) { + $kz81 += $einnahme['netto']; + $kz81_steuer += isset($einnahme['ust']) ? $einnahme['ust'] : ($einnahme['netto'] * 0.19); + } elseif ($ust_satz == 7) { + $kz86 += $einnahme['netto']; + $kz86_steuer += isset($einnahme['ust']) ? $einnahme['ust'] : ($einnahme['netto'] * 0.07); + } +} + +// Zahllast berechnen +$ust_gesamt = $kz81_steuer + $kz86_steuer; +$zahllast = $ust_gesamt - $kz66; + +print '
'; +print ''; + +// Header +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +// Abschnitt: Lieferungen und sonstige Leistungen +print ''; + +// Kz 81 - 19% Umsätze +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +// Kz 86 - 7% Umsätze +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +// Weitere wichtige Kennzahlen (leer, aber für Vollständigkeit) +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +// Steuerfreie Umsätze +print ''; + +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +// Abziehbare Vorsteuerbeträge +print ''; + +// Kz 66 - Vorsteuer +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +// Berechnung +print ''; + +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +// Zahllast / Erstattung +print ''; +print ''; +print ''; +print ''; +print ''; +$color = $zahllast >= 0 ? '' : 'amountremaintopay'; +print ''; +print ''; + +print '
ELSTER KzWISO FeldBezeichnungBemessungsgrundl.Steuer
Lieferungen und sonstige Leistungen (steuerpflichtige Umsätze)
Kz 81Zeile 28Steuerpflichtige Umsätze zum Steuersatz von 19%'.price(round($kz81), 0, $langs, 1, 0, 0).' EUR'.price($kz81_steuer, 0, $langs, 1, 2, 2).' EUR
Kz 86Zeile 29Steuerpflichtige Umsätze zum Steuersatz von 7%'.price(round($kz86), 0, $langs, 1, 0, 0).' EUR'.price($kz86_steuer, 0, $langs, 1, 2, 2).' EUR
Kz 35Zeile 30Umsätze zu anderen Steuersätzen0 EUR-
Steuerfreie Umsätze
Kz 41Zeile 20Innergemeinschaftliche Lieferungen (§ 4 Nr. 1b UStG)0 EUR-
Kz 44Zeile 21Steuerfreie Ausfuhrlieferungen (§ 4 Nr. 1a UStG)0 EUR-
Abziehbare Vorsteuerbeträge
Kz 66Zeile 55Vorsteuerbeträge aus Rechnungen von anderen Unternehmern-'.price($kz66, 0, $langs, 1, 2, 2).' EUR
Kz 61Zeile 56Vorsteuerbeträge aus innergemeinschaftlichem Erwerb-0,00 EUR
Kz 67Zeile 57Vorsteuerbeträge nach § 13b UStG (Reverse Charge)-0,00 EUR
Berechnung der Umsatzsteuer
Summe Umsatzsteuer (Kz 81 + Kz 86)-'.price($ust_gesamt, 0, $langs, 1, 2, 2).' EUR
./. Vorsteuer (Kz 66)-- '.price($kz66, 0, $langs, 1, 2, 2).' EUR
Kz 83Zeile 65'.($zahllast >= 0 ? 'Verbleibende Umsatzsteuer-Vorauszahlung' : 'Verbleibender Überschuss (Erstattung)').'-'.price(abs($zahllast), 0, $langs, 1, 2, 2).' EUR
'; +print '
'; + +// ============================================================================ +// Jahresübersicht +// ============================================================================ +print '

Jahresübersicht '.$jahr.'

'; + +print '
'; +print ''; + +// Header +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +$total_kz81 = 0; +$total_kz86 = 0; +$total_ust = 0; +$total_vst = 0; +$total_zahllast = 0; + +if ($ansicht == 'quartal') { + $perioden = array( + 'Q1' => array(1, 3), + 'Q2' => array(4, 6), + 'Q3' => array(7, 9), + 'Q4' => array(10, 12) + ); +} else { + $perioden = array(); + for ($m = 1; $m <= 12; $m++) { + $perioden[sprintf('%02d', $m)] = array($m, $m); + } +} + +foreach ($perioden as $key => $range) { + $euer->berechneAusDolibarr($jahr, $range[0], $range[1]); + + $p_kz81 = 0; + $p_kz86 = 0; + $p_ust = 0; + $p_vst = $euer->vst_summe; + + foreach ($euer->einnahmen as $einnahme) { + $ust_satz = isset($einnahme['ust_satz']) ? $einnahme['ust_satz'] : 19; + if ($ust_satz == 19) { + $p_kz81 += $einnahme['netto']; + $p_ust += isset($einnahme['ust']) ? $einnahme['ust'] : ($einnahme['netto'] * 0.19); + } elseif ($ust_satz == 7) { + $p_kz86 += $einnahme['netto']; + $p_ust += isset($einnahme['ust']) ? $einnahme['ust'] : ($einnahme['netto'] * 0.07); + } + } + + $p_zahllast = $p_ust - $p_vst; + + $total_kz81 += $p_kz81; + $total_kz86 += $p_kz86; + $total_ust += $p_ust; + $total_vst += $p_vst; + $total_zahllast += $p_zahllast; + + if ($ansicht == 'quartal') { + $periode_name = $key.' '.$jahr; + } else { + $periode_name = dol_print_date(mktime(0, 0, 0, (int)$key, 1, $jahr), '%B'); + } + + $is_current = ($ansicht != 'quartal' && (int)$key == $monat); + $row_class = $is_current ? 'liste_titre' : 'oddeven'; + + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + $color = $p_zahllast >= 0 ? '' : 'amountremaintopay'; + print ''; + print ''; +} + +// Summenzeile +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +$color = $total_zahllast >= 0 ? 'amountpaymentcomplete' : 'amountremaintopay'; +print ''; +print ''; + +print '
'.$langs->trans("Period").'Kz 81
Umsätze 19%
Kz 86
Umsätze 7%
USt
Steuer
Kz 66
Vorsteuer
Kz 83
Zahllast
'.($is_current ? '' : '').$periode_name.($is_current ? ' (oben)' : '').''.price(round($p_kz81), 0, $langs, 1, 0, 0).''.price(round($p_kz86), 0, $langs, 1, 0, 0).''.price($p_ust, 0, $langs, 1, 2, 2).''.price($p_vst, 0, $langs, 1, 2, 2).''.price($p_zahllast, 0, $langs, 1, 2, 2).'
Gesamt '.$jahr.''.price(round($total_kz81), 0, $langs, 1, 0, 0).''.price(round($total_kz86), 0, $langs, 1, 0, 0).''.price($total_ust, 0, $langs, 1, 2, 2).''.price($total_vst, 0, $langs, 1, 2, 2).''.price($total_zahllast, 0, $langs, 1, 2, 2).'
'; +print '
'; + +// ============================================================================ +// Legende +// ============================================================================ +print '
'; +print '
'; +print '
'; + +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print '
ELSTER Kennzahlen
Kz 81Bemessungsgrundlage für Umsätze zum Steuersatz von 19%
Kz 86Bemessungsgrundlage für Umsätze zum Steuersatz von 7%
Kz 66Vorsteuerbeträge aus Rechnungen von anderen Unternehmern
Kz 83Verbleibende Umsatzsteuer-Vorauszahlung / Überschuss
Kz 35Umsätze zu anderen Steuersätzen (z.B. 16%, 5%)
Kz 41Innergemeinschaftliche Lieferungen
Kz 44Steuerfreie Ausfuhrlieferungen
'; + +print '
'; +print '
'; + +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print '
WISO Steuer Zuordnung
Zeile 28= ELSTER Kz 81 (19% Umsätze)
Zeile 29= ELSTER Kz 86 (7% Umsätze)
Zeile 55= ELSTER Kz 66 (Vorsteuer)
Zeile 65= ELSTER Kz 83 (Zahllast)
Die WISO Zeilennummern können je nach Version abweichen. Orientieren Sie sich an den ELSTER-Kennzahlen.
'; + +print '
'; +print '
'; + +print '
'; + +// Hinweis +print '
'; +print '
'; +print 'Hinweis zur Übertragung:
'; +print '1. In ELSTER/WISO tragen Sie die Bemessungsgrundlagen (Netto-Beträge) in die Felder Kz 81 und Kz 86 ein
'; +print '2. Die Steuer wird automatisch berechnet
'; +print '3. Die Vorsteuer (Kz 66) ist der Gesamtbetrag der abziehbaren Vorsteuer
'; +print '4. Die Kennzahlen sind identisch für ELSTER und WISO Steuer
'; +print '
'; + +// Zurück-Button +print '
'; +print '
'; +print ''.$langs->trans("Back").''; +print '
'; + +llxFooter(); +$db->close();