diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..791c54c --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,53 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + build: + name: Build and test + runs-on: ubuntu-latest + timeout-minutes: 45 + defaults: + run: + working-directory: android-app + + steps: + - uses: actions/checkout@v5 + + - uses: actions/setup-java@v5 + with: + distribution: temurin + java-version: 21 + + - uses: gradle/actions/setup-gradle@v5 + + - name: Unit tests + run: ./gradlew testFossDebugUnitTest testGmsDebugUnitTest + + - name: Assemble debug APKs + run: ./gradlew assembleFossDebug assembleGmsDebug + + - name: Upload test reports + if: failure() + uses: actions/upload-artifact@v4 + with: + name: test-reports + path: android-app/app/build/reports/tests/ + retention-days: 7 + + - name: Upload debug APKs + uses: actions/upload-artifact@v4 + with: + name: debug-apks + path: android-app/app/build/outputs/apk/*/debug/*.apk + retention-days: 7 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..ed20a94 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,87 @@ +name: Release + +on: + push: + tags: + - "v*.*.*" + +permissions: + contents: write + +jobs: + release: + name: Build and publish release + runs-on: ubuntu-latest + timeout-minutes: 45 + defaults: + run: + working-directory: android-app + + steps: + - uses: actions/checkout@v5 + + - name: Check tag matches app version + id: version + run: | + tag="${GITHUB_REF_NAME#v}" + app_version=$(sed -n 's/.*ClientVersion\.validate("\([^"]*\)").*/\1/p' app/build.gradle.kts) + if [ "$tag" != "$app_version" ]; then + echo "::error::Tag $GITHUB_REF_NAME does not match versionName $app_version in app/build.gradle.kts" + exit 1 + fi + echo "name=$app_version" >> "$GITHUB_OUTPUT" + + - uses: actions/setup-java@v5 + with: + distribution: temurin + java-version: 21 + + - uses: gradle/actions/setup-gradle@v5 + with: + cache-read-only: true + + - name: Restore signing keystore + env: + KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }} + run: | + if [ -z "$KEYSTORE_BASE64" ]; then + echo "::error::KEYSTORE_BASE64 secret is not set" + exit 1 + fi + echo "$KEYSTORE_BASE64" | base64 --decode > "$RUNNER_TEMP/release.jks" + echo "HHO_KEYSTORE_FILE=$RUNNER_TEMP/release.jks" >> "$GITHUB_ENV" + + - name: Unit tests + run: ./gradlew testFossDebugUnitTest testGmsDebugUnitTest + + - name: Assemble release APKs + env: + HHO_KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }} + HHO_KEY_ALIAS: ${{ secrets.KEY_ALIAS }} + HHO_KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} + run: ./gradlew assembleFossRelease assembleGmsRelease + + - name: Collect artifacts + env: + VERSION: ${{ steps.version.outputs.name }} + run: | + mkdir -p dist + for flavor in foss gms; do + cp "app/build/outputs/apk/$flavor/release/app-$flavor-release.apk" "dist/hho-$VERSION-$flavor.apk" + done + cd dist + sha256sum *.apk > SHA256SUMS + + - name: Remove keystore + if: always() + run: rm -f "$RUNNER_TEMP/release.jks" + + - name: Publish GitHub release + uses: softprops/action-gh-release@v2 + with: + name: ${{ steps.version.outputs.name }} + generate_release_notes: true + fail_on_unmatched_files: true + files: | + android-app/dist/*.apk + android-app/dist/SHA256SUMS diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..be3f7b2 --- /dev/null +++ b/LICENSE @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/README.md b/README.md index 9a2ef3b..a8e65cf 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,27 @@ -# household-objects-android -household-objects-android +# HHO — Household Objects + +HHO is a **self-hosted home inventory and organization system**. You run it on your own +hardware (a Raspberry Pi, a NAS, a home server), and it helps a household track what it owns: +what's in the garage, which box has the holiday lights, whether the drill is still under +warranty. No cloud account, no subscription, no external service required to operate it. + +HHO ships as two coupled products : + +- **HHO Server** ( `https://github.com/ankek/household-objects-srv/server/`) — a single Go binary / container. SQLite storage, an embedded + Vue 3 web UI, and a documented public REST API. This is the whole product for a browser-only + household. +- **HHO Android app** (this one repository,`/android-app/`) — native Kotlin + Jetpack Compose, offline-first, + barcode-driven stock control for standing in front of a shelf with no signal. Syncs to the + server. *(Not yet functional — see [Project status](#project-status) below.)* + +Licensed **AGPL-3.0-only**; see [License](#license). + +## Project status +This project is under development — the HHO Server MVP + +## License + +HHO and all components are licensed under the **GNU Affero General Public License v3.0 only** (`AGPL-3.0-only`) — see +[`LICENSE`](LICENSE). The AGPL's network-use clause (section 13) is the deliberate reason it was +chosen over plain GPL: if you run a modified version of HHO as a network service, you must offer +its source to your users. Sorry, bro. Sad but true. \ No newline at end of file diff --git a/android-app/.gitignore b/android-app/.gitignore new file mode 100644 index 0000000..4b91077 --- /dev/null +++ b/android-app/.gitignore @@ -0,0 +1,24 @@ +.gradle/ +build/ +app/build/ +captures/ +.cxx/ + +local.properties +.kotlin/ + +*.apk +*.aab +*.ap_ +*.aar +*.dex +*.class +*.jks +*.keystore +output.json + +.idea/ +*.iml +.navigation/ + +!gradle/wrapper/gradle-wrapper.jar diff --git a/android-app/app/build.gradle.kts b/android-app/app/build.gradle.kts new file mode 100644 index 0000000..dc5863e --- /dev/null +++ b/android-app/app/build.gradle.kts @@ -0,0 +1,500 @@ +import dev.hho.android.buildsrc.ClientVersion +import org.openapitools.generator.gradle.plugin.tasks.GenerateTask +import java.io.File + +plugins { + alias(libs.plugins.android.application) + alias(libs.plugins.kotlin.compose) + alias(libs.plugins.kotlin.serialization) + alias(libs.plugins.ksp) + alias(libs.plugins.hilt) + alias(libs.plugins.openapi.generator) +} + +val hhoClientVersion = ClientVersion.validate("0.1.0") + +val releaseKeystore = providers.environmentVariable("HHO_KEYSTORE_FILE") + .orElse(providers.gradleProperty("hho.keystore.file")) + .orNull + ?.let(::file) + ?.takeIf { it.isFile } + +android { + namespace = "dev.hho.android" + compileSdk = libs.versions.compileSdk.get().toInt() + + defaultConfig { + applicationId = "dev.hho.android" + minSdk = libs.versions.minSdk.get().toInt() + targetSdk = libs.versions.targetSdk.get().toInt() + versionCode = 1 + versionName = hhoClientVersion + + buildConfigField("String", "HHO_CLIENT_VERSION", "\"$hhoClientVersion\"") + + testInstrumentationRunner = "dev.hho.android.HhoHiltTestRunner" + } + + flavorDimensions += "distribution" + productFlavors { + create("gms") { + dimension = "distribution" + } + create("foss") { + dimension = "distribution" + } + } + + signingConfigs { + if (releaseKeystore != null) { + create("release") { + storeFile = releaseKeystore + storePassword = providers.environmentVariable("HHO_KEYSTORE_PASSWORD") + .orElse(providers.gradleProperty("hho.keystore.password")).orNull + keyAlias = providers.environmentVariable("HHO_KEY_ALIAS") + .orElse(providers.gradleProperty("hho.key.alias")).orNull + keyPassword = providers.environmentVariable("HHO_KEY_PASSWORD") + .orElse(providers.gradleProperty("hho.key.password")).orNull + } + } + } + + buildTypes { + debug { + isMinifyEnabled = false + } + release { + isMinifyEnabled = false + isShrinkResources = false + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") + signingConfig = signingConfigs.findByName("release") + } + } + + dependenciesInfo { + includeInApk = false + includeInBundle = false + } + + compileOptions { + val java = JavaVersion.toVersion(libs.versions.jvmTarget.get()) + sourceCompatibility = java + targetCompatibility = java + } + + buildFeatures { + compose = true + buildConfig = true + } + + testOptions { + unitTests { + isIncludeAndroidResources = true + all { + it.jvmArgs( + "--add-opens=java.base/java.lang=ALL-UNNAMED", + "--add-opens=java.base/java.util=ALL-UNNAMED", + "--add-opens=java.base/java.io=ALL-UNNAMED", + "--add-opens=java.base/java.security=ALL-UNNAMED", + "--add-opens=java.base/java.net=ALL-UNNAMED", + "--add-opens=java.base/java.text=ALL-UNNAMED", + "--add-opens=java.base/java.lang.reflect=ALL-UNNAMED", + "--add-opens=java.base/java.util.concurrent=ALL-UNNAMED", + "--add-opens=java.base/jdk.internal.access=ALL-UNNAMED", + "--add-opens=java.base/sun.security.x509=ALL-UNNAMED", + "--add-opens=java.desktop/java.awt.font=ALL-UNNAMED", + ) + } + } + } + + sourceSets { + getByName("main").kotlin.srcDir("src/main/kotlin") + getByName("test").kotlin.srcDir("src/test/kotlin") + getByName("debug").assets.srcDir("schemas") + getByName("androidTest").kotlin.srcDir("src/androidTest/kotlin") + getByName("gms").kotlin.srcDir("src/gms/kotlin") + getByName("foss").kotlin.srcDir("src/foss/kotlin") + getByName("testGms").kotlin.srcDir("src/testGms/kotlin") + getByName("testFoss").kotlin.srcDir("src/testFoss/kotlin") + } +} + +dependencies { + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.lifecycle.runtime.ktx) + implementation(libs.androidx.lifecycle.viewmodel.compose) + implementation(libs.androidx.activity.compose) + + val composeBom = platform(libs.androidx.compose.bom) + implementation(composeBom) + androidTestImplementation(composeBom) + + implementation(libs.androidx.compose.ui) + implementation(libs.androidx.compose.ui.graphics) + implementation(libs.androidx.compose.ui.tooling.preview) + implementation(libs.androidx.compose.material3) + debugImplementation(libs.androidx.compose.ui.tooling) + + implementation(libs.hilt.android) + implementation(libs.androidx.hilt.navigation.compose) + ksp(libs.hilt.compiler) + + implementation(libs.androidx.room.runtime) + implementation(libs.androidx.room.ktx) + ksp(libs.androidx.room.compiler) + + implementation(libs.kotlinx.coroutines.core) + implementation(libs.androidx.datastore.preferences) + implementation(libs.okhttp) + + implementation(libs.kotlinx.serialization.json) + + implementation(libs.androidx.camera.core) + implementation(libs.androidx.camera.camera2) + implementation(libs.androidx.camera.lifecycle) + implementation(libs.androidx.camera.view) + implementation(libs.androidx.appcompat) + + "gmsImplementation"(libs.mlkit.barcode.scanning) + + implementation(libs.zxing.core) + + testImplementation(libs.junit) + testImplementation(libs.okhttp.mockwebserver) + testImplementation(libs.kotlinx.coroutines.test) + + kspTest(libs.dagger.compiler) + + testImplementation(libs.robolectric) + testImplementation(libs.androidx.room.testing) + testImplementation(libs.androidx.test.core) + testImplementation(libs.androidx.test.ext.junit) + + implementation(libs.androidx.work.runtime.ktx) + implementation(libs.androidx.hilt.work) + ksp(libs.androidx.hilt.compiler) + + testImplementation(libs.androidx.work.testing) + + androidTestImplementation(libs.androidx.compose.ui.test.junit4) + androidTestImplementation(libs.androidx.test.ext.junit) + androidTestImplementation(libs.androidx.test.runner) + androidTestImplementation(libs.androidx.test.rules) + androidTestImplementation(libs.androidx.test.espresso.core) + androidTestImplementation(libs.hilt.android.testing) + kspAndroidTest(libs.hilt.compiler) +} + +val mergedDebugManifest = + layout.buildDirectory.file("intermediates/merged_manifest/fossDebug/processFossDebugMainManifest/AndroidManifest.xml") + +val checkNoWorkManagerDefaultInitializer = tasks.register("checkNoWorkManagerDefaultInitializer") { + group = "verification" + description = "T158e: fails if the merged debug manifest still registers WorkManager's " + + "default androidx.startup initializer (which would bypass HiltWorkerFactory)." + + dependsOn("processFossDebugMainManifest") + val manifestProvider = mergedDebugManifest + inputs.file(manifestProvider) + + doLast { + val manifest = manifestProvider.get().asFile + check(manifest.isFile) { + "checkNoWorkManagerDefaultInitializer: merged manifest not found at ${manifest.path} " + + "— AGP's output path changed; update this task rather than letting it pass vacuously." + } + val androidNs = "http://schemas.android.com/apk/res/android" + val doc = javax.xml.parsers.DocumentBuilderFactory.newInstance() + .apply { isNamespaceAware = true } + .newDocumentBuilder() + .parse(manifest) + val metaData = doc.getElementsByTagName("meta-data") + val registered = (0 until metaData.length) + .map { (metaData.item(it) as org.w3c.dom.Element).getAttributeNS(androidNs, "name") } + if ("androidx.work.WorkManagerInitializer" in registered) { + throw GradleException( + "Merged manifest (${manifest.path}) still contains androidx.work.WorkManagerInitializer: " + + "WorkManager would be initialised with its default WorkerFactory at process start, " + + "bypassing HhoApplication's HiltWorkerFactory, so SyncWorker could never be created. " + + "Restore the tools:node=\"remove\" meta-data entry in src/main/AndroidManifest.xml.", + ) + } + } +} + +tasks.configureEach { + if (name == "testGmsDebugUnitTest" || name == "testFossDebugUnitTest" || name == "check") { + dependsOn(checkNoWorkManagerDefaultInitializer) + } +} + +ksp { + arg("room.schemaLocation", layout.projectDirectory.dir("schemas").asFile.path) + arg("room.generateKotlin", "true") +} + +val apiClientPackagePath = "dev/hho/android/data/apiclient/generated" + +val openApiGenerateKotlinClient = tasks.register("openApiGenerateKotlinClient") { + group = "hho openapi" + description = "Generates the Kotlin API client from server/api/openapi.yaml into a scratch " + + "build directory (D3.3, T157a). Run `generateApiClient` instead to update the committed " + + "sources under data/apiclient/generated/." + + generatorName.set("kotlin") + library.set("jvm-okhttp4") + inputSpec.set(rootProject.layout.projectDirectory.file("../server/api/openapi.yaml").asFile.absolutePath) + outputDir.set(layout.buildDirectory.dir("generated/openapi").get().asFile.path) + packageName.set("dev.hho.android.data.apiclient.generated") + + configOptions.set( + mapOf( + "serializationLibrary" to "kotlinx_serialization", + "dateLibrary" to "java8", + "legacyDiscriminatorBehavior" to "false", + "enumPropertyNaming" to "PascalCase", + ), + ) + globalProperties.set( + mapOf( + "apiTests" to "false", + "modelTests" to "false", + "apiDocs" to "false", + "modelDocs" to "false", + ), + ) +} + +val apiClientGeneratedDir = layout.projectDirectory.dir("src/main/kotlin/$apiClientPackagePath") +val apiClientHeader = """ + |// SPDX-License-Identifier: AGPL-3.0-only + |// Generated by OpenAPI Generator from server/api/openapi.yaml — DO NOT EDIT BY HAND. + |// Regenerate via `./gradlew :app:generateApiClient` (D3.3, T157a/T157b). + +""".trimMargin() + +tasks.register("generateApiClient") { + group = "hho openapi" + description = "Regenerates the committed Kotlin API client under " + + "data/apiclient/generated/ from server/api/openapi.yaml (D3.3, T157a/T157b)." + + dependsOn(openApiGenerateKotlinClient) + from(layout.buildDirectory.dir("generated/openapi/src/main/kotlin/$apiClientPackagePath")) + into(apiClientGeneratedDir) + + doLast { + apiClientGeneratedDir.asFileTree.matching { include("**/*.kt") }.forEach { file -> + val text = file.readText() + if (!text.startsWith(apiClientHeader)) { + file.writeText(apiClientHeader + text) + } + } + } +} + +val apiClientDriftStageDir = layout.buildDirectory.dir("generated/openapi-drift-check") + +val stageApiClientForDriftCheck = tasks.register("stageApiClientForDriftCheck") { + group = "hho openapi" + description = "Regenerates the Kotlin API client into a scratch directory (never the " + + "committed src/ tree) for checkApiClientDrift to compare against (D3.3, T157d)." + + dependsOn(openApiGenerateKotlinClient) + from(layout.buildDirectory.dir("generated/openapi/src/main/kotlin/$apiClientPackagePath")) + into(apiClientDriftStageDir) + + doLast { + apiClientDriftStageDir.get().asFileTree.matching { include("**/*.kt") }.forEach { file -> + val text = file.readText() + if (!text.startsWith(apiClientHeader)) { + file.writeText(apiClientHeader + text) + } + } + } +} + +tasks.register("checkApiClientDrift") { + group = "hho openapi" + description = "CI drift gate (D3.3, T157d, NFR-032): fails if the committed Kotlin API " + + "client under data/apiclient/generated/ differs, byte-for-byte, from what " + + "server/api/openapi.yaml generates today." + + dependsOn(stageApiClientForDriftCheck) + + doLast { + val committedDir = apiClientGeneratedDir.asFile + val stagedDir = apiClientDriftStageDir.get().asFile + + fun relativeFiles(root: File) = root.walkTopDown().filter { it.isFile } + .map { it.relativeTo(root).path }.toSortedSet() + + val committedFiles = relativeFiles(committedDir) + val stagedFiles = relativeFiles(stagedDir) + val staleInCommitted = (committedFiles - stagedFiles).toSortedSet() + val missingFromCommitted = (stagedFiles - committedFiles).toSortedSet() + val changed = (committedFiles intersect stagedFiles).filterTo(sortedSetOf()) { rel -> + !committedDir.resolve(rel).readBytes().contentEquals(stagedDir.resolve(rel).readBytes()) + } + + if (staleInCommitted.isEmpty() && missingFromCommitted.isEmpty() && changed.isEmpty()) { + logger.lifecycle( + "checkApiClientDrift: no drift — the committed API client matches " + + "server/api/openapi.yaml.", + ) + return@doLast + } + + val message = buildString { + appendLine( + "Generated Kotlin API client drift detected: data/apiclient/generated/ no " + + "longer matches what server/api/openapi.yaml generates.", + ) + if (staleInCommitted.isNotEmpty()) { + appendLine(" stale (committed, no longer generated): $staleInCommitted") + } + if (missingFromCommitted.isNotEmpty()) { + appendLine(" missing (generated, not committed): $missingFromCommitted") + } + if (changed.isNotEmpty()) { + appendLine(" changed: $changed") + } + append("Fix: run './gradlew :app:generateApiClient' and commit the result.") + } + throw GradleException(message) + } +} + +val apiClientAdditiveProbeDir = layout.buildDirectory.dir("generated/openapi-additive-probe") +val apiClientAdditiveProbeSpec = apiClientAdditiveProbeDir.map { it.file("openapi.yaml") } +val apiClientAdditiveProbeOutputDir = apiClientAdditiveProbeDir.map { it.dir("output") } + +val additiveProbeOperationId = "getDiagnosticsPing" +val additiveProbePathYaml = """ + | /diagnostics/ping: + | get: + | operationId: $additiveProbeOperationId + | tags: [diagnostics] + | summary: "T157e synthetic additive-drift-tolerance probe — never implemented server-side." + | responses: + | "200": + | description: OK + | content: + | application/json: + | schema: + | type: object + | properties: + | status: + | type: string + | required: [status] + | +""".trimMargin() + +val stageAdditiveOpenApiProbeSpec = tasks.register("stageAdditiveOpenApiProbeSpec") { + group = "hho openapi" + description = "T157e: writes a scratch copy of server/api/openapi.yaml with one synthetic " + + "additive path grafted in, for checkApiClientAdditiveDriftTolerance to regenerate " + + "against. Never modifies the real openapi.yaml." + + val realSpecFile = rootProject.layout.projectDirectory.file("../server/api/openapi.yaml").asFile + val outSpecProvider = apiClientAdditiveProbeSpec + inputs.file(realSpecFile) + outputs.file(outSpecProvider) + + doLast { + val original = realSpecFile.readText() + check("/diagnostics/ping" !in original) { + "T157e's synthetic probe path '/diagnostics/ping' already exists in the real " + + "server/api/openapi.yaml — pick a different placeholder path for the probe, " + + "this check needs a path guaranteed not to be there yet." + } + + val marker = "\npaths:\n" + val markerIndex = original.indexOf(marker) + check(markerIndex >= 0) { + "T157e: could not find a top-level 'paths:' section in server/api/openapi.yaml to " + + "graft the synthetic additive probe path onto." + } + val insertAt = markerIndex + marker.length + val mutated = original.substring(0, insertAt) + additiveProbePathYaml + + original.substring(insertAt) + + val outFile = outSpecProvider.get().asFile + outFile.parentFile.mkdirs() + outFile.writeText(mutated) + } +} + +val openApiGenerateAdditiveProbeClient = tasks.register("openApiGenerateAdditiveProbeClient") { + group = "hho openapi" + description = "T157e: regenerates the Kotlin API client from the mutated scratch spec " + + "(server/api/openapi.yaml plus one synthetic additive path) into its own scratch " + + "output directory." + + dependsOn(stageAdditiveOpenApiProbeSpec) + generatorName.set("kotlin") + library.set("jvm-okhttp4") + inputSpec.set(apiClientAdditiveProbeSpec.get().asFile.absolutePath) + outputDir.set(apiClientAdditiveProbeOutputDir.get().asFile.path) + packageName.set("dev.hho.android.data.apiclient.generated") + + configOptions.set( + mapOf( + "serializationLibrary" to "kotlinx_serialization", + "dateLibrary" to "java8", + "legacyDiscriminatorBehavior" to "false", + "enumPropertyNaming" to "PascalCase", + ), + ) + globalProperties.set( + mapOf( + "apiTests" to "false", + "modelTests" to "false", + "apiDocs" to "false", + "modelDocs" to "false", + ), + ) +} + +tasks.register("checkApiClientAdditiveDriftTolerance") { + group = "hho openapi" + description = "T157e / NFR-032, D3.3 cross-phase check: proves an additive openapi.yaml " + + "path (a synthetic probe route standing in for a future real addition, e.g. D2.3's " + + "postponed /import/homebox/* per A161) regenerates cleanly instead of being treated " + + "as unexpected drift. Runs entirely against scratch copies of the spec and client " + + "output — never touches the real openapi.yaml or the committed generated/ client." + + dependsOn(openApiGenerateAdditiveProbeClient) + + doLast { + val outputDir = apiClientAdditiveProbeOutputDir.get().asFile + check(outputDir.exists() && outputDir.isDirectory) { + "checkApiClientAdditiveDriftTolerance: expected generator output directory at " + + "${outputDir.path} — the additive-probe generation run did not produce one." + } + + val generatedFiles = outputDir.walkTopDown().filter { it.isFile }.toList() + check(generatedFiles.isNotEmpty()) { + "checkApiClientAdditiveDriftTolerance: additive-probe generation produced an empty " + + "output tree — regenerating against a spec with a new path must still emit files." + } + + val newApiFile = generatedFiles.firstOrNull { it.name.equals("DiagnosticsApi.kt", ignoreCase = true) } + check(newApiFile != null) { + "checkApiClientAdditiveDriftTolerance: expected a generated DiagnosticsApi.kt for " + + "the synthetic /diagnostics/ping probe path (new tag => new file is how this " + + "check tells 'the new path was picked up' from 'generation silently ignored " + + "it'); got: ${generatedFiles.map { it.name }.sorted()}" + } + check(newApiFile.readText().contains(additiveProbeOperationId)) { + "checkApiClientAdditiveDriftTolerance: generated DiagnosticsApi.kt does not " + + "contain the probe operation '$additiveProbeOperationId'." + } + + logger.lifecycle( + "checkApiClientAdditiveDriftTolerance: PASS — an additive openapi.yaml path " + + "regenerates cleanly (new file: ${newApiFile.relativeTo(outputDir)}), " + + "confirming the drift check above would pick it up rather than reject it.", + ) + } +} diff --git a/android-app/app/proguard-rules.pro b/android-app/app/proguard-rules.pro new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/android-app/app/proguard-rules.pro @@ -0,0 +1 @@ + diff --git a/android-app/app/schemas/dev.hho.android.data.room.HhoDatabase/1.json b/android-app/app/schemas/dev.hho.android.data.room.HhoDatabase/1.json new file mode 100644 index 0000000..f7ba19f --- /dev/null +++ b/android-app/app/schemas/dev.hho.android.data.room.HhoDatabase/1.json @@ -0,0 +1,876 @@ +{ + "formatVersion": 1, + "database": { + "version": 1, + "identityHash": "be4445a849992c8135699d0c150a8c88", + "entities": [ + { + "tableName": "item", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `group_change_seq` INTEGER NOT NULL, `name` TEXT NOT NULL, `description` TEXT, `location_id` TEXT, `quantity` INTEGER, `short_code` TEXT, `created_at` INTEGER, `updated_at` INTEGER, `version` INTEGER, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "groupChangeSeq", + "columnName": "group_change_seq", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT" + }, + { + "fieldPath": "locationId", + "columnName": "location_id", + "affinity": "TEXT" + }, + { + "fieldPath": "quantity", + "columnName": "quantity", + "affinity": "INTEGER" + }, + { + "fieldPath": "shortCode", + "columnName": "short_code", + "affinity": "TEXT" + }, + { + "fieldPath": "createdAt", + "columnName": "created_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "updatedAt", + "columnName": "updated_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_item_location_id", + "unique": false, + "columnNames": [ + "location_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_item_location_id` ON `${TABLE_NAME}` (`location_id`)" + } + ] + }, + { + "tableName": "warranty_block", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `group_change_seq` INTEGER NOT NULL, `item_id` TEXT, `is_lifetime` INTEGER NOT NULL, `holder` TEXT, `provider` TEXT, `starts_on` INTEGER, `expires_on` INTEGER, `notes` TEXT, `created_at` INTEGER, `updated_at` INTEGER, `version` INTEGER, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "groupChangeSeq", + "columnName": "group_change_seq", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "itemId", + "columnName": "item_id", + "affinity": "TEXT" + }, + { + "fieldPath": "isLifetime", + "columnName": "is_lifetime", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "holder", + "columnName": "holder", + "affinity": "TEXT" + }, + { + "fieldPath": "provider", + "columnName": "provider", + "affinity": "TEXT" + }, + { + "fieldPath": "startsOn", + "columnName": "starts_on", + "affinity": "INTEGER" + }, + { + "fieldPath": "expiresOn", + "columnName": "expires_on", + "affinity": "INTEGER" + }, + { + "fieldPath": "notes", + "columnName": "notes", + "affinity": "TEXT" + }, + { + "fieldPath": "createdAt", + "columnName": "created_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "updatedAt", + "columnName": "updated_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_warranty_block_item_id", + "unique": false, + "columnNames": [ + "item_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_warranty_block_item_id` ON `${TABLE_NAME}` (`item_id`)" + } + ] + }, + { + "tableName": "sold_to_block", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `group_change_seq` INTEGER NOT NULL, `item_id` TEXT, `sale_price_minor` INTEGER NOT NULL, `buyer_name` TEXT, `sold_on` INTEGER, `notes` TEXT, `created_at` INTEGER, `updated_at` INTEGER, `version` INTEGER, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "groupChangeSeq", + "columnName": "group_change_seq", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "itemId", + "columnName": "item_id", + "affinity": "TEXT" + }, + { + "fieldPath": "salePriceMinor", + "columnName": "sale_price_minor", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "buyerName", + "columnName": "buyer_name", + "affinity": "TEXT" + }, + { + "fieldPath": "soldOn", + "columnName": "sold_on", + "affinity": "INTEGER" + }, + { + "fieldPath": "notes", + "columnName": "notes", + "affinity": "TEXT" + }, + { + "fieldPath": "createdAt", + "columnName": "created_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "updatedAt", + "columnName": "updated_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_sold_to_block_item_id", + "unique": false, + "columnNames": [ + "item_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_sold_to_block_item_id` ON `${TABLE_NAME}` (`item_id`)" + } + ] + }, + { + "tableName": "purchased_from_block", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `group_change_seq` INTEGER NOT NULL, `item_id` TEXT, `purchase_price_minor` INTEGER NOT NULL, `vendor` TEXT, `purchased_on` INTEGER, `order_reference` TEXT, `notes` TEXT, `created_at` INTEGER, `updated_at` INTEGER, `version` INTEGER, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "groupChangeSeq", + "columnName": "group_change_seq", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "itemId", + "columnName": "item_id", + "affinity": "TEXT" + }, + { + "fieldPath": "purchasePriceMinor", + "columnName": "purchase_price_minor", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "vendor", + "columnName": "vendor", + "affinity": "TEXT" + }, + { + "fieldPath": "purchasedOn", + "columnName": "purchased_on", + "affinity": "INTEGER" + }, + { + "fieldPath": "orderReference", + "columnName": "order_reference", + "affinity": "TEXT" + }, + { + "fieldPath": "notes", + "columnName": "notes", + "affinity": "TEXT" + }, + { + "fieldPath": "createdAt", + "columnName": "created_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "updatedAt", + "columnName": "updated_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_purchased_from_block_item_id", + "unique": false, + "columnNames": [ + "item_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_purchased_from_block_item_id` ON `${TABLE_NAME}` (`item_id`)" + } + ] + }, + { + "tableName": "item_identification", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `group_change_seq` INTEGER NOT NULL, `item_id` TEXT, `kind` TEXT NOT NULL, `value` TEXT NOT NULL, `created_at` INTEGER, `updated_at` INTEGER, `version` INTEGER, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "groupChangeSeq", + "columnName": "group_change_seq", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "itemId", + "columnName": "item_id", + "affinity": "TEXT" + }, + { + "fieldPath": "kind", + "columnName": "kind", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "value", + "columnName": "value", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "created_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "updatedAt", + "columnName": "updated_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_item_identification_item_id", + "unique": false, + "columnNames": [ + "item_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_item_identification_item_id` ON `${TABLE_NAME}` (`item_id`)" + }, + { + "name": "index_item_identification_value", + "unique": false, + "columnNames": [ + "value" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_item_identification_value` ON `${TABLE_NAME}` (`value`)" + } + ] + }, + { + "tableName": "item_custom_field", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `group_change_seq` INTEGER NOT NULL, `item_id` TEXT, `name` TEXT NOT NULL, `field_type` TEXT NOT NULL, `field_def_id` TEXT, `text_value` TEXT, `number_value` TEXT, `bool_value` INTEGER, `date_value` INTEGER, `created_at` INTEGER, `updated_at` INTEGER, `version` INTEGER, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "groupChangeSeq", + "columnName": "group_change_seq", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "itemId", + "columnName": "item_id", + "affinity": "TEXT" + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "fieldType", + "columnName": "field_type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "fieldDefId", + "columnName": "field_def_id", + "affinity": "TEXT" + }, + { + "fieldPath": "textValue", + "columnName": "text_value", + "affinity": "TEXT" + }, + { + "fieldPath": "numberValue", + "columnName": "number_value", + "affinity": "TEXT" + }, + { + "fieldPath": "boolValue", + "columnName": "bool_value", + "affinity": "INTEGER" + }, + { + "fieldPath": "dateValue", + "columnName": "date_value", + "affinity": "INTEGER" + }, + { + "fieldPath": "createdAt", + "columnName": "created_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "updatedAt", + "columnName": "updated_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_item_custom_field_item_id", + "unique": false, + "columnNames": [ + "item_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_item_custom_field_item_id` ON `${TABLE_NAME}` (`item_id`)" + } + ] + }, + { + "tableName": "stock_adjustment", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `group_change_seq` INTEGER NOT NULL, `item_id` TEXT, `delta` INTEGER NOT NULL, `resulting_quantity` INTEGER NOT NULL, `reason` TEXT, `note` TEXT, `created_at` INTEGER, `updated_at` INTEGER, `version` INTEGER, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "groupChangeSeq", + "columnName": "group_change_seq", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "itemId", + "columnName": "item_id", + "affinity": "TEXT" + }, + { + "fieldPath": "delta", + "columnName": "delta", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "resultingQuantity", + "columnName": "resulting_quantity", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "reason", + "columnName": "reason", + "affinity": "TEXT" + }, + { + "fieldPath": "note", + "columnName": "note", + "affinity": "TEXT" + }, + { + "fieldPath": "createdAt", + "columnName": "created_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "updatedAt", + "columnName": "updated_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_stock_adjustment_item_id", + "unique": false, + "columnNames": [ + "item_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_stock_adjustment_item_id` ON `${TABLE_NAME}` (`item_id`)" + } + ] + }, + { + "tableName": "location", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `group_change_seq` INTEGER NOT NULL, `name` TEXT NOT NULL, `parent_id` TEXT, `created_at` INTEGER NOT NULL, `updated_at` INTEGER NOT NULL, `version` INTEGER NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "groupChangeSeq", + "columnName": "group_change_seq", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "parentId", + "columnName": "parent_id", + "affinity": "TEXT" + }, + { + "fieldPath": "createdAt", + "columnName": "created_at", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "updatedAt", + "columnName": "updated_at", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_location_parent_id", + "unique": false, + "columnNames": [ + "parent_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_location_parent_id` ON `${TABLE_NAME}` (`parent_id`)" + } + ] + }, + { + "tableName": "label", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `group_change_seq` INTEGER NOT NULL, `name` TEXT NOT NULL, `color` TEXT NOT NULL, `created_at` INTEGER NOT NULL, `updated_at` INTEGER NOT NULL, `version` INTEGER NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "groupChangeSeq", + "columnName": "group_change_seq", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "created_at", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "updatedAt", + "columnName": "updated_at", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + } + }, + { + "tableName": "item_label", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `group_change_seq` INTEGER NOT NULL, `item_id` TEXT NOT NULL, `label_id` TEXT NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "groupChangeSeq", + "columnName": "group_change_seq", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "itemId", + "columnName": "item_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "labelId", + "columnName": "label_id", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_item_label_item_id", + "unique": false, + "columnNames": [ + "item_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_item_label_item_id` ON `${TABLE_NAME}` (`item_id`)" + }, + { + "name": "index_item_label_label_id", + "unique": false, + "columnNames": [ + "label_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_item_label_label_id` ON `${TABLE_NAME}` (`label_id`)" + } + ] + }, + { + "tableName": "attachment", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `group_change_seq` INTEGER NOT NULL, `item_id` TEXT NOT NULL, `category` TEXT NOT NULL, `original_filename` TEXT NOT NULL, `content_type` TEXT NOT NULL, `size_bytes` INTEGER NOT NULL, `sha256` TEXT NOT NULL, `has_thumbnail` INTEGER NOT NULL, `created_at` INTEGER NOT NULL, `updated_at` INTEGER NOT NULL, `version` INTEGER NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "groupChangeSeq", + "columnName": "group_change_seq", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "itemId", + "columnName": "item_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "category", + "columnName": "category", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "originalFilename", + "columnName": "original_filename", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "contentType", + "columnName": "content_type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sizeBytes", + "columnName": "size_bytes", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "sha256", + "columnName": "sha256", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "hasThumbnail", + "columnName": "has_thumbnail", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "created_at", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "updatedAt", + "columnName": "updated_at", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_attachment_item_id", + "unique": false, + "columnNames": [ + "item_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_attachment_item_id` ON `${TABLE_NAME}` (`item_id`)" + } + ] + }, + { + "tableName": "sync_state", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `watermark` INTEGER NOT NULL, `lastSyncedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "watermark", + "columnName": "watermark", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastSyncedAt", + "columnName": "lastSyncedAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + } + } + ], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'be4445a849992c8135699d0c150a8c88')" + ] + } +} \ No newline at end of file diff --git a/android-app/app/schemas/dev.hho.android.data.room.HhoDatabase/2.json b/android-app/app/schemas/dev.hho.android.data.room.HhoDatabase/2.json new file mode 100644 index 0000000..2996566 --- /dev/null +++ b/android-app/app/schemas/dev.hho.android.data.room.HhoDatabase/2.json @@ -0,0 +1,1311 @@ +{ + "formatVersion": 1, + "database": { + "version": 2, + "identityHash": "4745a84ecf5a5ab0344dd116f6b92f45", + "entities": [ + { + "tableName": "item", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `group_change_seq` INTEGER NOT NULL, `name` TEXT NOT NULL, `description` TEXT, `location_id` TEXT, `quantity` INTEGER, `short_code` TEXT, `created_at` INTEGER, `updated_at` INTEGER, `version` INTEGER, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "groupChangeSeq", + "columnName": "group_change_seq", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT" + }, + { + "fieldPath": "locationId", + "columnName": "location_id", + "affinity": "TEXT" + }, + { + "fieldPath": "quantity", + "columnName": "quantity", + "affinity": "INTEGER" + }, + { + "fieldPath": "shortCode", + "columnName": "short_code", + "affinity": "TEXT" + }, + { + "fieldPath": "createdAt", + "columnName": "created_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "updatedAt", + "columnName": "updated_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_item_location_id", + "unique": false, + "columnNames": [ + "location_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_item_location_id` ON `${TABLE_NAME}` (`location_id`)" + } + ] + }, + { + "tableName": "warranty_block", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `group_change_seq` INTEGER NOT NULL, `item_id` TEXT, `is_lifetime` INTEGER NOT NULL, `holder` TEXT, `provider` TEXT, `starts_on` INTEGER, `expires_on` INTEGER, `notes` TEXT, `created_at` INTEGER, `updated_at` INTEGER, `version` INTEGER, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "groupChangeSeq", + "columnName": "group_change_seq", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "itemId", + "columnName": "item_id", + "affinity": "TEXT" + }, + { + "fieldPath": "isLifetime", + "columnName": "is_lifetime", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "holder", + "columnName": "holder", + "affinity": "TEXT" + }, + { + "fieldPath": "provider", + "columnName": "provider", + "affinity": "TEXT" + }, + { + "fieldPath": "startsOn", + "columnName": "starts_on", + "affinity": "INTEGER" + }, + { + "fieldPath": "expiresOn", + "columnName": "expires_on", + "affinity": "INTEGER" + }, + { + "fieldPath": "notes", + "columnName": "notes", + "affinity": "TEXT" + }, + { + "fieldPath": "createdAt", + "columnName": "created_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "updatedAt", + "columnName": "updated_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_warranty_block_item_id", + "unique": false, + "columnNames": [ + "item_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_warranty_block_item_id` ON `${TABLE_NAME}` (`item_id`)" + } + ] + }, + { + "tableName": "sold_to_block", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `group_change_seq` INTEGER NOT NULL, `item_id` TEXT, `sale_price_minor` INTEGER NOT NULL, `buyer_name` TEXT, `sold_on` INTEGER, `notes` TEXT, `created_at` INTEGER, `updated_at` INTEGER, `version` INTEGER, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "groupChangeSeq", + "columnName": "group_change_seq", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "itemId", + "columnName": "item_id", + "affinity": "TEXT" + }, + { + "fieldPath": "salePriceMinor", + "columnName": "sale_price_minor", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "buyerName", + "columnName": "buyer_name", + "affinity": "TEXT" + }, + { + "fieldPath": "soldOn", + "columnName": "sold_on", + "affinity": "INTEGER" + }, + { + "fieldPath": "notes", + "columnName": "notes", + "affinity": "TEXT" + }, + { + "fieldPath": "createdAt", + "columnName": "created_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "updatedAt", + "columnName": "updated_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_sold_to_block_item_id", + "unique": false, + "columnNames": [ + "item_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_sold_to_block_item_id` ON `${TABLE_NAME}` (`item_id`)" + } + ] + }, + { + "tableName": "purchased_from_block", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `group_change_seq` INTEGER NOT NULL, `item_id` TEXT, `purchase_price_minor` INTEGER NOT NULL, `vendor` TEXT, `purchased_on` INTEGER, `order_reference` TEXT, `notes` TEXT, `created_at` INTEGER, `updated_at` INTEGER, `version` INTEGER, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "groupChangeSeq", + "columnName": "group_change_seq", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "itemId", + "columnName": "item_id", + "affinity": "TEXT" + }, + { + "fieldPath": "purchasePriceMinor", + "columnName": "purchase_price_minor", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "vendor", + "columnName": "vendor", + "affinity": "TEXT" + }, + { + "fieldPath": "purchasedOn", + "columnName": "purchased_on", + "affinity": "INTEGER" + }, + { + "fieldPath": "orderReference", + "columnName": "order_reference", + "affinity": "TEXT" + }, + { + "fieldPath": "notes", + "columnName": "notes", + "affinity": "TEXT" + }, + { + "fieldPath": "createdAt", + "columnName": "created_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "updatedAt", + "columnName": "updated_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_purchased_from_block_item_id", + "unique": false, + "columnNames": [ + "item_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_purchased_from_block_item_id` ON `${TABLE_NAME}` (`item_id`)" + } + ] + }, + { + "tableName": "item_identification", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `group_change_seq` INTEGER NOT NULL, `item_id` TEXT, `kind` TEXT NOT NULL, `value` TEXT NOT NULL, `created_at` INTEGER, `updated_at` INTEGER, `version` INTEGER, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "groupChangeSeq", + "columnName": "group_change_seq", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "itemId", + "columnName": "item_id", + "affinity": "TEXT" + }, + { + "fieldPath": "kind", + "columnName": "kind", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "value", + "columnName": "value", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "created_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "updatedAt", + "columnName": "updated_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_item_identification_item_id", + "unique": false, + "columnNames": [ + "item_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_item_identification_item_id` ON `${TABLE_NAME}` (`item_id`)" + }, + { + "name": "index_item_identification_value", + "unique": false, + "columnNames": [ + "value" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_item_identification_value` ON `${TABLE_NAME}` (`value`)" + } + ] + }, + { + "tableName": "item_custom_field", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `group_change_seq` INTEGER NOT NULL, `item_id` TEXT, `name` TEXT NOT NULL, `field_type` TEXT NOT NULL, `field_def_id` TEXT, `text_value` TEXT, `number_value` TEXT, `bool_value` INTEGER, `date_value` INTEGER, `created_at` INTEGER, `updated_at` INTEGER, `version` INTEGER, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "groupChangeSeq", + "columnName": "group_change_seq", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "itemId", + "columnName": "item_id", + "affinity": "TEXT" + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "fieldType", + "columnName": "field_type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "fieldDefId", + "columnName": "field_def_id", + "affinity": "TEXT" + }, + { + "fieldPath": "textValue", + "columnName": "text_value", + "affinity": "TEXT" + }, + { + "fieldPath": "numberValue", + "columnName": "number_value", + "affinity": "TEXT" + }, + { + "fieldPath": "boolValue", + "columnName": "bool_value", + "affinity": "INTEGER" + }, + { + "fieldPath": "dateValue", + "columnName": "date_value", + "affinity": "INTEGER" + }, + { + "fieldPath": "createdAt", + "columnName": "created_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "updatedAt", + "columnName": "updated_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_item_custom_field_item_id", + "unique": false, + "columnNames": [ + "item_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_item_custom_field_item_id` ON `${TABLE_NAME}` (`item_id`)" + } + ] + }, + { + "tableName": "stock_adjustment", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `group_change_seq` INTEGER NOT NULL, `item_id` TEXT, `delta` INTEGER NOT NULL, `resulting_quantity` INTEGER NOT NULL, `reason` TEXT, `note` TEXT, `created_at` INTEGER, `updated_at` INTEGER, `version` INTEGER, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "groupChangeSeq", + "columnName": "group_change_seq", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "itemId", + "columnName": "item_id", + "affinity": "TEXT" + }, + { + "fieldPath": "delta", + "columnName": "delta", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "resultingQuantity", + "columnName": "resulting_quantity", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "reason", + "columnName": "reason", + "affinity": "TEXT" + }, + { + "fieldPath": "note", + "columnName": "note", + "affinity": "TEXT" + }, + { + "fieldPath": "createdAt", + "columnName": "created_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "updatedAt", + "columnName": "updated_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_stock_adjustment_item_id", + "unique": false, + "columnNames": [ + "item_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_stock_adjustment_item_id` ON `${TABLE_NAME}` (`item_id`)" + } + ] + }, + { + "tableName": "location", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `group_change_seq` INTEGER NOT NULL, `name` TEXT NOT NULL, `parent_id` TEXT, `created_at` INTEGER NOT NULL, `updated_at` INTEGER NOT NULL, `version` INTEGER NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "groupChangeSeq", + "columnName": "group_change_seq", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "parentId", + "columnName": "parent_id", + "affinity": "TEXT" + }, + { + "fieldPath": "createdAt", + "columnName": "created_at", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "updatedAt", + "columnName": "updated_at", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_location_parent_id", + "unique": false, + "columnNames": [ + "parent_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_location_parent_id` ON `${TABLE_NAME}` (`parent_id`)" + } + ] + }, + { + "tableName": "label", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `group_change_seq` INTEGER NOT NULL, `name` TEXT NOT NULL, `color` TEXT NOT NULL, `created_at` INTEGER NOT NULL, `updated_at` INTEGER NOT NULL, `version` INTEGER NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "groupChangeSeq", + "columnName": "group_change_seq", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "created_at", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "updatedAt", + "columnName": "updated_at", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + } + }, + { + "tableName": "item_label", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `group_change_seq` INTEGER NOT NULL, `item_id` TEXT NOT NULL, `label_id` TEXT NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "groupChangeSeq", + "columnName": "group_change_seq", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "itemId", + "columnName": "item_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "labelId", + "columnName": "label_id", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_item_label_item_id", + "unique": false, + "columnNames": [ + "item_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_item_label_item_id` ON `${TABLE_NAME}` (`item_id`)" + }, + { + "name": "index_item_label_label_id", + "unique": false, + "columnNames": [ + "label_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_item_label_label_id` ON `${TABLE_NAME}` (`label_id`)" + } + ] + }, + { + "tableName": "attachment", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `group_change_seq` INTEGER NOT NULL, `item_id` TEXT NOT NULL, `category` TEXT NOT NULL, `original_filename` TEXT NOT NULL, `content_type` TEXT NOT NULL, `size_bytes` INTEGER NOT NULL, `sha256` TEXT NOT NULL, `has_thumbnail` INTEGER NOT NULL, `created_at` INTEGER NOT NULL, `updated_at` INTEGER NOT NULL, `version` INTEGER NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "groupChangeSeq", + "columnName": "group_change_seq", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "itemId", + "columnName": "item_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "category", + "columnName": "category", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "originalFilename", + "columnName": "original_filename", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "contentType", + "columnName": "content_type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sizeBytes", + "columnName": "size_bytes", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "sha256", + "columnName": "sha256", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "hasThumbnail", + "columnName": "has_thumbnail", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "created_at", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "updatedAt", + "columnName": "updated_at", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_attachment_item_id", + "unique": false, + "columnNames": [ + "item_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_attachment_item_id` ON `${TABLE_NAME}` (`item_id`)" + } + ] + }, + { + "tableName": "sync_state", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `watermark` INTEGER NOT NULL, `lastSyncedAt` INTEGER NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "watermark", + "columnName": "watermark", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastSyncedAt", + "columnName": "lastSyncedAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + } + }, + { + "tableName": "outbox_mutation", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`seq` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `mutation_id` TEXT NOT NULL, `entity_type` TEXT NOT NULL, `entity_id` TEXT NOT NULL, `op` TEXT NOT NULL, `base_version` INTEGER NOT NULL, `fields_json` TEXT NOT NULL, `state` TEXT NOT NULL, `attempt_count` INTEGER NOT NULL, `last_error` TEXT, `last_attempt_at` INTEGER, `created_at` INTEGER NOT NULL)", + "fields": [ + { + "fieldPath": "seq", + "columnName": "seq", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "mutationId", + "columnName": "mutation_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "entityType", + "columnName": "entity_type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "entityId", + "columnName": "entity_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "op", + "columnName": "op", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "baseVersion", + "columnName": "base_version", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "fieldsJson", + "columnName": "fields_json", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "state", + "columnName": "state", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "attemptCount", + "columnName": "attempt_count", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastError", + "columnName": "last_error", + "affinity": "TEXT" + }, + { + "fieldPath": "lastAttemptAt", + "columnName": "last_attempt_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "createdAt", + "columnName": "created_at", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "seq" + ] + }, + "indices": [ + { + "name": "index_outbox_mutation_mutation_id", + "unique": true, + "columnNames": [ + "mutation_id" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_outbox_mutation_mutation_id` ON `${TABLE_NAME}` (`mutation_id`)" + }, + { + "name": "index_outbox_mutation_state_seq", + "unique": false, + "columnNames": [ + "state", + "seq" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_outbox_mutation_state_seq` ON `${TABLE_NAME}` (`state`, `seq`)" + }, + { + "name": "index_outbox_mutation_entity_type_entity_id", + "unique": false, + "columnNames": [ + "entity_type", + "entity_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_outbox_mutation_entity_type_entity_id` ON `${TABLE_NAME}` (`entity_type`, `entity_id`)" + } + ] + }, + { + "tableName": "receiving_session", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `vendor` TEXT NOT NULL, `order_reference` TEXT, `purchased_on` INTEGER, `status` TEXT NOT NULL, `created_at` INTEGER NOT NULL, `completed_at` INTEGER, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "vendor", + "columnName": "vendor", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "orderReference", + "columnName": "order_reference", + "affinity": "TEXT" + }, + { + "fieldPath": "purchasedOn", + "columnName": "purchased_on", + "affinity": "INTEGER" + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "created_at", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "completedAt", + "columnName": "completed_at", + "affinity": "INTEGER" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_receiving_session_status", + "unique": false, + "columnNames": [ + "status" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_receiving_session_status` ON `${TABLE_NAME}` (`status`)" + } + ] + }, + { + "tableName": "receiving_line", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`session_id` TEXT NOT NULL, `item_id` TEXT NOT NULL, `expected_qty` INTEGER, `received_qty` INTEGER NOT NULL, PRIMARY KEY(`session_id`, `item_id`))", + "fields": [ + { + "fieldPath": "sessionId", + "columnName": "session_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "itemId", + "columnName": "item_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "expectedQty", + "columnName": "expected_qty", + "affinity": "INTEGER" + }, + { + "fieldPath": "receivedQty", + "columnName": "received_qty", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "session_id", + "item_id" + ] + } + }, + { + "tableName": "photo_queue_entry", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `item_id` TEXT NOT NULL, `file_path` TEXT NOT NULL, `sha256` TEXT NOT NULL, `size_bytes` INTEGER NOT NULL, `category` TEXT NOT NULL, `state` TEXT NOT NULL, `attempt_count` INTEGER NOT NULL, `next_attempt_at` INTEGER, `last_error` TEXT, `created_at` INTEGER NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "itemId", + "columnName": "item_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "filePath", + "columnName": "file_path", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sha256", + "columnName": "sha256", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sizeBytes", + "columnName": "size_bytes", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "category", + "columnName": "category", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "state", + "columnName": "state", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "attemptCount", + "columnName": "attempt_count", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "nextAttemptAt", + "columnName": "next_attempt_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "lastError", + "columnName": "last_error", + "affinity": "TEXT" + }, + { + "fieldPath": "createdAt", + "columnName": "created_at", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_photo_queue_entry_state_created_at", + "unique": false, + "columnNames": [ + "state", + "created_at" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_photo_queue_entry_state_created_at` ON `${TABLE_NAME}` (`state`, `created_at`)" + }, + { + "name": "index_photo_queue_entry_item_id", + "unique": false, + "columnNames": [ + "item_id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_photo_queue_entry_item_id` ON `${TABLE_NAME}` (`item_id`)" + } + ] + }, + { + "tableName": "conflict_record", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `mutation_id` TEXT NOT NULL, `entity_type` TEXT NOT NULL, `entity_id` TEXT NOT NULL, `field_name` TEXT NOT NULL, `losing_value_json` TEXT, `server_value_json` TEXT, `detected_at` INTEGER NOT NULL, `origin` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "mutationId", + "columnName": "mutation_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "entityType", + "columnName": "entity_type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "entityId", + "columnName": "entity_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "fieldName", + "columnName": "field_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "losingValueJson", + "columnName": "losing_value_json", + "affinity": "TEXT" + }, + { + "fieldPath": "serverValueJson", + "columnName": "server_value_json", + "affinity": "TEXT" + }, + { + "fieldPath": "detectedAt", + "columnName": "detected_at", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "origin", + "columnName": "origin", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "index_conflict_record_mutation_id_entity_id_field_name", + "unique": true, + "columnNames": [ + "mutation_id", + "entity_id", + "field_name" + ], + "orders": [], + "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_conflict_record_mutation_id_entity_id_field_name` ON `${TABLE_NAME}` (`mutation_id`, `entity_id`, `field_name`)" + } + ] + }, + { + "tableName": "sync_run_state", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `last_run_at` INTEGER, `last_push_at` INTEGER, `last_error` TEXT, `last_error_at` INTEGER, `conflict_cursor` TEXT, `reconcile_pending` INTEGER NOT NULL DEFAULT 0, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastRunAt", + "columnName": "last_run_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "lastPushAt", + "columnName": "last_push_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "lastError", + "columnName": "last_error", + "affinity": "TEXT" + }, + { + "fieldPath": "lastErrorAt", + "columnName": "last_error_at", + "affinity": "INTEGER" + }, + { + "fieldPath": "conflictCursor", + "columnName": "conflict_cursor", + "affinity": "TEXT" + }, + { + "fieldPath": "reconcilePending", + "columnName": "reconcile_pending", + "affinity": "INTEGER", + "notNull": true, + "defaultValue": "0" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + } + } + ], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '4745a84ecf5a5ab0344dd116f6b92f45')" + ] + } +} \ No newline at end of file diff --git a/android-app/app/src/androidTest/kotlin/dev/hho/android/HhoHiltTestRunner.kt b/android-app/app/src/androidTest/kotlin/dev/hho/android/HhoHiltTestRunner.kt new file mode 100644 index 0000000..d09639c --- /dev/null +++ b/android-app/app/src/androidTest/kotlin/dev/hho/android/HhoHiltTestRunner.kt @@ -0,0 +1,11 @@ +package dev.hho.android + +import android.app.Application +import android.content.Context +import androidx.test.runner.AndroidJUnitRunner +import dagger.hilt.android.testing.HiltTestApplication + +class HhoHiltTestRunner : AndroidJUnitRunner() { + override fun newApplication(cl: ClassLoader?, className: String?, context: Context?): Application = + super.newApplication(cl, HiltTestApplication::class.java.name, context) +} diff --git a/android-app/app/src/androidTest/kotlin/dev/hho/android/testing/AirplaneModeRule.kt b/android-app/app/src/androidTest/kotlin/dev/hho/android/testing/AirplaneModeRule.kt new file mode 100644 index 0000000..885bc69 --- /dev/null +++ b/android-app/app/src/androidTest/kotlin/dev/hho/android/testing/AirplaneModeRule.kt @@ -0,0 +1,50 @@ +package dev.hho.android.testing + +import android.content.Context +import android.net.ConnectivityManager +import android.net.NetworkCapabilities +import android.os.SystemClock +import androidx.test.platform.app.InstrumentationRegistry +import org.junit.rules.ExternalResource +import java.io.FileInputStream + +class AirplaneModeRule : ExternalResource() { + + private val instrumentation get() = InstrumentationRegistry.getInstrumentation() + + override fun before() { + shell("cmd connectivity airplane-mode enable") + shell("svc wifi disable") + shell("svc data disable") + val deadline = SystemClock.elapsedRealtime() + TIMEOUT_MILLIS + while (hasInternet()) { + check(SystemClock.elapsedRealtime() < deadline) { + "Device still reports an active internet-capable network ${TIMEOUT_MILLIS}ms after enabling airplane mode" + } + Thread.sleep(POLL_MILLIS) + } + } + + override fun after() { + shell("cmd connectivity airplane-mode disable") + shell("svc wifi enable") + shell("svc data enable") + } + + fun hasInternet(): Boolean { + val cm = instrumentation.targetContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + val caps = cm.getNetworkCapabilities(cm.activeNetwork ?: return false) ?: return false + return caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + } + + private fun shell(command: String) { + instrumentation.uiAutomation.executeShellCommand(command).use { pfd -> + FileInputStream(pfd.fileDescriptor).use { it.readBytes() } + } + } + + private companion object { + const val TIMEOUT_MILLIS = 20_000L + const val POLL_MILLIS = 250L + } +} diff --git a/android-app/app/src/androidTest/kotlin/dev/hho/android/testing/TestModules.kt b/android-app/app/src/androidTest/kotlin/dev/hho/android/testing/TestModules.kt new file mode 100644 index 0000000..9a60729 --- /dev/null +++ b/android-app/app/src/androidTest/kotlin/dev/hho/android/testing/TestModules.kt @@ -0,0 +1,96 @@ +package dev.hho.android.testing + +import android.content.Context +import androidx.datastore.core.DataStore +import androidx.datastore.preferences.core.PreferenceDataStoreFactory +import androidx.datastore.preferences.core.Preferences +import androidx.room.Room +import dagger.Module +import dagger.Provides +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent +import dagger.hilt.testing.TestInstallIn +import dev.hho.android.data.room.HhoDatabase +import dev.hho.android.di.DataStoreModule +import dev.hho.android.di.DeviceTokenDataStore +import dev.hho.android.di.NetworkModule +import dev.hho.android.di.ProbeHttpClient +import dev.hho.android.di.RoomModule +import okhttp3.Interceptor +import okhttp3.OkHttpClient +import java.io.File +import java.io.IOException +import java.util.UUID +import java.util.Collections +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class NetworkTripwire @Inject constructor() : Interceptor { + val requests: MutableList = Collections.synchronizedList(mutableListOf()) + + override fun intercept(chain: Interceptor.Chain): okhttp3.Response { + requests += "${chain.request().method} ${chain.request().url}" + throw IOException("NetworkTripwire: network access attempted in an offline test") + } +} + +@Module +@TestInstallIn(components = [SingletonComponent::class], replaces = [RoomModule::class]) +object TestRoomModule { + @Provides + @Singleton + fun provideDatabase(@ApplicationContext context: Context): HhoDatabase = + Room.inMemoryDatabaseBuilder(context, HhoDatabase::class.java).allowMainThreadQueries().build() + + @Provides fun itemDao(db: HhoDatabase) = db.itemDao() + @Provides fun warrantyBlockDao(db: HhoDatabase) = db.warrantyBlockDao() + @Provides fun soldToBlockDao(db: HhoDatabase) = db.soldToBlockDao() + @Provides fun purchasedFromBlockDao(db: HhoDatabase) = db.purchasedFromBlockDao() + @Provides fun itemIdentificationDao(db: HhoDatabase) = db.itemIdentificationDao() + @Provides fun itemCustomFieldDao(db: HhoDatabase) = db.itemCustomFieldDao() + @Provides fun stockAdjustmentDao(db: HhoDatabase) = db.stockAdjustmentDao() + @Provides fun locationDao(db: HhoDatabase) = db.locationDao() + @Provides fun labelDao(db: HhoDatabase) = db.labelDao() + @Provides fun itemLabelDao(db: HhoDatabase) = db.itemLabelDao() + @Provides fun attachmentDao(db: HhoDatabase) = db.attachmentDao() + @Provides fun syncStateDao(db: HhoDatabase) = db.syncStateDao() + @Provides fun outboxDao(db: HhoDatabase) = db.outboxDao() + @Provides fun receivingDao(db: HhoDatabase) = db.receivingDao() + @Provides fun photoQueueDao(db: HhoDatabase) = db.photoQueueDao() + @Provides fun conflictRecordDao(db: HhoDatabase) = db.conflictRecordDao() + @Provides fun syncRunStateDao(db: HhoDatabase) = db.syncRunStateDao() +} + +@Module +@TestInstallIn(components = [SingletonComponent::class], replaces = [NetworkModule::class]) +object TestNetworkModule { + @Provides + @Singleton + fun provideOkHttpClient(tripwire: NetworkTripwire): OkHttpClient = + OkHttpClient.Builder().addInterceptor(tripwire).build() + + @Provides + @Singleton + @ProbeHttpClient + fun provideProbeOkHttpClient(tripwire: NetworkTripwire): OkHttpClient = + OkHttpClient.Builder().addInterceptor(tripwire).build() +} + +@Module +@TestInstallIn(components = [SingletonComponent::class], replaces = [DataStoreModule::class]) +object TestDataStoreModule { + @Provides + @Singleton + fun provideSettingsDataStore(@ApplicationContext context: Context): DataStore = fresh(context) + + @Provides + @Singleton + @DeviceTokenDataStore + fun provideDeviceTokenDataStore(@ApplicationContext context: Context): DataStore = fresh(context) + + private fun fresh(context: Context): DataStore = + PreferenceDataStoreFactory.create( + produceFile = { File(context.cacheDir, "test-${UUID.randomUUID()}.preferences_pb") }, + ) +} diff --git a/android-app/app/src/androidTest/kotlin/dev/hho/android/ui/items/OfflineEditsInstrumentedTest.kt b/android-app/app/src/androidTest/kotlin/dev/hho/android/ui/items/OfflineEditsInstrumentedTest.kt new file mode 100644 index 0000000..418f270 --- /dev/null +++ b/android-app/app/src/androidTest/kotlin/dev/hho/android/ui/items/OfflineEditsInstrumentedTest.kt @@ -0,0 +1,160 @@ +package dev.hho.android.ui.items + +import android.view.ViewGroup +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.platform.ComposeView +import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.hasSetTextAction +import androidx.compose.ui.test.hasText +import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.onAllNodesWithText +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.performScrollTo +import androidx.compose.ui.test.performTextInput +import androidx.compose.ui.test.performTextReplacement +import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel +import androidx.test.ext.junit.runners.AndroidJUnit4 +import dagger.hilt.android.testing.HiltAndroidRule +import dagger.hilt.android.testing.HiltAndroidTest +import dev.hho.android.MainActivity +import dev.hho.android.data.room.HhoDatabase +import dev.hho.android.data.room.ItemEntity +import dev.hho.android.testing.AirplaneModeRule +import dev.hho.android.testing.NetworkTripwire +import dev.hho.android.ui.theme.HhoTheme +import kotlinx.coroutines.runBlocking +import org.junit.After +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.rules.RuleChain +import org.junit.runner.RunWith +import javax.inject.Inject + +@HiltAndroidTest +@RunWith(AndroidJUnit4::class) +class OfflineEditsInstrumentedTest { + + private val hiltRule = HiltAndroidRule(this) + private val airplane = AirplaneModeRule() + private val compose = createAndroidComposeRule() + + @get:Rule + val chain: RuleChain = RuleChain.outerRule(hiltRule).around(airplane).around(compose) + + @Inject lateinit var db: HhoDatabase + + @Inject lateinit var tripwire: NetworkTripwire + + private sealed interface Screen { + data object List : Screen + data class Detail(val id: String) : Screen + data class Form(val id: String?, val visit: Int) : Screen + } + + @Before + fun seed() { + hiltRule.inject() + runBlocking { + db.itemDao().upsertAll( + listOf(ItemEntity(DRILL, 1L, "Cordless Drill", "A cordless drill", null, 3L, "DR-1", 1L, 1L, 1L)), + ) + } + compose.activityRule.scenario.onActivity { activity -> + val host = activity.findViewById(android.R.id.content).getChildAt(0) as ComposeView + host.setContent { + HhoTheme(darkTheme = false) { + var screen by remember { mutableStateOf(Screen.List) } + var visits by remember { mutableIntStateOf(0) } + when (val s = screen) { + Screen.List -> ItemListScreen( + onItemClick = { screen = Screen.Detail(it) }, + onNewItem = { screen = Screen.Form(null, ++visits) }, + ) + is Screen.Detail -> ItemDetailScreen( + itemId = s.id, + onBack = { screen = Screen.List }, + onEdit = { screen = Screen.Form(s.id, ++visits) }, + ) + is Screen.Form -> ItemFormScreen( + itemId = s.id, + viewModel = hiltViewModel(key = "form-${s.visit}"), + onSaved = { screen = Screen.Detail(it) }, + onCancel = { screen = if (s.id == null) Screen.List else Screen.Detail(s.id) }, + ) + } + } + } + } + compose.waitForIdle() + } + + @After + fun assertNoNetworkAttempted() { + assertEquals("network requests were attempted while offline", emptyList(), tripwire.requests.toList()) + } + + @Test + fun editAdjustAndCreateWorkOfflineAndQueueDistinctMutations() { + assertTrue("device is not offline", !airplane.hasInternet()) + + compose.onNodeWithText("Cordless Drill").performClick() + awaitText("Quantity: 3") + compose.onNodeWithText("Edit").performClick() + awaitText("Edit item") + compose.onNode(hasSetTextAction() and hasText("Name (required)")).performTextReplacement("Impact Driver") + compose.onNodeWithText("Save").performClick() + awaitText("Impact Driver") + shown("Impact Driver") + + compose.onNodeWithText("Adjust quantity").performClick() + compose.onNodeWithText("+1").performClick() + compose.onNodeWithText("+1").performClick() + compose.onNodeWithText("Confirm").performClick() + awaitText("Quantity: 6") + shown("Quantity: 6") + + compose.onNodeWithText("Back").performClick() + compose.onNodeWithText("New item").performClick() + awaitText("Identifier (optional)") + compose.onNode(hasSetTextAction() and hasText("Name (required)")).performTextInput("Label Maker") + compose.onNodeWithText("barcode").performScrollTo().performClick() + compose.onNode(hasSetTextAction() and hasText("Identifier value")).performScrollTo().performTextInput("4006381333931") + compose.onNodeWithText("Create").performScrollTo().performClick() + awaitText("Label Maker") + shown("Label Maker") + shown("barcode: 4006381333931") + + val rows = runBlocking { db.outboxDao().getAllOrdered() } + assertEquals(4, rows.size) + assertEquals(listOf("item", "stock_adjustment", "item", "item_identification"), rows.map { it.entityType }) + assertEquals(DRILL, rows[0].entityId) + assertEquals("mutation_ids must be distinct", 4, rows.map { it.mutationId }.toSet().size) + assertEquals(listOf("upsert", "upsert", "upsert", "upsert"), rows.map { it.op }) + assertEquals("creates are based on version 0", listOf(0L, 0L, 0L), listOf(rows[1], rows[2], rows[3]).map { it.baseVersion }) + assertTrue(rows[0].fieldsJson.contains("Impact Driver")) + assertTrue(rows[1].fieldsJson.contains("\"delta\"")) + assertTrue(rows[3].fieldsJson.contains("4006381333931")) + assertTrue("no item mutation may carry quantity", rows.filter { it.entityType == "item" }.none { it.fieldsJson.contains("quantity") }) + } + + private fun awaitText(text: String) { + compose.waitUntil(WAIT_MILLIS) { compose.onAllNodesWithText(text).fetchSemanticsNodes().isNotEmpty() } + } + + private fun shown(text: String) { + compose.onNodeWithText(text).performScrollTo().assertIsDisplayed() + } + + private companion object { + const val DRILL = "item-1" + const val WAIT_MILLIS = 10_000L + } +} diff --git a/android-app/app/src/androidTest/kotlin/dev/hho/android/ui/items/OfflineItemsInstrumentedTest.kt b/android-app/app/src/androidTest/kotlin/dev/hho/android/ui/items/OfflineItemsInstrumentedTest.kt new file mode 100644 index 0000000..ee74107 --- /dev/null +++ b/android-app/app/src/androidTest/kotlin/dev/hho/android/ui/items/OfflineItemsInstrumentedTest.kt @@ -0,0 +1,291 @@ +package dev.hho.android.ui.items + +import android.view.ViewGroup +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.platform.ComposeView +import androidx.compose.ui.test.assertCountEquals +import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.performScrollTo +import androidx.compose.ui.test.hasSetTextAction +import androidx.compose.ui.test.hasText +import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.onAllNodesWithText +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.performTextInput +import androidx.test.ext.junit.runners.AndroidJUnit4 +import dagger.hilt.android.testing.HiltAndroidRule +import dagger.hilt.android.testing.HiltAndroidTest +import dev.hho.android.data.room.HhoDatabase +import dev.hho.android.data.room.ItemCustomFieldEntity +import dev.hho.android.data.room.ItemEntity +import dev.hho.android.data.room.ItemIdentificationEntity +import dev.hho.android.data.room.ItemLabelEntity +import dev.hho.android.data.room.LabelEntity +import dev.hho.android.data.room.LocationEntity +import dev.hho.android.data.room.PurchasedFromBlockEntity +import dev.hho.android.data.room.SoldToBlockEntity +import dev.hho.android.data.room.StockAdjustmentEntity +import dev.hho.android.data.room.WarrantyBlockEntity +import dev.hho.android.testing.AirplaneModeRule +import dev.hho.android.MainActivity +import dev.hho.android.testing.NetworkTripwire +import dev.hho.android.ui.theme.HhoTheme +import kotlinx.coroutines.runBlocking +import org.junit.After +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.rules.RuleChain +import org.junit.runner.RunWith +import java.math.BigDecimal +import java.time.LocalDate +import javax.inject.Inject + +@HiltAndroidTest +@RunWith(AndroidJUnit4::class) +class OfflineItemsInstrumentedTest { + + private val hiltRule = HiltAndroidRule(this) + private val airplane = AirplaneModeRule() + private val compose = createAndroidComposeRule() + + @get:Rule + val chain: RuleChain = RuleChain.outerRule(hiltRule).around(airplane).around(compose) + + @Inject lateinit var db: HhoDatabase + + @Inject lateinit var tripwire: NetworkTripwire + + @Before + fun seed() { + hiltRule.inject() + runBlocking { seedFixtures() } + compose.activityRule.scenario.onActivity { activity -> + val host = activity.findViewById(android.R.id.content).getChildAt(0) as ComposeView + host.setContent { + HhoTheme(darkTheme = false) { + var selected by rememberSaveable { mutableStateOf(null) } + val id = selected + if (id == null) { + ItemListScreen(onItemClick = { selected = it }) + } else { + ItemDetailScreen(itemId = id, onBack = { selected = null }) + } + } + } + } + compose.waitForIdle() + } + + @After + fun assertNoNetworkAttempted() { + assertEquals("network requests were attempted while offline", emptyList(), tripwire.requests.toList()) + } + + @Test + fun deviceIsActuallyOffline() { + assertFalse("airplane mode did not take the device offline", airplane.hasInternet()) + } + + @Test + fun listShowsAllSeededItems() { + compose.onNodeWithText("Cordless Drill").assertExists() + compose.onNodeWithText("Garden Hose").assertExists() + compose.onNodeWithText("Stepladder").assertExists() + compose.onNodeWithText("Qty 3 · DR-1").assertExists() + } + + @Test + fun searchByNameFilters() { + search("hose") + compose.onNodeWithText("Garden Hose").assertExists() + compose.onAllNodesWithText("Cordless Drill").assertCountEquals(0) + compose.onAllNodesWithText("Stepladder").assertCountEquals(0) + } + + @Test + fun searchByIdentifierValueFilters() { + search("SN-DRILL") + compose.onNodeWithText("Cordless Drill").assertExists() + compose.onAllNodesWithText("Garden Hose").assertCountEquals(0) + compose.onAllNodesWithText("Stepladder").assertCountEquals(0) + } + + @Test + fun searchWithNoMatchShowsNoMatchesState() { + search("zzz-nothing") + compose.onNodeWithText("No items, short codes, or scanned values match \"zzz-nothing\".").assertExists() + compose.onAllNodesWithText("Cordless Drill").assertCountEquals(0) + } + + @Test + fun detailShowsCoreFieldsLocationAndLabels() { + openDrill() + shown("A cordless drill") + shown("Quantity: 3") + shown("Short code: DR-1") + shown("Location: Garage") + shown("Labels: Power tools, Fragile") + } + + @Test + fun detailShowsWarrantySoldToAndPurchasedFromBlocks() { + openDrill() + shown("Warranty") + shown("Holder: Jane Doe") + shown("Provider: Acme Warranties") + shown("Starts: 2024-01-01") + shown("Expires: 2026-01-01") + shown("Sold to") + shown("Sale price (minor units): 5000") + shown("Buyer: Alex Buyer") + shown("Purchased from") + shown("Purchase price (minor units): 12000") + shown("Vendor: Hardware Store") + shown("Order reference: PO-42") + } + + @Test + fun detailShowsIdentifiersAndEveryCustomFieldType() { + openDrill() + shown("Identifiers") + shown("barcode: 0123456789012") + shown("serial: SN-DRILL-77") + shown("Custom fields") + shown("Colour: Red") + shown("Voltage: 18.5") + shown("Cordless: Yes") + shown("Bought: 2023-03-01") + } + + @Test + fun detailShowsStockHistory() { + openDrill() + shown("Stock history") + shown("+5 → 5 (initial)") + shown("-2 → 3 (loan)") + shown("Note: lent to a neighbour") + } + + @Test + fun richItemLastStockRowIsReachableByScrolling() { + compose.onNode(hasText("Server Rack")).performClick() + compose.waitUntil(WAIT_MILLIS) { + compose.onAllNodesWithText("Short code: RACK-9").fetchSemanticsNodes().isNotEmpty() + } + shown("Note: adjustment note 30") + shown("+1 → 30 (adjust 30)") + shown("rack-id-1: RACK-VAL-1") + } + + @Test + fun backFromDetailReturnsToList() { + openDrill() + compose.onNodeWithText("Back").performClick() + compose.onNodeWithText("Garden Hose").assertExists() + compose.onNodeWithText("Stepladder").assertExists() + } + + @Test + fun itemWithoutBlocksOmitsThem() { + compose.onNodeWithText("Stepladder").performClick() + compose.onNodeWithText("Back").assertExists() + compose.onAllNodesWithText("Warranty").assertCountEquals(0) + compose.onAllNodesWithText("Identifiers").assertCountEquals(0) + } + + private fun shown(text: String) { + compose.onNodeWithText(text).performScrollTo().assertIsDisplayed() + } + + private fun search(query: String) { + compose.onNode(hasSetTextAction()).performTextInput(query) + compose.waitForIdle() + } + + private fun openDrill() { + compose.onNode(hasText("Cordless Drill")).performClick() + compose.waitUntil(WAIT_MILLIS) { + compose.onAllNodesWithText("Location: Garage").fetchSemanticsNodes().isNotEmpty() + } + } + + private suspend fun seedFixtures() { + db.locationDao().upsert(LocationEntity("loc-1", 1L, "Garage", null, 1L, 1L, 1L)) + db.labelDao().upsert(LabelEntity("label-1", 1L, "Power tools", "#ffffff", 1L, 1L, 1L)) + db.labelDao().upsert(LabelEntity("label-2", 1L, "Fragile", "#ffffff", 1L, 1L, 1L)) + db.itemDao().upsertAll( + listOf( + item("item-1", "Cordless Drill", locationId = "loc-1", quantity = 3L, shortCode = "DR-1", description = "A cordless drill"), + item("item-2", "Garden Hose", quantity = 1L, shortCode = "GH-2", description = null), + item("item-4", "Server Rack", quantity = 30L, shortCode = "RACK-9", description = null), + item("item-3", "Stepladder", quantity = null, shortCode = null, description = null), + ), + ) + db.itemLabelDao().upsert(ItemLabelEntity("il-1", 1L, "item-1", "label-1")) + db.itemLabelDao().upsert(ItemLabelEntity("il-2", 1L, "item-1", "label-2")) + db.warrantyBlockDao().upsert( + WarrantyBlockEntity( + "w-1", 1L, "item-1", false, "Jane Doe", "Acme Warranties", + LocalDate.of(2024, 1, 1), LocalDate.of(2026, 1, 1), "Keep receipt", 1L, 1L, 1L, + ), + ) + db.soldToBlockDao().upsert( + SoldToBlockEntity("s-1", 1L, "item-1", 5_000L, "Alex Buyer", LocalDate.of(2024, 6, 1), "Yard sale", 1L, 1L, 1L), + ) + db.purchasedFromBlockDao().upsert( + PurchasedFromBlockEntity( + "p-1", 1L, "item-1", 12_000L, "Hardware Store", LocalDate.of(2023, 3, 1), "PO-42", "On sale", 1L, 1L, 1L, + ), + ) + db.itemIdentificationDao().upsert(identifier("id-1", "item-1", "barcode", "0123456789012")) + db.itemIdentificationDao().upsert(identifier("id-2", "item-1", "serial", "SN-DRILL-77")) + db.itemIdentificationDao().upsert(identifier("id-3", "item-2", "barcode", "9998887776665")) + db.itemCustomFieldDao().upsert(customField("cf-1", "Colour", "text", textValue = "Red")) + db.itemCustomFieldDao().upsert(customField("cf-2", "Voltage", "number", numberValue = BigDecimal("18.5"))) + db.itemCustomFieldDao().upsert(customField("cf-3", "Cordless", "boolean", boolValue = true)) + db.itemCustomFieldDao().upsert(customField("cf-4", "Bought", "date", dateValue = LocalDate.of(2023, 3, 1))) + for (n in 1..RICH_ROWS) { + db.itemIdentificationDao().upsert(identifier("rid-$n", "item-4", "rack-id-$n", "RACK-VAL-$n")) + db.itemCustomFieldDao().upsert(customField("rcf-$n", "Field $n", "text", textValue = "Value $n", itemId = "item-4")) + db.stockAdjustmentDao().upsert( + StockAdjustmentEntity("rsa-$n", 1L, "item-4", 1L, n.toLong(), "adjust $n", "adjustment note $n", n.toLong(), n.toLong(), 1L), + ) + } + db.stockAdjustmentDao().upsert(stock("sa-1", 5L, 5L, "initial", null, 1L)) + db.stockAdjustmentDao().upsert(stock("sa-2", -2L, 3L, "loan", "lent to a neighbour", 2L)) + } + + private fun item(id: String, name: String, locationId: String? = null, quantity: Long?, shortCode: String?, description: String?) = + ItemEntity(id, 1L, name, description, locationId, quantity, shortCode, 1L, 1L, 1L) + + private fun identifier(id: String, itemId: String, kind: String, value: String) = + ItemIdentificationEntity(id, 1L, itemId, kind, value, 1L, 1L, 1L) + + private fun customField( + id: String, + name: String, + type: String, + textValue: String? = null, + numberValue: BigDecimal? = null, + boolValue: Boolean? = null, + dateValue: LocalDate? = null, + itemId: String = "item-1", + ) = ItemCustomFieldEntity( + id, 1L, itemId, name, type, null, textValue, numberValue, boolValue, dateValue, 1L, 1L, 1L, + ) + + private fun stock(id: String, delta: Long, resulting: Long, reason: String?, note: String?, at: Long) = + StockAdjustmentEntity(id, 1L, "item-1", delta, resulting, reason, note, at, at, 1L) + + private companion object { + const val WAIT_MILLIS = 10_000L + const val RICH_ROWS = 30 + } +} diff --git a/android-app/app/src/foss/kotlin/dev/hho/android/di/ScannerModule.kt b/android-app/app/src/foss/kotlin/dev/hho/android/di/ScannerModule.kt new file mode 100644 index 0000000..38c7ab7 --- /dev/null +++ b/android-app/app/src/foss/kotlin/dev/hho/android/di/ScannerModule.kt @@ -0,0 +1,18 @@ +package dev.hho.android.di + +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import dev.hho.android.data.scanner.BarcodeScanner +import dev.hho.android.data.scanner.ZxingBarcodeScanner +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +abstract class ScannerModule { + + @Binds + @Singleton + abstract fun bindBarcodeScanner(impl: ZxingBarcodeScanner): BarcodeScanner +} diff --git a/android-app/app/src/gms/kotlin/dev/hho/android/data/scanner/MlKitBarcodeScanner.kt b/android-app/app/src/gms/kotlin/dev/hho/android/data/scanner/MlKitBarcodeScanner.kt new file mode 100644 index 0000000..c0cac02 --- /dev/null +++ b/android-app/app/src/gms/kotlin/dev/hho/android/data/scanner/MlKitBarcodeScanner.kt @@ -0,0 +1,57 @@ +package dev.hho.android.data.scanner + +import androidx.camera.core.ImageProxy +import com.google.android.gms.tasks.Task +import com.google.mlkit.vision.barcode.BarcodeScanning +import com.google.mlkit.vision.barcode.common.Barcode +import com.google.mlkit.vision.common.InputImage +import kotlinx.coroutines.suspendCancellableCoroutine +import javax.inject.Inject +import kotlin.coroutines.resume +import kotlin.coroutines.resumeWithException + +class MlKitBarcodeScanner + @Inject + constructor() : BarcodeScanner { + + private val client: com.google.mlkit.vision.barcode.BarcodeScanner by lazy { BarcodeScanning.getClient() } + + override suspend fun scan(imageProxy: ImageProxy): List { + val mediaImage = imageProxy.image ?: return emptyList() + val inputImage = InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees) + val barcodes = client.process(inputImage).await() + return barcodes.mapNotNull { mapMlKitBarcode(it.rawValue, it.format) } + } + + override fun close() { + client.close() + } + } + +internal fun mapMlKitBarcode(rawValue: String?, mlKitFormat: Int): DecodedBarcode? = + rawValue?.let { DecodedBarcode(it, mapMlKitFormat(mlKitFormat)) } + +internal fun mapMlKitFormat(mlKitFormat: Int): BarcodeFormat = + when (mlKitFormat) { + Barcode.FORMAT_QR_CODE -> BarcodeFormat.QR_CODE + Barcode.FORMAT_AZTEC -> BarcodeFormat.AZTEC + Barcode.FORMAT_DATA_MATRIX -> BarcodeFormat.DATA_MATRIX + Barcode.FORMAT_PDF417 -> BarcodeFormat.PDF_417 + Barcode.FORMAT_CODE_39 -> BarcodeFormat.CODE_39 + Barcode.FORMAT_CODE_93 -> BarcodeFormat.CODE_93 + Barcode.FORMAT_CODE_128 -> BarcodeFormat.CODE_128 + Barcode.FORMAT_CODABAR -> BarcodeFormat.CODABAR + Barcode.FORMAT_ITF -> BarcodeFormat.ITF + Barcode.FORMAT_EAN_8 -> BarcodeFormat.EAN_8 + Barcode.FORMAT_EAN_13 -> BarcodeFormat.EAN_13 + Barcode.FORMAT_UPC_A -> BarcodeFormat.UPC_A + Barcode.FORMAT_UPC_E -> BarcodeFormat.UPC_E + else -> BarcodeFormat.UNKNOWN + } + +private suspend fun Task.await(): T = + suspendCancellableCoroutine { continuation -> + addOnSuccessListener { continuation.resume(it) } + addOnFailureListener { continuation.resumeWithException(it) } + addOnCanceledListener { continuation.cancel() } + } diff --git a/android-app/app/src/gms/kotlin/dev/hho/android/di/ScannerModule.kt b/android-app/app/src/gms/kotlin/dev/hho/android/di/ScannerModule.kt new file mode 100644 index 0000000..2268220 --- /dev/null +++ b/android-app/app/src/gms/kotlin/dev/hho/android/di/ScannerModule.kt @@ -0,0 +1,18 @@ +package dev.hho.android.di + +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import dev.hho.android.data.scanner.BarcodeScanner +import dev.hho.android.data.scanner.MlKitBarcodeScanner +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +abstract class ScannerModule { + + @Binds + @Singleton + abstract fun bindBarcodeScanner(impl: MlKitBarcodeScanner): BarcodeScanner +} diff --git a/android-app/app/src/main/AndroidManifest.xml b/android-app/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..192f07f --- /dev/null +++ b/android-app/app/src/main/AndroidManifest.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/HhoApplication.kt b/android-app/app/src/main/kotlin/dev/hho/android/HhoApplication.kt new file mode 100644 index 0000000..9100bd7 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/HhoApplication.kt @@ -0,0 +1,26 @@ +package dev.hho.android + +import android.app.Application +import androidx.hilt.work.HiltWorkerFactory +import androidx.work.Configuration +import dagger.hilt.android.HiltAndroidApp +import dev.hho.android.data.sync.SyncScheduler +import javax.inject.Inject + +@HiltAndroidApp +class HhoApplication : Application(), Configuration.Provider { + + @Inject + lateinit var hiltWorkerFactory: HiltWorkerFactory + + @Inject + lateinit var syncScheduler: SyncScheduler + + override val workManagerConfiguration: Configuration + get() = Configuration.Builder().setWorkerFactory(hiltWorkerFactory).build() + + override fun onCreate() { + super.onCreate() + syncScheduler.schedulePeriodic() + } +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/MainActivity.kt b/android-app/app/src/main/kotlin/dev/hho/android/MainActivity.kt new file mode 100644 index 0000000..51fd89d --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/MainActivity.kt @@ -0,0 +1,47 @@ +package dev.hho.android + +import android.content.Intent +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.activity.enableEdgeToEdge +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import dagger.hilt.android.AndroidEntryPoint +import dev.hho.android.ui.HhoApp +import dev.hho.android.ui.deeplink.ItemDeepLink +import dev.hho.android.ui.deeplink.parseItemDeepLink +import dev.hho.android.ui.theme.HhoTheme + +@AndroidEntryPoint +class MainActivity : ComponentActivity() { + + private var pendingDeepLink by mutableStateOf(null) + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + enableEdgeToEdge() + if (savedInstanceState == null) captureDeepLink(intent) + setContent { + HhoTheme { + HhoApp( + pendingDeepLink = pendingDeepLink, + onDeepLinkHandled = { pendingDeepLink = null }, + ) + } + } + } + + override fun onNewIntent(intent: Intent) { + super.onNewIntent(intent) + setIntent(intent) + captureDeepLink(intent) + } + + private fun captureDeepLink(intent: Intent?) { + if (intent?.action == Intent.ACTION_VIEW) { + parseItemDeepLink(intent.dataString)?.let { pendingDeepLink = it } + } + } +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/ApiError.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/ApiError.kt new file mode 100644 index 0000000..85bedda --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/ApiError.kt @@ -0,0 +1,34 @@ +package dev.hho.android.data.apiclient + +sealed class ApiError(message: String, cause: Throwable? = null) : Exception(message, cause) { + class NoInstanceConfigured(cause: Throwable) : + ApiError("No self-hosted instance is configured yet", cause) + + class Unauthorized(cause: Throwable? = null) : ApiError("Not authenticated", cause) + + class NotFound(cause: Throwable? = null) : ApiError("Not found", cause) + + class Conflict(val detail: String?, cause: Throwable? = null) : + ApiError("Conflict" + (detail?.let { ": $it" } ?: ""), cause) + + open class Validation(val status: Int, val detail: String?, cause: Throwable? = null) : + ApiError("Client error $status" + (detail?.let { ": $it" } ?: ""), cause) + + class PayloadTooLarge(detail: String?, cause: Throwable? = null) : Validation(413, detail, cause) + + class UpgradeRequired(val minimumVersion: String, val detail: String?, cause: Throwable? = null) : + ApiError( + "Client too old — server requires at least $minimumVersion" + (detail?.let { ": $it" } ?: ""), + cause, + ) + + class Server(val status: Int, val detail: String?, cause: Throwable? = null) : + ApiError("Server error $status" + (detail?.let { ": $it" } ?: ""), cause) + + class Network(cause: Throwable) : ApiError("Network failure", cause) + + class UnexpectedPayload(val detail: String, cause: Throwable? = null) : + ApiError("Unexpected response payload: $detail", cause) + + class Unknown(cause: Throwable) : ApiError(cause.message ?: "Unexpected error", cause) +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/AttachmentInfo.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/AttachmentInfo.kt new file mode 100644 index 0000000..0aa25df --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/AttachmentInfo.kt @@ -0,0 +1,46 @@ +package dev.hho.android.data.apiclient + +import dev.hho.android.data.apiclient.generated.apis.AttachmentsApi +import dev.hho.android.data.apiclient.generated.models.Attachment + +enum class AttachmentCategory(val wire: String) { + IMAGE("image"), + MANUAL("manual"), + WARRANTY("warranty"), + RECEIPT("receipt"), + GENERAL("general"), +} + +data class AttachmentInfo( + val id: String, + val itemId: String, + val category: String, + val originalFilename: String, + val contentType: String, + val sizeBytes: Long, + val sha256: String, + val createdAt: Long, + val hasThumbnail: Boolean, +) + +internal fun AttachmentCategory.toGenerated(): AttachmentsApi.CategoryUploadItemAttachment = + when (this) { + AttachmentCategory.IMAGE -> AttachmentsApi.CategoryUploadItemAttachment.Image + AttachmentCategory.MANUAL -> AttachmentsApi.CategoryUploadItemAttachment.Manual + AttachmentCategory.WARRANTY -> AttachmentsApi.CategoryUploadItemAttachment.Warranty + AttachmentCategory.RECEIPT -> AttachmentsApi.CategoryUploadItemAttachment.Receipt + AttachmentCategory.GENERAL -> AttachmentsApi.CategoryUploadItemAttachment.General + } + +internal fun Attachment.toInfo(): AttachmentInfo = + AttachmentInfo( + id = id, + itemId = itemId, + category = category.value, + originalFilename = originalFilename, + contentType = contentType, + sizeBytes = sizeBytes, + sha256 = sha256, + createdAt = createdAt, + hasThumbnail = hasThumbnail, + ) diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/HhoApiClient.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/HhoApiClient.kt new file mode 100644 index 0000000..c2d27eb --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/HhoApiClient.kt @@ -0,0 +1,328 @@ +package dev.hho.android.data.apiclient + +import dev.hho.android.data.apiclient.generated.apis.AttachmentsApi +import dev.hho.android.data.apiclient.generated.apis.AuthApi +import dev.hho.android.data.apiclient.generated.apis.StatusApi +import dev.hho.android.data.apiclient.generated.apis.SyncApi +import dev.hho.android.data.apiclient.generated.infrastructure.ApiResponse +import dev.hho.android.data.apiclient.generated.infrastructure.ClientError +import dev.hho.android.data.apiclient.generated.infrastructure.ClientException +import dev.hho.android.data.apiclient.generated.infrastructure.ResponseType +import dev.hho.android.data.apiclient.generated.infrastructure.Serializer +import dev.hho.android.data.apiclient.generated.infrastructure.ServerError +import dev.hho.android.data.apiclient.generated.infrastructure.ServerException +import dev.hho.android.data.apiclient.generated.infrastructure.Success +import dev.hho.android.data.apiclient.generated.infrastructure.Response as GeneratedResponse +import dev.hho.android.data.apiclient.generated.models.DeviceTokenIssueRequest +import dev.hho.android.data.apiclient.generated.models.DeviceTokenIssueResponse +import dev.hho.android.data.apiclient.generated.models.LoginRequest +import dev.hho.android.data.apiclient.generated.models.LoginResponse +import dev.hho.android.data.apiclient.generated.models.Problem +import dev.hho.android.data.apiclient.generated.models.StatusResponse +import dev.hho.android.data.apiclient.generated.models.SyncConflictLogResponse +import dev.hho.android.data.apiclient.generated.models.SyncPullRequest +import dev.hho.android.data.apiclient.generated.models.SyncPushResponse +import dev.hho.android.data.apiclient.generated.models.UpgradeRequiredProblem +import dev.hho.android.data.network.AuthHeaderInterceptor +import dev.hho.android.data.network.NoInstanceUrlConfiguredException +import dev.hho.android.di.ProbeHttpClient +import kotlinx.coroutines.CancellationException +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import kotlinx.serialization.SerializationException +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.buildJsonObject +import kotlinx.serialization.json.JsonArray +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.JsonPrimitive +import kotlinx.serialization.json.put +import okhttp3.HttpUrl +import okhttp3.HttpUrl.Companion.toHttpUrl +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.RequestBody.Companion.toRequestBody +import java.io.File +import java.io.IOException +import javax.inject.Inject +import javax.inject.Singleton + +private const val PLACEHOLDER_BASE_URL = "http://placeholder.invalid/api/v1" + +private val JSON_MEDIA_TYPE = "application/json; charset=utf-8".toMediaType() + +private const val SESSION_COOKIE_NAME = "hho_session" + +data class LoginOutcome( + val response: LoginResponse, + val sessionCookie: String, +) + +@Singleton +class HhoApiClient + @Inject + constructor( + private val httpClient: OkHttpClient, + @ProbeHttpClient private val probeHttpClient: OkHttpClient, + ) { + private val statusApi = StatusApi(PLACEHOLDER_BASE_URL, httpClient) + private val authApi = AuthApi(PLACEHOLDER_BASE_URL, httpClient) + private val attachmentsApi = AttachmentsApi(PLACEHOLDER_BASE_URL, httpClient) + private val syncApi = SyncApi(PLACEHOLDER_BASE_URL, httpClient) + + suspend fun getStatus(): Result = apiCall { statusApi.getStatus() } + + suspend fun probeInstance(candidateBaseUrl: HttpUrl): Result = + apiCall { + val probeBasePath = candidateBaseUrl.newBuilder().addPathSegments("api/v1").build().toString() + StatusApi(probeBasePath, probeHttpClient).getStatus() + } + + suspend fun login( + username: String, + password: String, + ): Result = + apiCall { + val httpResponse = authApi.loginWithHttpInfo(LoginRequest(username = username, password = password), null) + val body = httpResponse.bodyOrThrow() + val sessionCookie = httpResponse.headers.sessionCookieValue() + ?: throw MissingSessionCookieException() + LoginOutcome(response = body, sessionCookie = sessionCookie) + } + + suspend fun issueDeviceToken( + deviceLabel: String, + sessionCookie: String, + ): Result = + apiCall { + val cookieScopedClient = + httpClient.newBuilder() + .apply { interceptors().removeAll { it is AuthHeaderInterceptor } } + .addInterceptor { chain -> + chain.proceed(chain.request().newBuilder().header("Cookie", sessionCookie).build()) + } + .build() + AuthApi(PLACEHOLDER_BASE_URL, cookieScopedClient) + .issueDeviceToken(DeviceTokenIssueRequest(deviceLabel = deviceLabel)) + } + + suspend fun downloadAttachment( + itemId: String, + attachmentId: String, + ): Result = + apiCall { + attachmentsApi.downloadItemAttachment(itemID = itemId, attachmentID = attachmentId) + } + + suspend fun uploadAttachment( + itemId: String, + category: AttachmentCategory, + file: File, + ): Result = + apiCall { + attachmentsApi + .uploadItemAttachment(itemID = itemId, category = category.toGenerated(), file = file) + .toInfo() + } + + suspend fun listAttachments(itemId: String): Result> = + apiCall { + attachmentsApi.listItemAttachments(itemID = itemId).attachments.map { it.toInfo() } + } + + suspend fun syncPull( + deviceId: String, + since: Long, + limit: Int, + ): Result = + apiCall { + val requestJson = + Serializer.kotlinxSerializationJson.encodeToString( + SyncPullRequest(deviceId = deviceId, since = since, limit = limit), + ) + val request = + Request.Builder() + .url(PLACEHOLDER_BASE_URL.toHttpUrl().newBuilder().addPathSegments("sync/pull").build()) + .post(requestJson.toRequestBody(JSON_MEDIA_TYPE)) + .header("Accept", "application/json, application/problem+json") + .build() + + httpClient.newCall(request).execute().use { response -> + val bodyString = response.body?.string().orEmpty() + if (!response.isSuccessful) { + throw httpStatusToApiError(response.code, bodyString) + } + SyncChangeDecoder.decodePullResponse( + Serializer.kotlinxSerializationJson.parseToJsonElement(bodyString), + ) + } + } + + suspend fun syncPush( + deviceId: String, + mutations: List, + ): Result = + apiCall { + val requestJson = encodePushRequest(deviceId, mutations) + val request = + Request.Builder() + .url(PLACEHOLDER_BASE_URL.toHttpUrl().newBuilder().addPathSegments("sync/push").build()) + .post(requestJson.toRequestBody(JSON_MEDIA_TYPE)) + .header("Accept", "application/json, application/problem+json") + .build() + + httpClient.newCall(request).execute().use { response -> + val bodyString = response.body?.string().orEmpty() + if (response.code == 400) { + val detail = + runCatching { Serializer.kotlinxSerializationJson.decodeFromString(bodyString).detail }.getOrNull() + if (detail != null && detail.startsWith(SyncPushDetailParser.STRUCTURAL_PREFIX)) { + return@use SyncPushDetailParser.parse(detail) + } + } + if (!response.isSuccessful) { + throw httpStatusToApiError(response.code, bodyString) + } + val decoded = Serializer.kotlinxSerializationJson.decodeFromString(bodyString) + SyncPushOutcome.Success(decoded.applied, decoded.skipped, decoded.conflicts, decoded.newWatermark) + } + } + + suspend fun getConflicts( + after: String? = null, + limit: Int = 50, + ): Result = apiCall { syncApi.listSyncConflicts(limit = limit, after = after) } + + private suspend fun apiCall(block: () -> T): Result = + withContext(Dispatchers.IO) { + try { + Result.success(block()) + } catch (e: CancellationException) { + throw e + } catch (e: Throwable) { + Result.failure(e.toApiError()) + } + } + } + +private fun encodePushRequest( + deviceId: String, + mutations: List, +): String { + val root: JsonObject = + buildJsonObject { + put("device_id", deviceId) + put( + "mutations", + JsonArray( + mutations.map { m -> + buildJsonObject { + put("mutation_id", m.mutationId) + put("entity_type", m.entityType) + put("entity_id", m.entityId) + put("base_version", m.baseVersion) + put("fields", JsonObject(m.fields)) + m.op?.let { put("op", JsonPrimitive(it)) } + } + }, + ), + ) + } + return root.toString() +} + +private fun Throwable.toApiError(): ApiError = + when (this) { + is ApiError -> this + is NoInstanceUrlConfiguredException -> ApiError.NoInstanceConfigured(this) + is ClientException -> toApiError() + is ServerException -> ApiError.Server(statusCode, problemDetailOf(response), this) + is MissingSessionCookieException -> ApiError.UnexpectedPayload(message ?: toString(), this) + is UnknownSyncEntityTypeException -> ApiError.UnexpectedPayload(message ?: toString(), this) + is MalformedSyncPullResponseException -> ApiError.UnexpectedPayload(message ?: toString(), this) + is SerializationException -> ApiError.UnexpectedPayload(message ?: "malformed response body", this) + is UnsupportedOperationException -> ApiError.UnexpectedPayload(message ?: "unsupported response content type", this) + is IOException -> ApiError.Network(this) + else -> ApiError.Unknown(this) + } + +private fun ClientException.toApiError(): ApiError { + if (statusCode == 426) { + upgradeRequiredProblemOf(response)?.let { return ApiError.UpgradeRequired(it.minimumVersion, it.detail, this) } + } + val detail = problemDetailOf(response) + return when (statusCode) { + 401 -> ApiError.Unauthorized(this) + 404 -> ApiError.NotFound(this) + 413 -> ApiError.PayloadTooLarge(detail, this) + 409 -> ApiError.Conflict(detail, this) + else -> ApiError.Validation(statusCode, detail, this) + } +} + +private fun httpStatusToApiError( + statusCode: Int, + rawBody: String, +): ApiError { + if (statusCode == 426) { + runCatching { Serializer.kotlinxSerializationJson.decodeFromString(rawBody) } + .getOrNull() + ?.let { return ApiError.UpgradeRequired(it.minimumVersion, it.detail) } + } + val detail = runCatching { Serializer.kotlinxSerializationJson.decodeFromString(rawBody).detail }.getOrNull() + return when (statusCode) { + 401 -> ApiError.Unauthorized() + 404 -> ApiError.NotFound() + 413 -> ApiError.PayloadTooLarge(detail) + 409 -> ApiError.Conflict(detail) + in 500..599 -> ApiError.Server(statusCode, detail) + else -> ApiError.Validation(statusCode, detail) + } +} + +private fun upgradeRequiredProblemOf(response: GeneratedResponse?): UpgradeRequiredProblem? { + val rawBody = + when (response) { + is ClientError<*> -> response.body as? String + is ServerError<*> -> response.body as? String + else -> null + } ?: return null + return runCatching { Serializer.kotlinxSerializationJson.decodeFromString(rawBody) }.getOrNull() +} + +private fun problemDetailOf(response: GeneratedResponse?): String? { + val rawBody = + when (response) { + is ClientError<*> -> response.body as? String + is ServerError<*> -> response.body as? String + else -> null + } ?: return null + return runCatching { Serializer.kotlinxSerializationJson.decodeFromString(rawBody).detail }.getOrNull() +} + +@Suppress("UNCHECKED_CAST") +private fun ApiResponse.bodyOrThrow(): T = + when (responseType) { + ResponseType.Success -> (this as Success<*>).data as T + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val error = this as ClientError<*> + throw ClientException("Client error : ${error.statusCode} ${error.message.orEmpty()}", error.statusCode, this) + } + ResponseType.ServerError -> { + val error = this as ServerError<*> + throw ServerException("Server error : ${error.statusCode} ${error.message.orEmpty()} ${error.body}", error.statusCode, this) + } + } + +private fun Map>.sessionCookieValue(): String? = + entries + .firstOrNull { it.key.equals("Set-Cookie", ignoreCase = true) } + ?.value + ?.map { it.substringBefore(';') } + ?.firstOrNull { it.startsWith("$SESSION_COOKIE_NAME=") } + +private class MissingSessionCookieException : + Exception("Login succeeded but the response carried no $SESSION_COOKIE_NAME session cookie") diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/SyncChange.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/SyncChange.kt new file mode 100644 index 0000000..af6622a --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/SyncChange.kt @@ -0,0 +1,213 @@ +package dev.hho.android.data.apiclient + +import dev.hho.android.data.apiclient.generated.infrastructure.Serializer +import dev.hho.android.data.apiclient.generated.models.Attachment +import dev.hho.android.data.apiclient.generated.models.Identification +import dev.hho.android.data.apiclient.generated.models.Item +import dev.hho.android.data.apiclient.generated.models.ItemCustomField +import dev.hho.android.data.apiclient.generated.models.ItemLabelAssignment +import dev.hho.android.data.apiclient.generated.models.Label +import dev.hho.android.data.apiclient.generated.models.Location +import dev.hho.android.data.apiclient.generated.models.PurchaseBlock +import dev.hho.android.data.apiclient.generated.models.SaleBlock +import dev.hho.android.data.apiclient.generated.models.StockAdjustment +import dev.hho.android.data.apiclient.generated.models.SyncChangeEntryAttachment +import dev.hho.android.data.apiclient.generated.models.SyncChangeEntryItem +import dev.hho.android.data.apiclient.generated.models.SyncChangeEntryItemCustomField +import dev.hho.android.data.apiclient.generated.models.SyncChangeEntryItemIdentification +import dev.hho.android.data.apiclient.generated.models.SyncChangeEntryItemLabel +import dev.hho.android.data.apiclient.generated.models.SyncChangeEntryLabel +import dev.hho.android.data.apiclient.generated.models.SyncChangeEntryLocation +import dev.hho.android.data.apiclient.generated.models.SyncChangeEntryPurchasedFromBlock +import dev.hho.android.data.apiclient.generated.models.SyncChangeEntrySoldToBlock +import dev.hho.android.data.apiclient.generated.models.SyncChangeEntryStockAdjustment +import dev.hho.android.data.apiclient.generated.models.SyncChangeEntryWarrantyBlock +import dev.hho.android.data.apiclient.generated.models.SyncTombstoneEntry +import dev.hho.android.data.apiclient.generated.models.WarrantyBlock +import kotlinx.serialization.SerializationException +import kotlinx.serialization.json.JsonArray +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.booleanOrNull +import kotlinx.serialization.json.contentOrNull +import kotlinx.serialization.json.decodeFromJsonElement +import kotlinx.serialization.json.jsonPrimitive +import kotlinx.serialization.json.longOrNull + +sealed interface SyncChange { + val id: String + + val groupChangeSeq: Long + + data class ItemChange(override val id: String, override val groupChangeSeq: Long, val data: Item) : SyncChange + + data class WarrantyBlockChange( + override val id: String, + override val groupChangeSeq: Long, + val data: WarrantyBlock, + ) : SyncChange + + data class SoldToBlockChange( + override val id: String, + override val groupChangeSeq: Long, + val data: SaleBlock, + ) : SyncChange + + data class PurchasedFromBlockChange( + override val id: String, + override val groupChangeSeq: Long, + val data: PurchaseBlock, + ) : SyncChange + + data class ItemIdentificationChange( + override val id: String, + override val groupChangeSeq: Long, + val data: Identification, + ) : SyncChange + + data class ItemCustomFieldChange( + override val id: String, + override val groupChangeSeq: Long, + val data: ItemCustomField, + ) : SyncChange + + data class StockAdjustmentChange( + override val id: String, + override val groupChangeSeq: Long, + val data: StockAdjustment, + ) : SyncChange + + data class LocationChange( + override val id: String, + override val groupChangeSeq: Long, + val data: Location, + ) : SyncChange + + data class LabelChange(override val id: String, override val groupChangeSeq: Long, val data: Label) : SyncChange + + data class ItemLabelChange( + override val id: String, + override val groupChangeSeq: Long, + val data: ItemLabelAssignment, + ) : SyncChange + + data class AttachmentChange( + override val id: String, + override val groupChangeSeq: Long, + val data: Attachment, + ) : SyncChange +} + +sealed interface SyncPullOutcome { + data class Page( + val changes: List, + val tombstones: List, + val nextWatermark: Long, + val hasMore: Boolean, + ) : SyncPullOutcome + + data object CursorTooOld : SyncPullOutcome +} + +class UnknownSyncEntityTypeException(val rawEntityType: String?) : + IllegalStateException("Unknown sync entity_type: $rawEntityType — client/server drift (A7 closed set)") + +class MalformedSyncPullResponseException(detail: String, cause: Throwable? = null) : + IllegalStateException("Malformed /sync/pull response: $detail", cause) + +internal object SyncChangeDecoder { + + private val json = Serializer.kotlinxSerializationJson + + fun decodePullResponse(root: JsonElement): SyncPullOutcome { + val obj = + root as? JsonObject + ?: throw MalformedSyncPullResponseException("expected a JSON object, got $root") + + if (obj["cursor_too_old"]?.jsonPrimitive?.booleanOrNull == true) { + return SyncPullOutcome.CursorTooOld + } + + try { + val changesJson = + obj["changes"] as? JsonArray + ?: throw MalformedSyncPullResponseException("missing or non-array 'changes'") + val tombstonesJson = + obj["tombstones"] as? JsonArray + ?: throw MalformedSyncPullResponseException("missing or non-array 'tombstones'") + val nextWatermark = + obj["next_watermark"]?.jsonPrimitive?.longOrNull + ?: throw MalformedSyncPullResponseException("missing or non-numeric 'next_watermark'") + val hasMore = + obj["has_more"]?.jsonPrimitive?.booleanOrNull + ?: throw MalformedSyncPullResponseException("missing or non-boolean 'has_more'") + + return SyncPullOutcome.Page( + changes = changesJson.map { decodeChange(it) }, + tombstones = tombstonesJson.map { json.decodeFromJsonElement(it) }, + nextWatermark = nextWatermark, + hasMore = hasMore, + ) + } catch (e: SerializationException) { + throw MalformedSyncPullResponseException(e.message ?: "decode failure", e) + } + } + + fun decodeChange(element: JsonElement): SyncChange { + val entityType = + (element as? JsonObject)?.get("entity_type")?.jsonPrimitive?.contentOrNull + ?: throw UnknownSyncEntityTypeException(rawEntityType = null) + + return try { + when (entityType) { + "item" -> + json.decodeFromJsonElement(element).let { + SyncChange.ItemChange(it.id, it.groupChangeSeq, it.data) + } + "warranty_block" -> + json.decodeFromJsonElement(element).let { + SyncChange.WarrantyBlockChange(it.id, it.groupChangeSeq, it.data) + } + "sold_to_block" -> + json.decodeFromJsonElement(element).let { + SyncChange.SoldToBlockChange(it.id, it.groupChangeSeq, it.data) + } + "purchased_from_block" -> + json.decodeFromJsonElement(element).let { + SyncChange.PurchasedFromBlockChange(it.id, it.groupChangeSeq, it.data) + } + "item_identification" -> + json.decodeFromJsonElement(element).let { + SyncChange.ItemIdentificationChange(it.id, it.groupChangeSeq, it.data) + } + "item_custom_field" -> + json.decodeFromJsonElement(element).let { + SyncChange.ItemCustomFieldChange(it.id, it.groupChangeSeq, it.data) + } + "stock_adjustment" -> + json.decodeFromJsonElement(element).let { + SyncChange.StockAdjustmentChange(it.id, it.groupChangeSeq, it.data) + } + "location" -> + json.decodeFromJsonElement(element).let { + SyncChange.LocationChange(it.id, it.groupChangeSeq, it.data) + } + "label" -> + json.decodeFromJsonElement(element).let { + SyncChange.LabelChange(it.id, it.groupChangeSeq, it.data) + } + "item_label" -> + json.decodeFromJsonElement(element).let { + SyncChange.ItemLabelChange(it.id, it.groupChangeSeq, it.data) + } + "attachment" -> + json.decodeFromJsonElement(element).let { + SyncChange.AttachmentChange(it.id, it.groupChangeSeq, it.data) + } + else -> throw UnknownSyncEntityTypeException(entityType) + } + } catch (e: SerializationException) { + throw MalformedSyncPullResponseException("entity_type=$entityType: ${e.message}", e) + } + } +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/SyncPushOutcome.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/SyncPushOutcome.kt new file mode 100644 index 0000000..4196166 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/SyncPushOutcome.kt @@ -0,0 +1,47 @@ +package dev.hho.android.data.apiclient + +import dev.hho.android.data.apiclient.generated.models.SyncAppliedEntry +import dev.hho.android.data.apiclient.generated.models.SyncConflictEntry +import dev.hho.android.data.apiclient.generated.models.SyncSkippedEntry +import kotlinx.serialization.json.JsonElement + +data class PushMutation( + val mutationId: String, + val entityType: String, + val entityId: String, + val baseVersion: Long, + val fields: Map, + val op: String? = null, +) + +sealed interface SyncPushOutcome { + data class Success( + val applied: List, + val skipped: List, + val conflicts: List, + val newWatermark: Long, + ) : SyncPushOutcome + + data class StructuralRejection( + val index: Int?, + val mutationId: String?, + val detail: String, + ) : SyncPushOutcome +} + +internal object SyncPushDetailParser { + const val STRUCTURAL_PREFIX = "mutations[" + + private val pattern = Regex("""^mutations\[(\d+)] \(mutation_id="((?:[^"\\]|\\.)*)"\): .*""", RegexOption.DOT_MATCHES_ALL) + + fun parse(detail: String): SyncPushOutcome.StructuralRejection { + val match = pattern.matchEntire(detail) + val index = match?.groupValues?.get(1)?.toIntOrNull() + val id = match?.groupValues?.get(2)?.replace(Regex("""\\(.)"""), "$1") + return if (index == null || id == null) { + SyncPushOutcome.StructuralRejection(null, null, detail) + } else { + SyncPushOutcome.StructuralRejection(index, id, detail) + } + } +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/AttachmentsApi.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/AttachmentsApi.kt new file mode 100644 index 0000000..97eba6b --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/AttachmentsApi.kt @@ -0,0 +1,300 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.apis + +import java.io.IOException +import okhttp3.Call +import okhttp3.HttpUrl + +import dev.hho.android.data.apiclient.generated.models.Attachment +import dev.hho.android.data.apiclient.generated.models.AttachmentListResponse +import dev.hho.android.data.apiclient.generated.models.Problem +import dev.hho.android.data.apiclient.generated.models.UpgradeRequiredProblem + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +import dev.hho.android.data.apiclient.generated.infrastructure.ApiClient +import dev.hho.android.data.apiclient.generated.infrastructure.ApiResponse +import dev.hho.android.data.apiclient.generated.infrastructure.ClientException +import dev.hho.android.data.apiclient.generated.infrastructure.ClientError +import dev.hho.android.data.apiclient.generated.infrastructure.ServerException +import dev.hho.android.data.apiclient.generated.infrastructure.ServerError +import dev.hho.android.data.apiclient.generated.infrastructure.MultiValueMap +import dev.hho.android.data.apiclient.generated.infrastructure.PartConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestMethod +import dev.hho.android.data.apiclient.generated.infrastructure.ResponseType +import dev.hho.android.data.apiclient.generated.infrastructure.Success +import dev.hho.android.data.apiclient.generated.infrastructure.toMultiValue +import dev.hho.android.data.apiclient.generated.infrastructure.Serializer + +open class AttachmentsApi(basePath: kotlin.String = defaultBasePath, client: Call.Factory = ApiClient.defaultClient) : ApiClient(basePath, client) { + companion object { + @JvmStatic + val defaultBasePath: String by lazy { + System.getProperties().getProperty(ApiClient.BASE_URL_KEY, "/api/v1") + } + } + + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun deleteItemAttachment(itemID: kotlin.String, attachmentID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : Unit { + val localVarResponse = deleteItemAttachmentWithHttpInfo(itemID = itemID, attachmentID = attachmentID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Throws(IllegalStateException::class, IOException::class) + fun deleteItemAttachmentWithHttpInfo(itemID: kotlin.String, attachmentID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = deleteItemAttachmentRequestConfig(itemID = itemID, attachmentID = attachmentID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun deleteItemAttachmentRequestConfig(itemID: kotlin.String, attachmentID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.DELETE, + path = "/items/{itemID}/attachments/{attachmentID}".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())).replace("{"+"attachmentID"+"}", encodeURIComponent(attachmentID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun downloadItemAttachment(itemID: kotlin.String, attachmentID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : java.io.File { + val localVarResponse = downloadItemAttachmentWithHttpInfo(itemID = itemID, attachmentID = attachmentID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as java.io.File + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun downloadItemAttachmentWithHttpInfo(itemID: kotlin.String, attachmentID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = downloadItemAttachmentRequestConfig(itemID = itemID, attachmentID = attachmentID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun downloadItemAttachmentRequestConfig(itemID: kotlin.String, attachmentID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/octet-stream, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/items/{itemID}/attachments/{attachmentID}".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())).replace("{"+"attachmentID"+"}", encodeURIComponent(attachmentID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun downloadItemAttachmentThumbnail(itemID: kotlin.String, attachmentID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : java.io.File { + val localVarResponse = downloadItemAttachmentThumbnailWithHttpInfo(itemID = itemID, attachmentID = attachmentID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as java.io.File + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun downloadItemAttachmentThumbnailWithHttpInfo(itemID: kotlin.String, attachmentID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = downloadItemAttachmentThumbnailRequestConfig(itemID = itemID, attachmentID = attachmentID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun downloadItemAttachmentThumbnailRequestConfig(itemID: kotlin.String, attachmentID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/items/{itemID}/attachments/{attachmentID}/thumbnail".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())).replace("{"+"attachmentID"+"}", encodeURIComponent(attachmentID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun listItemAttachments(itemID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : AttachmentListResponse { + val localVarResponse = listItemAttachmentsWithHttpInfo(itemID = itemID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as AttachmentListResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun listItemAttachmentsWithHttpInfo(itemID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = listItemAttachmentsRequestConfig(itemID = itemID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun listItemAttachmentsRequestConfig(itemID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/items/{itemID}/attachments".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + enum class CategoryUploadItemAttachment(val value: kotlin.String) { + @SerialName(value = "image") Image("image"), + @SerialName(value = "manual") Manual("manual"), + @SerialName(value = "warranty") Warranty("warranty"), + @SerialName(value = "receipt") Receipt("receipt"), + @SerialName(value = "general") General("general"); + + override fun toString(): kotlin.String = "$value" + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun uploadItemAttachment(itemID: kotlin.String, category: CategoryUploadItemAttachment, file: java.io.File, xHHOClientVersion: kotlin.String? = null) : Attachment { + val localVarResponse = uploadItemAttachmentWithHttpInfo(itemID = itemID, category = category, file = file, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as Attachment + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun uploadItemAttachmentWithHttpInfo(itemID: kotlin.String, category: CategoryUploadItemAttachment, file: java.io.File, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = uploadItemAttachmentRequestConfig(itemID = itemID, category = category, file = file, xHHOClientVersion = xHHOClientVersion) + + return request>, Attachment>( + localVariableConfig + ) + } + + fun uploadItemAttachmentRequestConfig(itemID: kotlin.String, category: CategoryUploadItemAttachment, file: java.io.File, xHHOClientVersion: kotlin.String?) : RequestConfig>> { + val localVariableBody = mapOf( + "category" to PartConfig(body = category.value, headers = mutableMapOf()), + "file" to PartConfig(body = file, headers = mutableMapOf("Content-Type" to "*/*")),) + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf("Content-Type" to "multipart/form-data") + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.POST, + path = "/items/{itemID}/attachments".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + private fun encodeURIComponent(uriComponent: kotlin.String): kotlin.String = + HttpUrl.Builder().scheme("http").host("localhost").addPathSegment(uriComponent).build().encodedPathSegments[0] +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/AuthApi.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/AuthApi.kt new file mode 100644 index 0000000..2bfe2a5 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/AuthApi.kt @@ -0,0 +1,481 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.apis + +import java.io.IOException +import okhttp3.Call +import okhttp3.HttpUrl + +import dev.hho.android.data.apiclient.generated.models.DeviceTokenIssueRequest +import dev.hho.android.data.apiclient.generated.models.DeviceTokenIssueResponse +import dev.hho.android.data.apiclient.generated.models.DeviceTokenListResponse +import dev.hho.android.data.apiclient.generated.models.LoginRequest +import dev.hho.android.data.apiclient.generated.models.LoginResponse +import dev.hho.android.data.apiclient.generated.models.Problem +import dev.hho.android.data.apiclient.generated.models.RegisterRequest +import dev.hho.android.data.apiclient.generated.models.RegisterResponse +import dev.hho.android.data.apiclient.generated.models.SessionListResponse +import dev.hho.android.data.apiclient.generated.models.UpgradeRequiredProblem + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +import dev.hho.android.data.apiclient.generated.infrastructure.ApiClient +import dev.hho.android.data.apiclient.generated.infrastructure.ApiResponse +import dev.hho.android.data.apiclient.generated.infrastructure.ClientException +import dev.hho.android.data.apiclient.generated.infrastructure.ClientError +import dev.hho.android.data.apiclient.generated.infrastructure.ServerException +import dev.hho.android.data.apiclient.generated.infrastructure.ServerError +import dev.hho.android.data.apiclient.generated.infrastructure.MultiValueMap +import dev.hho.android.data.apiclient.generated.infrastructure.PartConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestMethod +import dev.hho.android.data.apiclient.generated.infrastructure.ResponseType +import dev.hho.android.data.apiclient.generated.infrastructure.Success +import dev.hho.android.data.apiclient.generated.infrastructure.toMultiValue +import dev.hho.android.data.apiclient.generated.infrastructure.Serializer + +open class AuthApi(basePath: kotlin.String = defaultBasePath, client: Call.Factory = ApiClient.defaultClient) : ApiClient(basePath, client) { + companion object { + @JvmStatic + val defaultBasePath: String by lazy { + System.getProperties().getProperty(ApiClient.BASE_URL_KEY, "/api/v1") + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun getCurrentUser(xHHOClientVersion: kotlin.String? = null) : LoginResponse { + val localVarResponse = getCurrentUserWithHttpInfo(xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as LoginResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun getCurrentUserWithHttpInfo(xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = getCurrentUserRequestConfig(xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun getCurrentUserRequestConfig(xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/auth/me", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun issueDeviceToken(deviceTokenIssueRequest: DeviceTokenIssueRequest, xHHOClientVersion: kotlin.String? = null) : DeviceTokenIssueResponse { + val localVarResponse = issueDeviceTokenWithHttpInfo(deviceTokenIssueRequest = deviceTokenIssueRequest, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as DeviceTokenIssueResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun issueDeviceTokenWithHttpInfo(deviceTokenIssueRequest: DeviceTokenIssueRequest, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = issueDeviceTokenRequestConfig(deviceTokenIssueRequest = deviceTokenIssueRequest, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun issueDeviceTokenRequestConfig(deviceTokenIssueRequest: DeviceTokenIssueRequest, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = deviceTokenIssueRequest + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.POST, + path = "/auth/device-tokens", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun listDeviceTokens(xHHOClientVersion: kotlin.String? = null) : DeviceTokenListResponse { + val localVarResponse = listDeviceTokensWithHttpInfo(xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as DeviceTokenListResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun listDeviceTokensWithHttpInfo(xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = listDeviceTokensRequestConfig(xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun listDeviceTokensRequestConfig(xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/auth/device-tokens", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun listSessions(xHHOClientVersion: kotlin.String? = null) : SessionListResponse { + val localVarResponse = listSessionsWithHttpInfo(xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as SessionListResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun listSessionsWithHttpInfo(xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = listSessionsRequestConfig(xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun listSessionsRequestConfig(xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/auth/sessions", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun login(loginRequest: LoginRequest, xHHOClientVersion: kotlin.String? = null) : LoginResponse { + val localVarResponse = loginWithHttpInfo(loginRequest = loginRequest, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as LoginResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun loginWithHttpInfo(loginRequest: LoginRequest, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = loginRequestConfig(loginRequest = loginRequest, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun loginRequestConfig(loginRequest: LoginRequest, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = loginRequest + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.POST, + path = "/auth/login", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = false, + body = localVariableBody + ) + } + + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun logout(xHHOClientVersion: kotlin.String? = null) : Unit { + val localVarResponse = logoutWithHttpInfo(xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Throws(IllegalStateException::class, IOException::class) + fun logoutWithHttpInfo(xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = logoutRequestConfig(xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun logoutRequestConfig(xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.POST, + path = "/auth/logout", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun registerFirstRun(registerRequest: RegisterRequest, xHHOClientVersion: kotlin.String? = null) : RegisterResponse { + val localVarResponse = registerFirstRunWithHttpInfo(registerRequest = registerRequest, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as RegisterResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun registerFirstRunWithHttpInfo(registerRequest: RegisterRequest, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = registerFirstRunRequestConfig(registerRequest = registerRequest, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun registerFirstRunRequestConfig(registerRequest: RegisterRequest, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = registerRequest + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.POST, + path = "/auth/register", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = false, + body = localVariableBody + ) + } + + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun revokeDeviceToken(deviceTokenID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : Unit { + val localVarResponse = revokeDeviceTokenWithHttpInfo(deviceTokenID = deviceTokenID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Throws(IllegalStateException::class, IOException::class) + fun revokeDeviceTokenWithHttpInfo(deviceTokenID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = revokeDeviceTokenRequestConfig(deviceTokenID = deviceTokenID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun revokeDeviceTokenRequestConfig(deviceTokenID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.DELETE, + path = "/auth/device-tokens/{deviceTokenID}".replace("{"+"deviceTokenID"+"}", encodeURIComponent(deviceTokenID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun revokeSession(sessionID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : Unit { + val localVarResponse = revokeSessionWithHttpInfo(sessionID = sessionID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Throws(IllegalStateException::class, IOException::class) + fun revokeSessionWithHttpInfo(sessionID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = revokeSessionRequestConfig(sessionID = sessionID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun revokeSessionRequestConfig(sessionID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.DELETE, + path = "/auth/sessions/{sessionID}".replace("{"+"sessionID"+"}", encodeURIComponent(sessionID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + private fun encodeURIComponent(uriComponent: kotlin.String): kotlin.String = + HttpUrl.Builder().scheme("http").host("localhost").addPathSegment(uriComponent).build().encodedPathSegments[0] +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/BackupApi.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/BackupApi.kt new file mode 100644 index 0000000..cd9cc35 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/BackupApi.kt @@ -0,0 +1,100 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.apis + +import java.io.IOException +import okhttp3.Call +import okhttp3.HttpUrl + +import dev.hho.android.data.apiclient.generated.models.Problem +import dev.hho.android.data.apiclient.generated.models.UpgradeRequiredProblem + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +import dev.hho.android.data.apiclient.generated.infrastructure.ApiClient +import dev.hho.android.data.apiclient.generated.infrastructure.ApiResponse +import dev.hho.android.data.apiclient.generated.infrastructure.ClientException +import dev.hho.android.data.apiclient.generated.infrastructure.ClientError +import dev.hho.android.data.apiclient.generated.infrastructure.ServerException +import dev.hho.android.data.apiclient.generated.infrastructure.ServerError +import dev.hho.android.data.apiclient.generated.infrastructure.MultiValueMap +import dev.hho.android.data.apiclient.generated.infrastructure.PartConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestMethod +import dev.hho.android.data.apiclient.generated.infrastructure.ResponseType +import dev.hho.android.data.apiclient.generated.infrastructure.Success +import dev.hho.android.data.apiclient.generated.infrastructure.toMultiValue +import dev.hho.android.data.apiclient.generated.infrastructure.Serializer + +open class BackupApi(basePath: kotlin.String = defaultBasePath, client: Call.Factory = ApiClient.defaultClient) : ApiClient(basePath, client) { + companion object { + @JvmStatic + val defaultBasePath: String by lazy { + System.getProperties().getProperty(ApiClient.BASE_URL_KEY, "/api/v1") + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun getBackup(xHHOClientVersion: kotlin.String? = null) : java.io.File { + val localVarResponse = getBackupWithHttpInfo(xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as java.io.File + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun getBackupWithHttpInfo(xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = getBackupRequestConfig(xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun getBackupRequestConfig(xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/backup", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + private fun encodeURIComponent(uriComponent: kotlin.String): kotlin.String = + HttpUrl.Builder().scheme("http").host("localhost").addPathSegment(uriComponent).build().encodedPathSegments[0] +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/CustomFieldDefsApi.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/CustomFieldDefsApi.kt new file mode 100644 index 0000000..bac59e8 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/CustomFieldDefsApi.kt @@ -0,0 +1,245 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.apis + +import java.io.IOException +import okhttp3.Call +import okhttp3.HttpUrl + +import dev.hho.android.data.apiclient.generated.models.CustomFieldDef +import dev.hho.android.data.apiclient.generated.models.CustomFieldDefCreateRequest +import dev.hho.android.data.apiclient.generated.models.CustomFieldDefListResponse +import dev.hho.android.data.apiclient.generated.models.CustomFieldDefUpdateRequest +import dev.hho.android.data.apiclient.generated.models.Problem +import dev.hho.android.data.apiclient.generated.models.UpgradeRequiredProblem + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +import dev.hho.android.data.apiclient.generated.infrastructure.ApiClient +import dev.hho.android.data.apiclient.generated.infrastructure.ApiResponse +import dev.hho.android.data.apiclient.generated.infrastructure.ClientException +import dev.hho.android.data.apiclient.generated.infrastructure.ClientError +import dev.hho.android.data.apiclient.generated.infrastructure.ServerException +import dev.hho.android.data.apiclient.generated.infrastructure.ServerError +import dev.hho.android.data.apiclient.generated.infrastructure.MultiValueMap +import dev.hho.android.data.apiclient.generated.infrastructure.PartConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestMethod +import dev.hho.android.data.apiclient.generated.infrastructure.ResponseType +import dev.hho.android.data.apiclient.generated.infrastructure.Success +import dev.hho.android.data.apiclient.generated.infrastructure.toMultiValue +import dev.hho.android.data.apiclient.generated.infrastructure.Serializer + +open class CustomFieldDefsApi(basePath: kotlin.String = defaultBasePath, client: Call.Factory = ApiClient.defaultClient) : ApiClient(basePath, client) { + companion object { + @JvmStatic + val defaultBasePath: String by lazy { + System.getProperties().getProperty(ApiClient.BASE_URL_KEY, "/api/v1") + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun createCustomFieldDef(customFieldDefCreateRequest: CustomFieldDefCreateRequest, xHHOClientVersion: kotlin.String? = null) : CustomFieldDef { + val localVarResponse = createCustomFieldDefWithHttpInfo(customFieldDefCreateRequest = customFieldDefCreateRequest, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as CustomFieldDef + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun createCustomFieldDefWithHttpInfo(customFieldDefCreateRequest: CustomFieldDefCreateRequest, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = createCustomFieldDefRequestConfig(customFieldDefCreateRequest = customFieldDefCreateRequest, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun createCustomFieldDefRequestConfig(customFieldDefCreateRequest: CustomFieldDefCreateRequest, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = customFieldDefCreateRequest + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.POST, + path = "/custom-field-defs", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun deleteCustomFieldDef(fieldDefID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : Unit { + val localVarResponse = deleteCustomFieldDefWithHttpInfo(fieldDefID = fieldDefID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Throws(IllegalStateException::class, IOException::class) + fun deleteCustomFieldDefWithHttpInfo(fieldDefID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = deleteCustomFieldDefRequestConfig(fieldDefID = fieldDefID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun deleteCustomFieldDefRequestConfig(fieldDefID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.DELETE, + path = "/custom-field-defs/{fieldDefID}".replace("{"+"fieldDefID"+"}", encodeURIComponent(fieldDefID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun listCustomFieldDefs(xHHOClientVersion: kotlin.String? = null) : CustomFieldDefListResponse { + val localVarResponse = listCustomFieldDefsWithHttpInfo(xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as CustomFieldDefListResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun listCustomFieldDefsWithHttpInfo(xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = listCustomFieldDefsRequestConfig(xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun listCustomFieldDefsRequestConfig(xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/custom-field-defs", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun updateCustomFieldDef(fieldDefID: kotlin.String, customFieldDefUpdateRequest: CustomFieldDefUpdateRequest, xHHOClientVersion: kotlin.String? = null) : CustomFieldDef { + val localVarResponse = updateCustomFieldDefWithHttpInfo(fieldDefID = fieldDefID, customFieldDefUpdateRequest = customFieldDefUpdateRequest, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as CustomFieldDef + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun updateCustomFieldDefWithHttpInfo(fieldDefID: kotlin.String, customFieldDefUpdateRequest: CustomFieldDefUpdateRequest, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = updateCustomFieldDefRequestConfig(fieldDefID = fieldDefID, customFieldDefUpdateRequest = customFieldDefUpdateRequest, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun updateCustomFieldDefRequestConfig(fieldDefID: kotlin.String, customFieldDefUpdateRequest: CustomFieldDefUpdateRequest, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = customFieldDefUpdateRequest + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.PUT, + path = "/custom-field-defs/{fieldDefID}".replace("{"+"fieldDefID"+"}", encodeURIComponent(fieldDefID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + private fun encodeURIComponent(uriComponent: kotlin.String): kotlin.String = + HttpUrl.Builder().scheme("http").host("localhost").addPathSegment(uriComponent).build().encodedPathSegments[0] +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/ExportApi.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/ExportApi.kt new file mode 100644 index 0000000..a4924c1 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/ExportApi.kt @@ -0,0 +1,158 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.apis + +import java.io.IOException +import okhttp3.Call +import okhttp3.HttpUrl + +import dev.hho.android.data.apiclient.generated.models.Problem +import dev.hho.android.data.apiclient.generated.models.UpgradeRequiredProblem + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +import dev.hho.android.data.apiclient.generated.infrastructure.ApiClient +import dev.hho.android.data.apiclient.generated.infrastructure.ApiResponse +import dev.hho.android.data.apiclient.generated.infrastructure.ClientException +import dev.hho.android.data.apiclient.generated.infrastructure.ClientError +import dev.hho.android.data.apiclient.generated.infrastructure.ServerException +import dev.hho.android.data.apiclient.generated.infrastructure.ServerError +import dev.hho.android.data.apiclient.generated.infrastructure.MultiValueMap +import dev.hho.android.data.apiclient.generated.infrastructure.PartConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestMethod +import dev.hho.android.data.apiclient.generated.infrastructure.ResponseType +import dev.hho.android.data.apiclient.generated.infrastructure.Success +import dev.hho.android.data.apiclient.generated.infrastructure.toMultiValue +import dev.hho.android.data.apiclient.generated.infrastructure.Serializer + +open class ExportApi(basePath: kotlin.String = defaultBasePath, client: Call.Factory = ApiClient.defaultClient) : ApiClient(basePath, client) { + companion object { + @JvmStatic + val defaultBasePath: String by lazy { + System.getProperties().getProperty(ApiClient.BASE_URL_KEY, "/api/v1") + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun exportBoM(locationId: kotlin.collections.List? = null, labelId: kotlin.collections.List? = null, itemId: kotlin.collections.List? = null, xHHOClientVersion: kotlin.String? = null) : java.io.File { + val localVarResponse = exportBoMWithHttpInfo(locationId = locationId, labelId = labelId, itemId = itemId, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as java.io.File + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun exportBoMWithHttpInfo(locationId: kotlin.collections.List?, labelId: kotlin.collections.List?, itemId: kotlin.collections.List?, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = exportBoMRequestConfig(locationId = locationId, labelId = labelId, itemId = itemId, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun exportBoMRequestConfig(locationId: kotlin.collections.List?, labelId: kotlin.collections.List?, itemId: kotlin.collections.List?, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf>() + .apply { + if (locationId != null) { + put("location_id", toMultiValue(locationId.toList(), "multi")) + } + if (labelId != null) { + put("label_id", toMultiValue(labelId.toList(), "multi")) + } + if (itemId != null) { + put("item_id", toMultiValue(itemId.toList(), "multi")) + } + } + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/export/bom", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun exportItemsCSV(xHHOClientVersion: kotlin.String? = null) : java.io.File { + val localVarResponse = exportItemsCSVWithHttpInfo(xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as java.io.File + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun exportItemsCSVWithHttpInfo(xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = exportItemsCSVRequestConfig(xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun exportItemsCSVRequestConfig(xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/export/items.csv", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + private fun encodeURIComponent(uriComponent: kotlin.String): kotlin.String = + HttpUrl.Builder().scheme("http").host("localhost").addPathSegment(uriComponent).build().encodedPathSegments[0] +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/GroupsApi.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/GroupsApi.kt new file mode 100644 index 0000000..f5895d8 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/GroupsApi.kt @@ -0,0 +1,198 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.apis + +import java.io.IOException +import okhttp3.Call +import okhttp3.HttpUrl + +import dev.hho.android.data.apiclient.generated.models.GroupMembersResponse +import dev.hho.android.data.apiclient.generated.models.GroupVisibility +import dev.hho.android.data.apiclient.generated.models.GroupVisibilityUpdateRequest +import dev.hho.android.data.apiclient.generated.models.Problem +import dev.hho.android.data.apiclient.generated.models.UpgradeRequiredProblem + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +import dev.hho.android.data.apiclient.generated.infrastructure.ApiClient +import dev.hho.android.data.apiclient.generated.infrastructure.ApiResponse +import dev.hho.android.data.apiclient.generated.infrastructure.ClientException +import dev.hho.android.data.apiclient.generated.infrastructure.ClientError +import dev.hho.android.data.apiclient.generated.infrastructure.ServerException +import dev.hho.android.data.apiclient.generated.infrastructure.ServerError +import dev.hho.android.data.apiclient.generated.infrastructure.MultiValueMap +import dev.hho.android.data.apiclient.generated.infrastructure.PartConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestMethod +import dev.hho.android.data.apiclient.generated.infrastructure.ResponseType +import dev.hho.android.data.apiclient.generated.infrastructure.Success +import dev.hho.android.data.apiclient.generated.infrastructure.toMultiValue +import dev.hho.android.data.apiclient.generated.infrastructure.Serializer + +open class GroupsApi(basePath: kotlin.String = defaultBasePath, client: Call.Factory = ApiClient.defaultClient) : ApiClient(basePath, client) { + companion object { + @JvmStatic + val defaultBasePath: String by lazy { + System.getProperties().getProperty(ApiClient.BASE_URL_KEY, "/api/v1") + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun getGroupDetailVisibility(xHHOClientVersion: kotlin.String? = null) : GroupVisibility { + val localVarResponse = getGroupDetailVisibilityWithHttpInfo(xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as GroupVisibility + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun getGroupDetailVisibilityWithHttpInfo(xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = getGroupDetailVisibilityRequestConfig(xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun getGroupDetailVisibilityRequestConfig(xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/groups/detail-visibility", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun listGroupMembers(xHHOClientVersion: kotlin.String? = null) : GroupMembersResponse { + val localVarResponse = listGroupMembersWithHttpInfo(xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as GroupMembersResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun listGroupMembersWithHttpInfo(xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = listGroupMembersRequestConfig(xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun listGroupMembersRequestConfig(xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/groups/members", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun updateGroupDetailVisibility(groupVisibilityUpdateRequest: GroupVisibilityUpdateRequest, xHHOClientVersion: kotlin.String? = null) : GroupVisibility { + val localVarResponse = updateGroupDetailVisibilityWithHttpInfo(groupVisibilityUpdateRequest = groupVisibilityUpdateRequest, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as GroupVisibility + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun updateGroupDetailVisibilityWithHttpInfo(groupVisibilityUpdateRequest: GroupVisibilityUpdateRequest, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = updateGroupDetailVisibilityRequestConfig(groupVisibilityUpdateRequest = groupVisibilityUpdateRequest, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun updateGroupDetailVisibilityRequestConfig(groupVisibilityUpdateRequest: GroupVisibilityUpdateRequest, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = groupVisibilityUpdateRequest + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.PUT, + path = "/groups/detail-visibility", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + private fun encodeURIComponent(uriComponent: kotlin.String): kotlin.String = + HttpUrl.Builder().scheme("http").host("localhost").addPathSegment(uriComponent).build().encodedPathSegments[0] +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/ImportApi.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/ImportApi.kt new file mode 100644 index 0000000..c81bd30 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/ImportApi.kt @@ -0,0 +1,198 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.apis + +import java.io.IOException +import okhttp3.Call +import okhttp3.HttpUrl + +import dev.hho.android.data.apiclient.generated.models.ImportCommitRejectedResponse +import dev.hho.android.data.apiclient.generated.models.ImportCommitResponse +import dev.hho.android.data.apiclient.generated.models.ImportPreviewResponse +import dev.hho.android.data.apiclient.generated.models.ImportUploadResponse +import dev.hho.android.data.apiclient.generated.models.Problem +import dev.hho.android.data.apiclient.generated.models.UpgradeRequiredProblem + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +import dev.hho.android.data.apiclient.generated.infrastructure.ApiClient +import dev.hho.android.data.apiclient.generated.infrastructure.ApiResponse +import dev.hho.android.data.apiclient.generated.infrastructure.ClientException +import dev.hho.android.data.apiclient.generated.infrastructure.ClientError +import dev.hho.android.data.apiclient.generated.infrastructure.ServerException +import dev.hho.android.data.apiclient.generated.infrastructure.ServerError +import dev.hho.android.data.apiclient.generated.infrastructure.MultiValueMap +import dev.hho.android.data.apiclient.generated.infrastructure.PartConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestMethod +import dev.hho.android.data.apiclient.generated.infrastructure.ResponseType +import dev.hho.android.data.apiclient.generated.infrastructure.Success +import dev.hho.android.data.apiclient.generated.infrastructure.toMultiValue +import dev.hho.android.data.apiclient.generated.infrastructure.Serializer + +open class ImportApi(basePath: kotlin.String = defaultBasePath, client: Call.Factory = ApiClient.defaultClient) : ApiClient(basePath, client) { + companion object { + @JvmStatic + val defaultBasePath: String by lazy { + System.getProperties().getProperty(ApiClient.BASE_URL_KEY, "/api/v1") + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun getImportPreview(importID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : ImportPreviewResponse { + val localVarResponse = getImportPreviewWithHttpInfo(importID = importID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as ImportPreviewResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun getImportPreviewWithHttpInfo(importID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = getImportPreviewRequestConfig(importID = importID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun getImportPreviewRequestConfig(importID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/import/{importID}/preview".replace("{"+"importID"+"}", encodeURIComponent(importID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun importNativeUpload(body: java.io.File, xHHOClientVersion: kotlin.String? = null) : ImportUploadResponse { + val localVarResponse = importNativeUploadWithHttpInfo(body = body, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as ImportUploadResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun importNativeUploadWithHttpInfo(body: java.io.File, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = importNativeUploadRequestConfig(body = body, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun importNativeUploadRequestConfig(body: java.io.File, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = body + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.POST, + path = "/import/native/upload", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun postImportCommit(importID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : ImportCommitResponse { + val localVarResponse = postImportCommitWithHttpInfo(importID = importID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as ImportCommitResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun postImportCommitWithHttpInfo(importID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = postImportCommitRequestConfig(importID = importID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun postImportCommitRequestConfig(importID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.POST, + path = "/import/{importID}/commit".replace("{"+"importID"+"}", encodeURIComponent(importID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + private fun encodeURIComponent(uriComponent: kotlin.String): kotlin.String = + HttpUrl.Builder().scheme("http").host("localhost").addPathSegment(uriComponent).build().encodedPathSegments[0] +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/InvitesApi.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/InvitesApi.kt new file mode 100644 index 0000000..1f51037 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/InvitesApi.kt @@ -0,0 +1,244 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.apis + +import java.io.IOException +import okhttp3.Call +import okhttp3.HttpUrl + +import dev.hho.android.data.apiclient.generated.models.InviteCreateResponse +import dev.hho.android.data.apiclient.generated.models.InviteListResponse +import dev.hho.android.data.apiclient.generated.models.InviteRedeemRequest +import dev.hho.android.data.apiclient.generated.models.InviteRedeemResponse +import dev.hho.android.data.apiclient.generated.models.Problem +import dev.hho.android.data.apiclient.generated.models.UpgradeRequiredProblem + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +import dev.hho.android.data.apiclient.generated.infrastructure.ApiClient +import dev.hho.android.data.apiclient.generated.infrastructure.ApiResponse +import dev.hho.android.data.apiclient.generated.infrastructure.ClientException +import dev.hho.android.data.apiclient.generated.infrastructure.ClientError +import dev.hho.android.data.apiclient.generated.infrastructure.ServerException +import dev.hho.android.data.apiclient.generated.infrastructure.ServerError +import dev.hho.android.data.apiclient.generated.infrastructure.MultiValueMap +import dev.hho.android.data.apiclient.generated.infrastructure.PartConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestMethod +import dev.hho.android.data.apiclient.generated.infrastructure.ResponseType +import dev.hho.android.data.apiclient.generated.infrastructure.Success +import dev.hho.android.data.apiclient.generated.infrastructure.toMultiValue +import dev.hho.android.data.apiclient.generated.infrastructure.Serializer + +open class InvitesApi(basePath: kotlin.String = defaultBasePath, client: Call.Factory = ApiClient.defaultClient) : ApiClient(basePath, client) { + companion object { + @JvmStatic + val defaultBasePath: String by lazy { + System.getProperties().getProperty(ApiClient.BASE_URL_KEY, "/api/v1") + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun createInvite(xHHOClientVersion: kotlin.String? = null) : InviteCreateResponse { + val localVarResponse = createInviteWithHttpInfo(xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as InviteCreateResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun createInviteWithHttpInfo(xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = createInviteRequestConfig(xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun createInviteRequestConfig(xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.POST, + path = "/invites", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun listInvites(xHHOClientVersion: kotlin.String? = null) : InviteListResponse { + val localVarResponse = listInvitesWithHttpInfo(xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as InviteListResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun listInvitesWithHttpInfo(xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = listInvitesRequestConfig(xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun listInvitesRequestConfig(xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/invites", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun redeemInvite(inviteRedeemRequest: InviteRedeemRequest, xHHOClientVersion: kotlin.String? = null) : InviteRedeemResponse { + val localVarResponse = redeemInviteWithHttpInfo(inviteRedeemRequest = inviteRedeemRequest, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as InviteRedeemResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun redeemInviteWithHttpInfo(inviteRedeemRequest: InviteRedeemRequest, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = redeemInviteRequestConfig(inviteRedeemRequest = inviteRedeemRequest, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun redeemInviteRequestConfig(inviteRedeemRequest: InviteRedeemRequest, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = inviteRedeemRequest + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.POST, + path = "/invites/redeem", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = false, + body = localVariableBody + ) + } + + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun revokeInvite(inviteID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : Unit { + val localVarResponse = revokeInviteWithHttpInfo(inviteID = inviteID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Throws(IllegalStateException::class, IOException::class) + fun revokeInviteWithHttpInfo(inviteID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = revokeInviteRequestConfig(inviteID = inviteID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun revokeInviteRequestConfig(inviteID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.DELETE, + path = "/invites/{inviteID}".replace("{"+"inviteID"+"}", encodeURIComponent(inviteID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + private fun encodeURIComponent(uriComponent: kotlin.String): kotlin.String = + HttpUrl.Builder().scheme("http").host("localhost").addPathSegment(uriComponent).build().encodedPathSegments[0] +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/ItemsApi.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/ItemsApi.kt new file mode 100644 index 0000000..fa53e78 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/ItemsApi.kt @@ -0,0 +1,1782 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.apis + +import java.io.IOException +import okhttp3.Call +import okhttp3.HttpUrl + +import dev.hho.android.data.apiclient.generated.models.Attachment +import dev.hho.android.data.apiclient.generated.models.AttachmentListResponse +import dev.hho.android.data.apiclient.generated.models.Identification +import dev.hho.android.data.apiclient.generated.models.IdentificationCreateRequest +import dev.hho.android.data.apiclient.generated.models.IdentificationListResponse +import dev.hho.android.data.apiclient.generated.models.IdentificationUpdateRequest +import dev.hho.android.data.apiclient.generated.models.Item +import dev.hho.android.data.apiclient.generated.models.ItemCustomField +import dev.hho.android.data.apiclient.generated.models.ItemCustomFieldCreateRequest +import dev.hho.android.data.apiclient.generated.models.ItemCustomFieldListResponse +import dev.hho.android.data.apiclient.generated.models.ItemCustomFieldUpdateRequest +import dev.hho.android.data.apiclient.generated.models.ItemListResponse +import dev.hho.android.data.apiclient.generated.models.ItemUpdateRequest +import dev.hho.android.data.apiclient.generated.models.LabelListResponse +import dev.hho.android.data.apiclient.generated.models.Problem +import dev.hho.android.data.apiclient.generated.models.PurchaseBlock +import dev.hho.android.data.apiclient.generated.models.PurchaseCreateRequest +import dev.hho.android.data.apiclient.generated.models.PurchaseUpdateRequest +import dev.hho.android.data.apiclient.generated.models.SaleBlock +import dev.hho.android.data.apiclient.generated.models.SaleCreateRequest +import dev.hho.android.data.apiclient.generated.models.SaleUpdateRequest +import dev.hho.android.data.apiclient.generated.models.StockAdjustment +import dev.hho.android.data.apiclient.generated.models.StockAdjustmentCreateRequest +import dev.hho.android.data.apiclient.generated.models.StockAdjustmentListResponse +import dev.hho.android.data.apiclient.generated.models.UpgradeRequiredProblem +import dev.hho.android.data.apiclient.generated.models.WarrantyBlock +import dev.hho.android.data.apiclient.generated.models.WarrantyCreateRequest +import dev.hho.android.data.apiclient.generated.models.WarrantyUpdateRequest + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +import dev.hho.android.data.apiclient.generated.infrastructure.ApiClient +import dev.hho.android.data.apiclient.generated.infrastructure.ApiResponse +import dev.hho.android.data.apiclient.generated.infrastructure.ClientException +import dev.hho.android.data.apiclient.generated.infrastructure.ClientError +import dev.hho.android.data.apiclient.generated.infrastructure.ServerException +import dev.hho.android.data.apiclient.generated.infrastructure.ServerError +import dev.hho.android.data.apiclient.generated.infrastructure.MultiValueMap +import dev.hho.android.data.apiclient.generated.infrastructure.PartConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestMethod +import dev.hho.android.data.apiclient.generated.infrastructure.ResponseType +import dev.hho.android.data.apiclient.generated.infrastructure.Success +import dev.hho.android.data.apiclient.generated.infrastructure.toMultiValue +import dev.hho.android.data.apiclient.generated.infrastructure.Serializer + +open class ItemsApi(basePath: kotlin.String = defaultBasePath, client: Call.Factory = ApiClient.defaultClient) : ApiClient(basePath, client) { + companion object { + @JvmStatic + val defaultBasePath: String by lazy { + System.getProperties().getProperty(ApiClient.BASE_URL_KEY, "/api/v1") + } + } + + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun attachItemLabel(itemID: kotlin.String, labelID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : Unit { + val localVarResponse = attachItemLabelWithHttpInfo(itemID = itemID, labelID = labelID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Throws(IllegalStateException::class, IOException::class) + fun attachItemLabelWithHttpInfo(itemID: kotlin.String, labelID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = attachItemLabelRequestConfig(itemID = itemID, labelID = labelID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun attachItemLabelRequestConfig(itemID: kotlin.String, labelID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.PUT, + path = "/items/{itemID}/labels/{labelID}".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())).replace("{"+"labelID"+"}", encodeURIComponent(labelID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun createItem(item: Item, xHHOClientVersion: kotlin.String? = null) : Item { + val localVarResponse = createItemWithHttpInfo(item = item, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as Item + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun createItemWithHttpInfo(item: Item, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = createItemRequestConfig(item = item, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun createItemRequestConfig(item: Item, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = item + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.POST, + path = "/items", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun createItemCustomField(itemID: kotlin.String, itemCustomFieldCreateRequest: ItemCustomFieldCreateRequest, xHHOClientVersion: kotlin.String? = null) : ItemCustomField { + val localVarResponse = createItemCustomFieldWithHttpInfo(itemID = itemID, itemCustomFieldCreateRequest = itemCustomFieldCreateRequest, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as ItemCustomField + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun createItemCustomFieldWithHttpInfo(itemID: kotlin.String, itemCustomFieldCreateRequest: ItemCustomFieldCreateRequest, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = createItemCustomFieldRequestConfig(itemID = itemID, itemCustomFieldCreateRequest = itemCustomFieldCreateRequest, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun createItemCustomFieldRequestConfig(itemID: kotlin.String, itemCustomFieldCreateRequest: ItemCustomFieldCreateRequest, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = itemCustomFieldCreateRequest + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.POST, + path = "/items/{itemID}/custom-fields".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun createItemIdentification(itemID: kotlin.String, identificationCreateRequest: IdentificationCreateRequest, xHHOClientVersion: kotlin.String? = null) : Identification { + val localVarResponse = createItemIdentificationWithHttpInfo(itemID = itemID, identificationCreateRequest = identificationCreateRequest, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as Identification + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun createItemIdentificationWithHttpInfo(itemID: kotlin.String, identificationCreateRequest: IdentificationCreateRequest, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = createItemIdentificationRequestConfig(itemID = itemID, identificationCreateRequest = identificationCreateRequest, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun createItemIdentificationRequestConfig(itemID: kotlin.String, identificationCreateRequest: IdentificationCreateRequest, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = identificationCreateRequest + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.POST, + path = "/items/{itemID}/identifications".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun createItemPurchase(itemID: kotlin.String, purchaseCreateRequest: PurchaseCreateRequest, xHHOClientVersion: kotlin.String? = null) : PurchaseBlock { + val localVarResponse = createItemPurchaseWithHttpInfo(itemID = itemID, purchaseCreateRequest = purchaseCreateRequest, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as PurchaseBlock + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun createItemPurchaseWithHttpInfo(itemID: kotlin.String, purchaseCreateRequest: PurchaseCreateRequest, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = createItemPurchaseRequestConfig(itemID = itemID, purchaseCreateRequest = purchaseCreateRequest, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun createItemPurchaseRequestConfig(itemID: kotlin.String, purchaseCreateRequest: PurchaseCreateRequest, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = purchaseCreateRequest + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.POST, + path = "/items/{itemID}/purchase".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun createItemSale(itemID: kotlin.String, saleCreateRequest: SaleCreateRequest, xHHOClientVersion: kotlin.String? = null) : SaleBlock { + val localVarResponse = createItemSaleWithHttpInfo(itemID = itemID, saleCreateRequest = saleCreateRequest, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as SaleBlock + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun createItemSaleWithHttpInfo(itemID: kotlin.String, saleCreateRequest: SaleCreateRequest, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = createItemSaleRequestConfig(itemID = itemID, saleCreateRequest = saleCreateRequest, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun createItemSaleRequestConfig(itemID: kotlin.String, saleCreateRequest: SaleCreateRequest, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = saleCreateRequest + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.POST, + path = "/items/{itemID}/sale".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun createItemStockAdjustment(itemID: kotlin.String, stockAdjustmentCreateRequest: StockAdjustmentCreateRequest, xHHOClientVersion: kotlin.String? = null) : StockAdjustment { + val localVarResponse = createItemStockAdjustmentWithHttpInfo(itemID = itemID, stockAdjustmentCreateRequest = stockAdjustmentCreateRequest, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as StockAdjustment + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun createItemStockAdjustmentWithHttpInfo(itemID: kotlin.String, stockAdjustmentCreateRequest: StockAdjustmentCreateRequest, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = createItemStockAdjustmentRequestConfig(itemID = itemID, stockAdjustmentCreateRequest = stockAdjustmentCreateRequest, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun createItemStockAdjustmentRequestConfig(itemID: kotlin.String, stockAdjustmentCreateRequest: StockAdjustmentCreateRequest, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = stockAdjustmentCreateRequest + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.POST, + path = "/items/{itemID}/stock-adjustments".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun createItemWarranty(itemID: kotlin.String, warrantyCreateRequest: WarrantyCreateRequest, xHHOClientVersion: kotlin.String? = null) : WarrantyBlock { + val localVarResponse = createItemWarrantyWithHttpInfo(itemID = itemID, warrantyCreateRequest = warrantyCreateRequest, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as WarrantyBlock + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun createItemWarrantyWithHttpInfo(itemID: kotlin.String, warrantyCreateRequest: WarrantyCreateRequest, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = createItemWarrantyRequestConfig(itemID = itemID, warrantyCreateRequest = warrantyCreateRequest, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun createItemWarrantyRequestConfig(itemID: kotlin.String, warrantyCreateRequest: WarrantyCreateRequest, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = warrantyCreateRequest + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.POST, + path = "/items/{itemID}/warranty".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun deleteItem(itemID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : Unit { + val localVarResponse = deleteItemWithHttpInfo(itemID = itemID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Throws(IllegalStateException::class, IOException::class) + fun deleteItemWithHttpInfo(itemID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = deleteItemRequestConfig(itemID = itemID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun deleteItemRequestConfig(itemID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.DELETE, + path = "/items/{itemID}".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun deleteItemAttachment(itemID: kotlin.String, attachmentID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : Unit { + val localVarResponse = deleteItemAttachmentWithHttpInfo(itemID = itemID, attachmentID = attachmentID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Throws(IllegalStateException::class, IOException::class) + fun deleteItemAttachmentWithHttpInfo(itemID: kotlin.String, attachmentID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = deleteItemAttachmentRequestConfig(itemID = itemID, attachmentID = attachmentID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun deleteItemAttachmentRequestConfig(itemID: kotlin.String, attachmentID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.DELETE, + path = "/items/{itemID}/attachments/{attachmentID}".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())).replace("{"+"attachmentID"+"}", encodeURIComponent(attachmentID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun deleteItemCustomField(itemID: kotlin.String, customFieldID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : Unit { + val localVarResponse = deleteItemCustomFieldWithHttpInfo(itemID = itemID, customFieldID = customFieldID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Throws(IllegalStateException::class, IOException::class) + fun deleteItemCustomFieldWithHttpInfo(itemID: kotlin.String, customFieldID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = deleteItemCustomFieldRequestConfig(itemID = itemID, customFieldID = customFieldID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun deleteItemCustomFieldRequestConfig(itemID: kotlin.String, customFieldID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.DELETE, + path = "/items/{itemID}/custom-fields/{customFieldID}".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())).replace("{"+"customFieldID"+"}", encodeURIComponent(customFieldID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun deleteItemIdentification(itemID: kotlin.String, identificationID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : Unit { + val localVarResponse = deleteItemIdentificationWithHttpInfo(itemID = itemID, identificationID = identificationID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Throws(IllegalStateException::class, IOException::class) + fun deleteItemIdentificationWithHttpInfo(itemID: kotlin.String, identificationID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = deleteItemIdentificationRequestConfig(itemID = itemID, identificationID = identificationID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun deleteItemIdentificationRequestConfig(itemID: kotlin.String, identificationID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.DELETE, + path = "/items/{itemID}/identifications/{identificationID}".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())).replace("{"+"identificationID"+"}", encodeURIComponent(identificationID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun deleteItemPurchase(itemID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : Unit { + val localVarResponse = deleteItemPurchaseWithHttpInfo(itemID = itemID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Throws(IllegalStateException::class, IOException::class) + fun deleteItemPurchaseWithHttpInfo(itemID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = deleteItemPurchaseRequestConfig(itemID = itemID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun deleteItemPurchaseRequestConfig(itemID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.DELETE, + path = "/items/{itemID}/purchase".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun deleteItemSale(itemID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : Unit { + val localVarResponse = deleteItemSaleWithHttpInfo(itemID = itemID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Throws(IllegalStateException::class, IOException::class) + fun deleteItemSaleWithHttpInfo(itemID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = deleteItemSaleRequestConfig(itemID = itemID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun deleteItemSaleRequestConfig(itemID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.DELETE, + path = "/items/{itemID}/sale".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun deleteItemWarranty(itemID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : Unit { + val localVarResponse = deleteItemWarrantyWithHttpInfo(itemID = itemID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Throws(IllegalStateException::class, IOException::class) + fun deleteItemWarrantyWithHttpInfo(itemID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = deleteItemWarrantyRequestConfig(itemID = itemID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun deleteItemWarrantyRequestConfig(itemID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.DELETE, + path = "/items/{itemID}/warranty".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun detachItemLabel(itemID: kotlin.String, labelID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : Unit { + val localVarResponse = detachItemLabelWithHttpInfo(itemID = itemID, labelID = labelID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Throws(IllegalStateException::class, IOException::class) + fun detachItemLabelWithHttpInfo(itemID: kotlin.String, labelID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = detachItemLabelRequestConfig(itemID = itemID, labelID = labelID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun detachItemLabelRequestConfig(itemID: kotlin.String, labelID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.DELETE, + path = "/items/{itemID}/labels/{labelID}".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())).replace("{"+"labelID"+"}", encodeURIComponent(labelID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun downloadItemAttachment(itemID: kotlin.String, attachmentID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : java.io.File { + val localVarResponse = downloadItemAttachmentWithHttpInfo(itemID = itemID, attachmentID = attachmentID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as java.io.File + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun downloadItemAttachmentWithHttpInfo(itemID: kotlin.String, attachmentID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = downloadItemAttachmentRequestConfig(itemID = itemID, attachmentID = attachmentID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun downloadItemAttachmentRequestConfig(itemID: kotlin.String, attachmentID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/octet-stream, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/items/{itemID}/attachments/{attachmentID}".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())).replace("{"+"attachmentID"+"}", encodeURIComponent(attachmentID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun downloadItemAttachmentThumbnail(itemID: kotlin.String, attachmentID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : java.io.File { + val localVarResponse = downloadItemAttachmentThumbnailWithHttpInfo(itemID = itemID, attachmentID = attachmentID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as java.io.File + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun downloadItemAttachmentThumbnailWithHttpInfo(itemID: kotlin.String, attachmentID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = downloadItemAttachmentThumbnailRequestConfig(itemID = itemID, attachmentID = attachmentID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun downloadItemAttachmentThumbnailRequestConfig(itemID: kotlin.String, attachmentID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/items/{itemID}/attachments/{attachmentID}/thumbnail".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())).replace("{"+"attachmentID"+"}", encodeURIComponent(attachmentID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun getItem(itemID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : Item { + val localVarResponse = getItemWithHttpInfo(itemID = itemID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as Item + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun getItemWithHttpInfo(itemID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = getItemRequestConfig(itemID = itemID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun getItemRequestConfig(itemID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/items/{itemID}".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun getItemPurchase(itemID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : PurchaseBlock { + val localVarResponse = getItemPurchaseWithHttpInfo(itemID = itemID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as PurchaseBlock + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun getItemPurchaseWithHttpInfo(itemID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = getItemPurchaseRequestConfig(itemID = itemID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun getItemPurchaseRequestConfig(itemID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/items/{itemID}/purchase".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun getItemSale(itemID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : SaleBlock { + val localVarResponse = getItemSaleWithHttpInfo(itemID = itemID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as SaleBlock + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun getItemSaleWithHttpInfo(itemID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = getItemSaleRequestConfig(itemID = itemID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun getItemSaleRequestConfig(itemID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/items/{itemID}/sale".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun getItemWarranty(itemID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : WarrantyBlock { + val localVarResponse = getItemWarrantyWithHttpInfo(itemID = itemID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as WarrantyBlock + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun getItemWarrantyWithHttpInfo(itemID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = getItemWarrantyRequestConfig(itemID = itemID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun getItemWarrantyRequestConfig(itemID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/items/{itemID}/warranty".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun listItemAttachments(itemID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : AttachmentListResponse { + val localVarResponse = listItemAttachmentsWithHttpInfo(itemID = itemID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as AttachmentListResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun listItemAttachmentsWithHttpInfo(itemID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = listItemAttachmentsRequestConfig(itemID = itemID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun listItemAttachmentsRequestConfig(itemID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/items/{itemID}/attachments".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun listItemCustomFields(itemID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : ItemCustomFieldListResponse { + val localVarResponse = listItemCustomFieldsWithHttpInfo(itemID = itemID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as ItemCustomFieldListResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun listItemCustomFieldsWithHttpInfo(itemID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = listItemCustomFieldsRequestConfig(itemID = itemID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun listItemCustomFieldsRequestConfig(itemID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/items/{itemID}/custom-fields".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun listItemIdentifications(itemID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : IdentificationListResponse { + val localVarResponse = listItemIdentificationsWithHttpInfo(itemID = itemID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as IdentificationListResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun listItemIdentificationsWithHttpInfo(itemID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = listItemIdentificationsRequestConfig(itemID = itemID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun listItemIdentificationsRequestConfig(itemID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/items/{itemID}/identifications".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun listItemLabels(itemID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : LabelListResponse { + val localVarResponse = listItemLabelsWithHttpInfo(itemID = itemID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as LabelListResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun listItemLabelsWithHttpInfo(itemID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = listItemLabelsRequestConfig(itemID = itemID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun listItemLabelsRequestConfig(itemID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/items/{itemID}/labels".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun listItemStockAdjustments(itemID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : StockAdjustmentListResponse { + val localVarResponse = listItemStockAdjustmentsWithHttpInfo(itemID = itemID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as StockAdjustmentListResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun listItemStockAdjustmentsWithHttpInfo(itemID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = listItemStockAdjustmentsRequestConfig(itemID = itemID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun listItemStockAdjustmentsRequestConfig(itemID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/items/{itemID}/stock-adjustments".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + enum class WarrantyStatusListItems(val value: kotlin.String) { + @SerialName(value = "none") None("none"), + @SerialName(value = "any") Any("any"), + @SerialName(value = "active") Active("active"), + @SerialName(value = "expired") Expired("expired"), + @SerialName(value = "lifetime") Lifetime("lifetime"); + + override fun toString(): kotlin.String = "$value" + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun listItems(q: kotlin.String? = null, locationId: kotlin.String? = null, descendants: kotlin.Boolean? = false, labelId: kotlin.collections.List? = null, customField: kotlin.collections.List? = null, warrantyStatus: WarrantyStatusListItems? = null, createdFrom: kotlin.Long? = null, createdTo: kotlin.Long? = null, updatedFrom: kotlin.Long? = null, updatedTo: kotlin.Long? = null, sort: kotlin.String? = null, limit: kotlin.Int? = 50, offset: kotlin.Int? = 0, xHHOClientVersion: kotlin.String? = null) : ItemListResponse { + val localVarResponse = listItemsWithHttpInfo(q = q, locationId = locationId, descendants = descendants, labelId = labelId, customField = customField, warrantyStatus = warrantyStatus, createdFrom = createdFrom, createdTo = createdTo, updatedFrom = updatedFrom, updatedTo = updatedTo, sort = sort, limit = limit, offset = offset, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as ItemListResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun listItemsWithHttpInfo(q: kotlin.String?, locationId: kotlin.String?, descendants: kotlin.Boolean?, labelId: kotlin.collections.List?, customField: kotlin.collections.List?, warrantyStatus: WarrantyStatusListItems?, createdFrom: kotlin.Long?, createdTo: kotlin.Long?, updatedFrom: kotlin.Long?, updatedTo: kotlin.Long?, sort: kotlin.String?, limit: kotlin.Int?, offset: kotlin.Int?, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = listItemsRequestConfig(q = q, locationId = locationId, descendants = descendants, labelId = labelId, customField = customField, warrantyStatus = warrantyStatus, createdFrom = createdFrom, createdTo = createdTo, updatedFrom = updatedFrom, updatedTo = updatedTo, sort = sort, limit = limit, offset = offset, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun listItemsRequestConfig(q: kotlin.String?, locationId: kotlin.String?, descendants: kotlin.Boolean?, labelId: kotlin.collections.List?, customField: kotlin.collections.List?, warrantyStatus: WarrantyStatusListItems?, createdFrom: kotlin.Long?, createdTo: kotlin.Long?, updatedFrom: kotlin.Long?, updatedTo: kotlin.Long?, sort: kotlin.String?, limit: kotlin.Int?, offset: kotlin.Int?, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf>() + .apply { + if (q != null) { + put("q", listOf(q.toString())) + } + if (locationId != null) { + put("location_id", listOf(locationId.toString())) + } + if (descendants != null) { + put("descendants", listOf(descendants.toString())) + } + if (labelId != null) { + put("label_id", toMultiValue(labelId.toList(), "multi")) + } + if (customField != null) { + put("custom_field", toMultiValue(customField.toList(), "multi")) + } + if (warrantyStatus != null) { + put("warranty_status", listOf(warrantyStatus.value)) + } + if (createdFrom != null) { + put("created_from", listOf(createdFrom.toString())) + } + if (createdTo != null) { + put("created_to", listOf(createdTo.toString())) + } + if (updatedFrom != null) { + put("updated_from", listOf(updatedFrom.toString())) + } + if (updatedTo != null) { + put("updated_to", listOf(updatedTo.toString())) + } + if (sort != null) { + put("sort", listOf(sort.toString())) + } + if (limit != null) { + put("limit", listOf(limit.toString())) + } + if (offset != null) { + put("offset", listOf(offset.toString())) + } + } + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/items", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun updateItem(itemID: kotlin.String, itemUpdateRequest: ItemUpdateRequest, xHHOClientVersion: kotlin.String? = null) : Item { + val localVarResponse = updateItemWithHttpInfo(itemID = itemID, itemUpdateRequest = itemUpdateRequest, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as Item + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun updateItemWithHttpInfo(itemID: kotlin.String, itemUpdateRequest: ItemUpdateRequest, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = updateItemRequestConfig(itemID = itemID, itemUpdateRequest = itemUpdateRequest, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun updateItemRequestConfig(itemID: kotlin.String, itemUpdateRequest: ItemUpdateRequest, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = itemUpdateRequest + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.PUT, + path = "/items/{itemID}".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun updateItemCustomField(itemID: kotlin.String, customFieldID: kotlin.String, itemCustomFieldUpdateRequest: ItemCustomFieldUpdateRequest, xHHOClientVersion: kotlin.String? = null) : ItemCustomField { + val localVarResponse = updateItemCustomFieldWithHttpInfo(itemID = itemID, customFieldID = customFieldID, itemCustomFieldUpdateRequest = itemCustomFieldUpdateRequest, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as ItemCustomField + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun updateItemCustomFieldWithHttpInfo(itemID: kotlin.String, customFieldID: kotlin.String, itemCustomFieldUpdateRequest: ItemCustomFieldUpdateRequest, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = updateItemCustomFieldRequestConfig(itemID = itemID, customFieldID = customFieldID, itemCustomFieldUpdateRequest = itemCustomFieldUpdateRequest, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun updateItemCustomFieldRequestConfig(itemID: kotlin.String, customFieldID: kotlin.String, itemCustomFieldUpdateRequest: ItemCustomFieldUpdateRequest, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = itemCustomFieldUpdateRequest + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.PUT, + path = "/items/{itemID}/custom-fields/{customFieldID}".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())).replace("{"+"customFieldID"+"}", encodeURIComponent(customFieldID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun updateItemIdentification(itemID: kotlin.String, identificationID: kotlin.String, identificationUpdateRequest: IdentificationUpdateRequest, xHHOClientVersion: kotlin.String? = null) : Identification { + val localVarResponse = updateItemIdentificationWithHttpInfo(itemID = itemID, identificationID = identificationID, identificationUpdateRequest = identificationUpdateRequest, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as Identification + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun updateItemIdentificationWithHttpInfo(itemID: kotlin.String, identificationID: kotlin.String, identificationUpdateRequest: IdentificationUpdateRequest, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = updateItemIdentificationRequestConfig(itemID = itemID, identificationID = identificationID, identificationUpdateRequest = identificationUpdateRequest, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun updateItemIdentificationRequestConfig(itemID: kotlin.String, identificationID: kotlin.String, identificationUpdateRequest: IdentificationUpdateRequest, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = identificationUpdateRequest + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.PUT, + path = "/items/{itemID}/identifications/{identificationID}".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())).replace("{"+"identificationID"+"}", encodeURIComponent(identificationID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun updateItemPurchase(itemID: kotlin.String, purchaseUpdateRequest: PurchaseUpdateRequest, xHHOClientVersion: kotlin.String? = null) : PurchaseBlock { + val localVarResponse = updateItemPurchaseWithHttpInfo(itemID = itemID, purchaseUpdateRequest = purchaseUpdateRequest, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as PurchaseBlock + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun updateItemPurchaseWithHttpInfo(itemID: kotlin.String, purchaseUpdateRequest: PurchaseUpdateRequest, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = updateItemPurchaseRequestConfig(itemID = itemID, purchaseUpdateRequest = purchaseUpdateRequest, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun updateItemPurchaseRequestConfig(itemID: kotlin.String, purchaseUpdateRequest: PurchaseUpdateRequest, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = purchaseUpdateRequest + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.PUT, + path = "/items/{itemID}/purchase".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun updateItemSale(itemID: kotlin.String, saleUpdateRequest: SaleUpdateRequest, xHHOClientVersion: kotlin.String? = null) : SaleBlock { + val localVarResponse = updateItemSaleWithHttpInfo(itemID = itemID, saleUpdateRequest = saleUpdateRequest, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as SaleBlock + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun updateItemSaleWithHttpInfo(itemID: kotlin.String, saleUpdateRequest: SaleUpdateRequest, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = updateItemSaleRequestConfig(itemID = itemID, saleUpdateRequest = saleUpdateRequest, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun updateItemSaleRequestConfig(itemID: kotlin.String, saleUpdateRequest: SaleUpdateRequest, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = saleUpdateRequest + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.PUT, + path = "/items/{itemID}/sale".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun updateItemWarranty(itemID: kotlin.String, warrantyUpdateRequest: WarrantyUpdateRequest, xHHOClientVersion: kotlin.String? = null) : WarrantyBlock { + val localVarResponse = updateItemWarrantyWithHttpInfo(itemID = itemID, warrantyUpdateRequest = warrantyUpdateRequest, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as WarrantyBlock + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun updateItemWarrantyWithHttpInfo(itemID: kotlin.String, warrantyUpdateRequest: WarrantyUpdateRequest, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = updateItemWarrantyRequestConfig(itemID = itemID, warrantyUpdateRequest = warrantyUpdateRequest, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun updateItemWarrantyRequestConfig(itemID: kotlin.String, warrantyUpdateRequest: WarrantyUpdateRequest, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = warrantyUpdateRequest + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.PUT, + path = "/items/{itemID}/warranty".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + enum class CategoryUploadItemAttachment(val value: kotlin.String) { + @SerialName(value = "image") Image("image"), + @SerialName(value = "manual") Manual("manual"), + @SerialName(value = "warranty") Warranty("warranty"), + @SerialName(value = "receipt") Receipt("receipt"), + @SerialName(value = "general") General("general"); + + override fun toString(): kotlin.String = "$value" + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun uploadItemAttachment(itemID: kotlin.String, category: CategoryUploadItemAttachment, file: java.io.File, xHHOClientVersion: kotlin.String? = null) : Attachment { + val localVarResponse = uploadItemAttachmentWithHttpInfo(itemID = itemID, category = category, file = file, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as Attachment + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun uploadItemAttachmentWithHttpInfo(itemID: kotlin.String, category: CategoryUploadItemAttachment, file: java.io.File, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = uploadItemAttachmentRequestConfig(itemID = itemID, category = category, file = file, xHHOClientVersion = xHHOClientVersion) + + return request>, Attachment>( + localVariableConfig + ) + } + + fun uploadItemAttachmentRequestConfig(itemID: kotlin.String, category: CategoryUploadItemAttachment, file: java.io.File, xHHOClientVersion: kotlin.String?) : RequestConfig>> { + val localVariableBody = mapOf( + "category" to PartConfig(body = category.value, headers = mutableMapOf()), + "file" to PartConfig(body = file, headers = mutableMapOf("Content-Type" to "*/*")),) + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf("Content-Type" to "multipart/form-data") + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.POST, + path = "/items/{itemID}/attachments".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + private fun encodeURIComponent(uriComponent: kotlin.String): kotlin.String = + HttpUrl.Builder().scheme("http").host("localhost").addPathSegment(uriComponent).build().encodedPathSegments[0] +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/LabelsApi.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/LabelsApi.kt new file mode 100644 index 0000000..8351a3e --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/LabelsApi.kt @@ -0,0 +1,382 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.apis + +import java.io.IOException +import okhttp3.Call +import okhttp3.HttpUrl + +import dev.hho.android.data.apiclient.generated.models.Label +import dev.hho.android.data.apiclient.generated.models.LabelCreateRequest +import dev.hho.android.data.apiclient.generated.models.LabelListResponse +import dev.hho.android.data.apiclient.generated.models.LabelUpdateRequest +import dev.hho.android.data.apiclient.generated.models.Problem +import dev.hho.android.data.apiclient.generated.models.UpgradeRequiredProblem + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +import dev.hho.android.data.apiclient.generated.infrastructure.ApiClient +import dev.hho.android.data.apiclient.generated.infrastructure.ApiResponse +import dev.hho.android.data.apiclient.generated.infrastructure.ClientException +import dev.hho.android.data.apiclient.generated.infrastructure.ClientError +import dev.hho.android.data.apiclient.generated.infrastructure.ServerException +import dev.hho.android.data.apiclient.generated.infrastructure.ServerError +import dev.hho.android.data.apiclient.generated.infrastructure.MultiValueMap +import dev.hho.android.data.apiclient.generated.infrastructure.PartConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestMethod +import dev.hho.android.data.apiclient.generated.infrastructure.ResponseType +import dev.hho.android.data.apiclient.generated.infrastructure.Success +import dev.hho.android.data.apiclient.generated.infrastructure.toMultiValue +import dev.hho.android.data.apiclient.generated.infrastructure.Serializer + +open class LabelsApi(basePath: kotlin.String = defaultBasePath, client: Call.Factory = ApiClient.defaultClient) : ApiClient(basePath, client) { + companion object { + @JvmStatic + val defaultBasePath: String by lazy { + System.getProperties().getProperty(ApiClient.BASE_URL_KEY, "/api/v1") + } + } + + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun attachItemLabel(itemID: kotlin.String, labelID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : Unit { + val localVarResponse = attachItemLabelWithHttpInfo(itemID = itemID, labelID = labelID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Throws(IllegalStateException::class, IOException::class) + fun attachItemLabelWithHttpInfo(itemID: kotlin.String, labelID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = attachItemLabelRequestConfig(itemID = itemID, labelID = labelID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun attachItemLabelRequestConfig(itemID: kotlin.String, labelID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.PUT, + path = "/items/{itemID}/labels/{labelID}".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())).replace("{"+"labelID"+"}", encodeURIComponent(labelID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun createLabel(labelCreateRequest: LabelCreateRequest, xHHOClientVersion: kotlin.String? = null) : Label { + val localVarResponse = createLabelWithHttpInfo(labelCreateRequest = labelCreateRequest, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as Label + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun createLabelWithHttpInfo(labelCreateRequest: LabelCreateRequest, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = createLabelRequestConfig(labelCreateRequest = labelCreateRequest, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun createLabelRequestConfig(labelCreateRequest: LabelCreateRequest, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = labelCreateRequest + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.POST, + path = "/labels", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun deleteLabel(labelID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : Unit { + val localVarResponse = deleteLabelWithHttpInfo(labelID = labelID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Throws(IllegalStateException::class, IOException::class) + fun deleteLabelWithHttpInfo(labelID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = deleteLabelRequestConfig(labelID = labelID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun deleteLabelRequestConfig(labelID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.DELETE, + path = "/labels/{labelID}".replace("{"+"labelID"+"}", encodeURIComponent(labelID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun detachItemLabel(itemID: kotlin.String, labelID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : Unit { + val localVarResponse = detachItemLabelWithHttpInfo(itemID = itemID, labelID = labelID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Throws(IllegalStateException::class, IOException::class) + fun detachItemLabelWithHttpInfo(itemID: kotlin.String, labelID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = detachItemLabelRequestConfig(itemID = itemID, labelID = labelID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun detachItemLabelRequestConfig(itemID: kotlin.String, labelID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.DELETE, + path = "/items/{itemID}/labels/{labelID}".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())).replace("{"+"labelID"+"}", encodeURIComponent(labelID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun listItemLabels(itemID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : LabelListResponse { + val localVarResponse = listItemLabelsWithHttpInfo(itemID = itemID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as LabelListResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun listItemLabelsWithHttpInfo(itemID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = listItemLabelsRequestConfig(itemID = itemID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun listItemLabelsRequestConfig(itemID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/items/{itemID}/labels".replace("{"+"itemID"+"}", encodeURIComponent(itemID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun listLabels(xHHOClientVersion: kotlin.String? = null) : LabelListResponse { + val localVarResponse = listLabelsWithHttpInfo(xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as LabelListResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun listLabelsWithHttpInfo(xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = listLabelsRequestConfig(xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun listLabelsRequestConfig(xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/labels", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun updateLabel(labelID: kotlin.String, labelUpdateRequest: LabelUpdateRequest, xHHOClientVersion: kotlin.String? = null) : Label { + val localVarResponse = updateLabelWithHttpInfo(labelID = labelID, labelUpdateRequest = labelUpdateRequest, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as Label + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun updateLabelWithHttpInfo(labelID: kotlin.String, labelUpdateRequest: LabelUpdateRequest, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = updateLabelRequestConfig(labelID = labelID, labelUpdateRequest = labelUpdateRequest, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun updateLabelRequestConfig(labelID: kotlin.String, labelUpdateRequest: LabelUpdateRequest, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = labelUpdateRequest + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.PUT, + path = "/labels/{labelID}".replace("{"+"labelID"+"}", encodeURIComponent(labelID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + private fun encodeURIComponent(uriComponent: kotlin.String): kotlin.String = + HttpUrl.Builder().scheme("http").host("localhost").addPathSegment(uriComponent).build().encodedPathSegments[0] +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/LabelsQrApi.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/LabelsQrApi.kt new file mode 100644 index 0000000..a4d2dfb --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/LabelsQrApi.kt @@ -0,0 +1,147 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.apis + +import java.io.IOException +import okhttp3.Call +import okhttp3.HttpUrl + +import dev.hho.android.data.apiclient.generated.models.LabelsQRBatchRequest +import dev.hho.android.data.apiclient.generated.models.LabelsQRBatchResponse +import dev.hho.android.data.apiclient.generated.models.Problem +import dev.hho.android.data.apiclient.generated.models.UpgradeRequiredProblem + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +import dev.hho.android.data.apiclient.generated.infrastructure.ApiClient +import dev.hho.android.data.apiclient.generated.infrastructure.ApiResponse +import dev.hho.android.data.apiclient.generated.infrastructure.ClientException +import dev.hho.android.data.apiclient.generated.infrastructure.ClientError +import dev.hho.android.data.apiclient.generated.infrastructure.ServerException +import dev.hho.android.data.apiclient.generated.infrastructure.ServerError +import dev.hho.android.data.apiclient.generated.infrastructure.MultiValueMap +import dev.hho.android.data.apiclient.generated.infrastructure.PartConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestMethod +import dev.hho.android.data.apiclient.generated.infrastructure.ResponseType +import dev.hho.android.data.apiclient.generated.infrastructure.Success +import dev.hho.android.data.apiclient.generated.infrastructure.toMultiValue +import dev.hho.android.data.apiclient.generated.infrastructure.Serializer + +open class LabelsQrApi(basePath: kotlin.String = defaultBasePath, client: Call.Factory = ApiClient.defaultClient) : ApiClient(basePath, client) { + companion object { + @JvmStatic + val defaultBasePath: String by lazy { + System.getProperties().getProperty(ApiClient.BASE_URL_KEY, "/api/v1") + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun createLabelsQRBatch(labelsQRBatchRequest: LabelsQRBatchRequest, xHHOClientVersion: kotlin.String? = null) : LabelsQRBatchResponse { + val localVarResponse = createLabelsQRBatchWithHttpInfo(labelsQRBatchRequest = labelsQRBatchRequest, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as LabelsQRBatchResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun createLabelsQRBatchWithHttpInfo(labelsQRBatchRequest: LabelsQRBatchRequest, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = createLabelsQRBatchRequestConfig(labelsQRBatchRequest = labelsQRBatchRequest, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun createLabelsQRBatchRequestConfig(labelsQRBatchRequest: LabelsQRBatchRequest, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = labelsQRBatchRequest + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.POST, + path = "/labels/qr/batch", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun resolveItemToken(token: kotlin.String) : Unit { + val localVarResponse = resolveItemTokenWithHttpInfo(token = token) + + return when (localVarResponse.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Throws(IllegalStateException::class, IOException::class) + fun resolveItemTokenWithHttpInfo(token: kotlin.String) : ApiResponse { + val localVariableConfig = resolveItemTokenRequestConfig(token = token) + + return request( + localVariableConfig + ) + } + + fun resolveItemTokenRequestConfig(token: kotlin.String) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/problem+json" + + return RequestConfig( + method = RequestMethod.GET, + path = "/i/{token}".replace("{"+"token"+"}", encodeURIComponent(token.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = false, + body = localVariableBody + ) + } + + private fun encodeURIComponent(uriComponent: kotlin.String): kotlin.String = + HttpUrl.Builder().scheme("http").host("localhost").addPathSegment(uriComponent).build().encodedPathSegments[0] +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/LocationsApi.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/LocationsApi.kt new file mode 100644 index 0000000..17c26e9 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/LocationsApi.kt @@ -0,0 +1,346 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.apis + +import java.io.IOException +import okhttp3.Call +import okhttp3.HttpUrl + +import dev.hho.android.data.apiclient.generated.models.Location +import dev.hho.android.data.apiclient.generated.models.LocationCreateRequest +import dev.hho.android.data.apiclient.generated.models.LocationListResponse +import dev.hho.android.data.apiclient.generated.models.LocationNotEmptyProblem +import dev.hho.android.data.apiclient.generated.models.LocationTreeResponse +import dev.hho.android.data.apiclient.generated.models.LocationUpdateRequest +import dev.hho.android.data.apiclient.generated.models.Problem +import dev.hho.android.data.apiclient.generated.models.UpgradeRequiredProblem + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +import dev.hho.android.data.apiclient.generated.infrastructure.ApiClient +import dev.hho.android.data.apiclient.generated.infrastructure.ApiResponse +import dev.hho.android.data.apiclient.generated.infrastructure.ClientException +import dev.hho.android.data.apiclient.generated.infrastructure.ClientError +import dev.hho.android.data.apiclient.generated.infrastructure.ServerException +import dev.hho.android.data.apiclient.generated.infrastructure.ServerError +import dev.hho.android.data.apiclient.generated.infrastructure.MultiValueMap +import dev.hho.android.data.apiclient.generated.infrastructure.PartConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestMethod +import dev.hho.android.data.apiclient.generated.infrastructure.ResponseType +import dev.hho.android.data.apiclient.generated.infrastructure.Success +import dev.hho.android.data.apiclient.generated.infrastructure.toMultiValue +import dev.hho.android.data.apiclient.generated.infrastructure.Serializer + +open class LocationsApi(basePath: kotlin.String = defaultBasePath, client: Call.Factory = ApiClient.defaultClient) : ApiClient(basePath, client) { + companion object { + @JvmStatic + val defaultBasePath: String by lazy { + System.getProperties().getProperty(ApiClient.BASE_URL_KEY, "/api/v1") + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun createLocation(locationCreateRequest: LocationCreateRequest, xHHOClientVersion: kotlin.String? = null) : Location { + val localVarResponse = createLocationWithHttpInfo(locationCreateRequest = locationCreateRequest, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as Location + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun createLocationWithHttpInfo(locationCreateRequest: LocationCreateRequest, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = createLocationRequestConfig(locationCreateRequest = locationCreateRequest, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun createLocationRequestConfig(locationCreateRequest: LocationCreateRequest, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = locationCreateRequest + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.POST, + path = "/locations", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun deleteLocation(locationID: kotlin.String, reassignTo: kotlin.String? = null, xHHOClientVersion: kotlin.String? = null) : Unit { + val localVarResponse = deleteLocationWithHttpInfo(locationID = locationID, reassignTo = reassignTo, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> Unit + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Throws(IllegalStateException::class, IOException::class) + fun deleteLocationWithHttpInfo(locationID: kotlin.String, reassignTo: kotlin.String?, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = deleteLocationRequestConfig(locationID = locationID, reassignTo = reassignTo, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun deleteLocationRequestConfig(locationID: kotlin.String, reassignTo: kotlin.String?, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf>() + .apply { + if (reassignTo != null) { + put("reassign_to", listOf(reassignTo.toString())) + } + } + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.DELETE, + path = "/locations/{locationID}".replace("{"+"locationID"+"}", encodeURIComponent(locationID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun getLocation(locationID: kotlin.String, xHHOClientVersion: kotlin.String? = null) : Location { + val localVarResponse = getLocationWithHttpInfo(locationID = locationID, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as Location + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun getLocationWithHttpInfo(locationID: kotlin.String, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = getLocationRequestConfig(locationID = locationID, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun getLocationRequestConfig(locationID: kotlin.String, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/locations/{locationID}".replace("{"+"locationID"+"}", encodeURIComponent(locationID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun getLocationTree(xHHOClientVersion: kotlin.String? = null) : LocationTreeResponse { + val localVarResponse = getLocationTreeWithHttpInfo(xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as LocationTreeResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun getLocationTreeWithHttpInfo(xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = getLocationTreeRequestConfig(xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun getLocationTreeRequestConfig(xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/locations/tree", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun listLocations(xHHOClientVersion: kotlin.String? = null) : LocationListResponse { + val localVarResponse = listLocationsWithHttpInfo(xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as LocationListResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun listLocationsWithHttpInfo(xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = listLocationsRequestConfig(xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun listLocationsRequestConfig(xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/locations", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun updateLocation(locationID: kotlin.String, locationUpdateRequest: LocationUpdateRequest, xHHOClientVersion: kotlin.String? = null) : Location { + val localVarResponse = updateLocationWithHttpInfo(locationID = locationID, locationUpdateRequest = locationUpdateRequest, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as Location + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun updateLocationWithHttpInfo(locationID: kotlin.String, locationUpdateRequest: LocationUpdateRequest, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = updateLocationRequestConfig(locationID = locationID, locationUpdateRequest = locationUpdateRequest, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun updateLocationRequestConfig(locationID: kotlin.String, locationUpdateRequest: LocationUpdateRequest, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = locationUpdateRequest + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.PUT, + path = "/locations/{locationID}".replace("{"+"locationID"+"}", encodeURIComponent(locationID.toString())), + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + private fun encodeURIComponent(uriComponent: kotlin.String): kotlin.String = + HttpUrl.Builder().scheme("http").host("localhost").addPathSegment(uriComponent).build().encodedPathSegments[0] +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/MetaApi.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/MetaApi.kt new file mode 100644 index 0000000..684befb --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/MetaApi.kt @@ -0,0 +1,100 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.apis + +import java.io.IOException +import okhttp3.Call +import okhttp3.HttpUrl + +import dev.hho.android.data.apiclient.generated.models.Problem +import dev.hho.android.data.apiclient.generated.models.UpgradeRequiredProblem + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +import dev.hho.android.data.apiclient.generated.infrastructure.ApiClient +import dev.hho.android.data.apiclient.generated.infrastructure.ApiResponse +import dev.hho.android.data.apiclient.generated.infrastructure.ClientException +import dev.hho.android.data.apiclient.generated.infrastructure.ClientError +import dev.hho.android.data.apiclient.generated.infrastructure.ServerException +import dev.hho.android.data.apiclient.generated.infrastructure.ServerError +import dev.hho.android.data.apiclient.generated.infrastructure.MultiValueMap +import dev.hho.android.data.apiclient.generated.infrastructure.PartConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestMethod +import dev.hho.android.data.apiclient.generated.infrastructure.ResponseType +import dev.hho.android.data.apiclient.generated.infrastructure.Success +import dev.hho.android.data.apiclient.generated.infrastructure.toMultiValue +import dev.hho.android.data.apiclient.generated.infrastructure.Serializer + +open class MetaApi(basePath: kotlin.String = defaultBasePath, client: Call.Factory = ApiClient.defaultClient) : ApiClient(basePath, client) { + companion object { + @JvmStatic + val defaultBasePath: String by lazy { + System.getProperties().getProperty(ApiClient.BASE_URL_KEY, "/api/v1") + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun getOpenAPISpec(xHHOClientVersion: kotlin.String? = null) : kotlin.String { + val localVarResponse = getOpenAPISpecWithHttpInfo(xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as kotlin.String + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun getOpenAPISpecWithHttpInfo(xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = getOpenAPISpecRequestConfig(xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun getOpenAPISpecRequestConfig(xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/openapi.yaml", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = false, + body = localVariableBody + ) + } + + private fun encodeURIComponent(uriComponent: kotlin.String): kotlin.String = + HttpUrl.Builder().scheme("http").host("localhost").addPathSegment(uriComponent).build().encodedPathSegments[0] +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/ReportsApi.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/ReportsApi.kt new file mode 100644 index 0000000..979c038 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/ReportsApi.kt @@ -0,0 +1,306 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.apis + +import java.io.IOException +import okhttp3.Call +import okhttp3.HttpUrl + +import dev.hho.android.data.apiclient.generated.models.Problem +import dev.hho.android.data.apiclient.generated.models.ReportItemCountByLocationResponse +import dev.hho.android.data.apiclient.generated.models.ReportPurchasesResponse +import dev.hho.android.data.apiclient.generated.models.ReportValuationResponse +import dev.hho.android.data.apiclient.generated.models.ReportWarrantyExpiringResponse +import dev.hho.android.data.apiclient.generated.models.UpgradeRequiredProblem + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +import dev.hho.android.data.apiclient.generated.infrastructure.ApiClient +import dev.hho.android.data.apiclient.generated.infrastructure.ApiResponse +import dev.hho.android.data.apiclient.generated.infrastructure.ClientException +import dev.hho.android.data.apiclient.generated.infrastructure.ClientError +import dev.hho.android.data.apiclient.generated.infrastructure.ServerException +import dev.hho.android.data.apiclient.generated.infrastructure.ServerError +import dev.hho.android.data.apiclient.generated.infrastructure.MultiValueMap +import dev.hho.android.data.apiclient.generated.infrastructure.PartConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestMethod +import dev.hho.android.data.apiclient.generated.infrastructure.ResponseType +import dev.hho.android.data.apiclient.generated.infrastructure.Success +import dev.hho.android.data.apiclient.generated.infrastructure.toMultiValue +import dev.hho.android.data.apiclient.generated.infrastructure.Serializer + +open class ReportsApi(basePath: kotlin.String = defaultBasePath, client: Call.Factory = ApiClient.defaultClient) : ApiClient(basePath, client) { + companion object { + @JvmStatic + val defaultBasePath: String by lazy { + System.getProperties().getProperty(ApiClient.BASE_URL_KEY, "/api/v1") + } + } + + enum class FormatGetReportItemCountByLocation(val value: kotlin.String) { + @SerialName(value = "json") Json("json"), + @SerialName(value = "csv") Csv("csv"); + + override fun toString(): kotlin.String = "$value" + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun getReportItemCountByLocation(format: FormatGetReportItemCountByLocation? = FormatGetReportItemCountByLocation.Json, xHHOClientVersion: kotlin.String? = null) : ReportItemCountByLocationResponse { + val localVarResponse = getReportItemCountByLocationWithHttpInfo(format = format, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as ReportItemCountByLocationResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun getReportItemCountByLocationWithHttpInfo(format: FormatGetReportItemCountByLocation?, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = getReportItemCountByLocationRequestConfig(format = format, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun getReportItemCountByLocationRequestConfig(format: FormatGetReportItemCountByLocation?, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf>() + .apply { + if (format != null) { + put("format", listOf(format.value)) + } + } + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/reports/item-count-by-location", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + enum class FormatGetReportPurchases(val value: kotlin.String) { + @SerialName(value = "json") Json("json"), + @SerialName(value = "csv") Csv("csv"); + + override fun toString(): kotlin.String = "$value" + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun getReportPurchases(from: kotlin.String, to: kotlin.String, format: FormatGetReportPurchases? = FormatGetReportPurchases.Json, xHHOClientVersion: kotlin.String? = null) : ReportPurchasesResponse { + val localVarResponse = getReportPurchasesWithHttpInfo(from = from, to = to, format = format, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as ReportPurchasesResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun getReportPurchasesWithHttpInfo(from: kotlin.String, to: kotlin.String, format: FormatGetReportPurchases?, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = getReportPurchasesRequestConfig(from = from, to = to, format = format, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun getReportPurchasesRequestConfig(from: kotlin.String, to: kotlin.String, format: FormatGetReportPurchases?, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf>() + .apply { + if (format != null) { + put("format", listOf(format.value)) + } + put("from", listOf(from.toString())) + put("to", listOf(to.toString())) + } + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/reports/purchases", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + enum class GroupByGetReportValuation(val value: kotlin.String) { + @SerialName(value = "location") Location("location"), + @SerialName(value = "label") Label("label"); + + override fun toString(): kotlin.String = "$value" + } + + enum class FormatGetReportValuation(val value: kotlin.String) { + @SerialName(value = "json") Json("json"), + @SerialName(value = "csv") Csv("csv"); + + override fun toString(): kotlin.String = "$value" + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun getReportValuation(groupBy: GroupByGetReportValuation, format: FormatGetReportValuation? = FormatGetReportValuation.Json, xHHOClientVersion: kotlin.String? = null) : ReportValuationResponse { + val localVarResponse = getReportValuationWithHttpInfo(groupBy = groupBy, format = format, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as ReportValuationResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun getReportValuationWithHttpInfo(groupBy: GroupByGetReportValuation, format: FormatGetReportValuation?, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = getReportValuationRequestConfig(groupBy = groupBy, format = format, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun getReportValuationRequestConfig(groupBy: GroupByGetReportValuation, format: FormatGetReportValuation?, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf>() + .apply { + if (format != null) { + put("format", listOf(format.value)) + } + put("group_by", listOf(groupBy.value)) + } + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/reports/valuation", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + enum class FormatGetReportWarrantyExpiring(val value: kotlin.String) { + @SerialName(value = "json") Json("json"), + @SerialName(value = "csv") Csv("csv"); + + override fun toString(): kotlin.String = "$value" + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun getReportWarrantyExpiring(format: FormatGetReportWarrantyExpiring? = FormatGetReportWarrantyExpiring.Json, withinDays: kotlin.Int? = 30, xHHOClientVersion: kotlin.String? = null) : ReportWarrantyExpiringResponse { + val localVarResponse = getReportWarrantyExpiringWithHttpInfo(format = format, withinDays = withinDays, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as ReportWarrantyExpiringResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun getReportWarrantyExpiringWithHttpInfo(format: FormatGetReportWarrantyExpiring?, withinDays: kotlin.Int?, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = getReportWarrantyExpiringRequestConfig(format = format, withinDays = withinDays, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun getReportWarrantyExpiringRequestConfig(format: FormatGetReportWarrantyExpiring?, withinDays: kotlin.Int?, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf>() + .apply { + if (format != null) { + put("format", listOf(format.value)) + } + if (withinDays != null) { + put("within_days", listOf(withinDays.toString())) + } + } + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/reports/warranty-expiring", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + private fun encodeURIComponent(uriComponent: kotlin.String): kotlin.String = + HttpUrl.Builder().scheme("http").host("localhost").addPathSegment(uriComponent).build().encodedPathSegments[0] +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/StatusApi.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/StatusApi.kt new file mode 100644 index 0000000..1bae151 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/StatusApi.kt @@ -0,0 +1,101 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.apis + +import java.io.IOException +import okhttp3.Call +import okhttp3.HttpUrl + +import dev.hho.android.data.apiclient.generated.models.Problem +import dev.hho.android.data.apiclient.generated.models.StatusResponse +import dev.hho.android.data.apiclient.generated.models.UpgradeRequiredProblem + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +import dev.hho.android.data.apiclient.generated.infrastructure.ApiClient +import dev.hho.android.data.apiclient.generated.infrastructure.ApiResponse +import dev.hho.android.data.apiclient.generated.infrastructure.ClientException +import dev.hho.android.data.apiclient.generated.infrastructure.ClientError +import dev.hho.android.data.apiclient.generated.infrastructure.ServerException +import dev.hho.android.data.apiclient.generated.infrastructure.ServerError +import dev.hho.android.data.apiclient.generated.infrastructure.MultiValueMap +import dev.hho.android.data.apiclient.generated.infrastructure.PartConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestMethod +import dev.hho.android.data.apiclient.generated.infrastructure.ResponseType +import dev.hho.android.data.apiclient.generated.infrastructure.Success +import dev.hho.android.data.apiclient.generated.infrastructure.toMultiValue +import dev.hho.android.data.apiclient.generated.infrastructure.Serializer + +open class StatusApi(basePath: kotlin.String = defaultBasePath, client: Call.Factory = ApiClient.defaultClient) : ApiClient(basePath, client) { + companion object { + @JvmStatic + val defaultBasePath: String by lazy { + System.getProperties().getProperty(ApiClient.BASE_URL_KEY, "/api/v1") + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun getStatus(xHHOClientVersion: kotlin.String? = null) : StatusResponse { + val localVarResponse = getStatusWithHttpInfo(xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as StatusResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun getStatusWithHttpInfo(xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = getStatusRequestConfig(xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun getStatusRequestConfig(xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/status", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = false, + body = localVariableBody + ) + } + + private fun encodeURIComponent(uriComponent: kotlin.String): kotlin.String = + HttpUrl.Builder().scheme("http").host("localhost").addPathSegment(uriComponent).build().encodedPathSegments[0] +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/SyncApi.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/SyncApi.kt new file mode 100644 index 0000000..1bd7692 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/apis/SyncApi.kt @@ -0,0 +1,209 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.apis + +import java.io.IOException +import okhttp3.Call +import okhttp3.HttpUrl + +import dev.hho.android.data.apiclient.generated.models.Problem +import dev.hho.android.data.apiclient.generated.models.SyncConflictLogResponse +import dev.hho.android.data.apiclient.generated.models.SyncPullRequest +import dev.hho.android.data.apiclient.generated.models.SyncPullResponse +import dev.hho.android.data.apiclient.generated.models.SyncPushRequest +import dev.hho.android.data.apiclient.generated.models.SyncPushResponse +import dev.hho.android.data.apiclient.generated.models.UpgradeRequiredProblem + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +import dev.hho.android.data.apiclient.generated.infrastructure.ApiClient +import dev.hho.android.data.apiclient.generated.infrastructure.ApiResponse +import dev.hho.android.data.apiclient.generated.infrastructure.ClientException +import dev.hho.android.data.apiclient.generated.infrastructure.ClientError +import dev.hho.android.data.apiclient.generated.infrastructure.ServerException +import dev.hho.android.data.apiclient.generated.infrastructure.ServerError +import dev.hho.android.data.apiclient.generated.infrastructure.MultiValueMap +import dev.hho.android.data.apiclient.generated.infrastructure.PartConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestConfig +import dev.hho.android.data.apiclient.generated.infrastructure.RequestMethod +import dev.hho.android.data.apiclient.generated.infrastructure.ResponseType +import dev.hho.android.data.apiclient.generated.infrastructure.Success +import dev.hho.android.data.apiclient.generated.infrastructure.toMultiValue +import dev.hho.android.data.apiclient.generated.infrastructure.Serializer + +open class SyncApi(basePath: kotlin.String = defaultBasePath, client: Call.Factory = ApiClient.defaultClient) : ApiClient(basePath, client) { + companion object { + @JvmStatic + val defaultBasePath: String by lazy { + System.getProperties().getProperty(ApiClient.BASE_URL_KEY, "/api/v1") + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun listSyncConflicts(limit: kotlin.Int? = 50, after: kotlin.String? = null, xHHOClientVersion: kotlin.String? = null) : SyncConflictLogResponse { + val localVarResponse = listSyncConflictsWithHttpInfo(limit = limit, after = after, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as SyncConflictLogResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun listSyncConflictsWithHttpInfo(limit: kotlin.Int?, after: kotlin.String?, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = listSyncConflictsRequestConfig(limit = limit, after = after, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun listSyncConflictsRequestConfig(limit: kotlin.Int?, after: kotlin.String?, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = null + val localVariableQuery: MultiValueMap = mutableMapOf>() + .apply { + if (limit != null) { + put("limit", listOf(limit.toString())) + } + if (after != null) { + put("after", listOf(after.toString())) + } + } + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.GET, + path = "/sync/conflicts", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun syncPull(syncPullRequest: SyncPullRequest, xHHOClientVersion: kotlin.String? = null) : SyncPullResponse { + val localVarResponse = syncPullWithHttpInfo(syncPullRequest = syncPullRequest, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as SyncPullResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun syncPullWithHttpInfo(syncPullRequest: SyncPullRequest, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = syncPullRequestConfig(syncPullRequest = syncPullRequest, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun syncPullRequestConfig(syncPullRequest: SyncPullRequest, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = syncPullRequest + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.POST, + path = "/sync/pull", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class) + fun syncPush(syncPushRequest: SyncPushRequest, xHHOClientVersion: kotlin.String? = null) : SyncPushResponse { + val localVarResponse = syncPushWithHttpInfo(syncPushRequest = syncPushRequest, xHHOClientVersion = xHHOClientVersion) + + return when (localVarResponse.responseType) { + ResponseType.Success -> (localVarResponse as Success<*>).data as SyncPushResponse + ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.") + ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.") + ResponseType.ClientError -> { + val localVarError = localVarResponse as ClientError<*> + throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse) + } + ResponseType.ServerError -> { + val localVarError = localVarResponse as ServerError<*> + throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()} ${localVarError.body}", localVarError.statusCode, localVarResponse) + } + } + } + + @Suppress("UNCHECKED_CAST") + @Throws(IllegalStateException::class, IOException::class) + fun syncPushWithHttpInfo(syncPushRequest: SyncPushRequest, xHHOClientVersion: kotlin.String?) : ApiResponse { + val localVariableConfig = syncPushRequestConfig(syncPushRequest = syncPushRequest, xHHOClientVersion = xHHOClientVersion) + + return request( + localVariableConfig + ) + } + + fun syncPushRequestConfig(syncPushRequest: SyncPushRequest, xHHOClientVersion: kotlin.String?) : RequestConfig { + val localVariableBody = syncPushRequest + val localVariableQuery: MultiValueMap = mutableMapOf() + val localVariableHeaders: MutableMap = mutableMapOf() + localVariableHeaders["Content-Type"] = "application/json" + localVariableHeaders["Accept"] = "application/json, application/problem+json" + xHHOClientVersion?.apply { localVariableHeaders["X-HHO-Client-Version"] = this.toString() } + + return RequestConfig( + method = RequestMethod.POST, + path = "/sync/push", + query = localVariableQuery, + headers = localVariableHeaders, + requiresAuthentication = true, + body = localVariableBody + ) + } + + private fun encodeURIComponent(uriComponent: kotlin.String): kotlin.String = + HttpUrl.Builder().scheme("http").host("localhost").addPathSegment(uriComponent).build().encodedPathSegments[0] +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/ApiAbstractions.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/ApiAbstractions.kt new file mode 100644 index 0000000..4a32dcb --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/ApiAbstractions.kt @@ -0,0 +1,23 @@ +package dev.hho.android.data.apiclient.generated.infrastructure + +typealias MultiValueMap = MutableMap> + +fun collectionDelimiter(collectionFormat: String): String = when(collectionFormat) { + "csv" -> "," + "tsv" -> "\t" + "pipe" -> "|" + "space" -> " " + else -> "" +} + +val defaultMultiValueConverter: (item: Any?) -> String = { item -> "$item" } + +fun toMultiValue(items: Array, collectionFormat: String, map: (item: T) -> String = defaultMultiValueConverter): List + = toMultiValue(items.asIterable(), collectionFormat, map) + +fun toMultiValue(items: Iterable, collectionFormat: String, map: (item: T) -> String = defaultMultiValueConverter): List { + return when(collectionFormat) { + "multi" -> items.map(map) + else -> listOf(items.joinToString(separator = collectionDelimiter(collectionFormat), transform = map)) + } +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/ApiClient.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/ApiClient.kt new file mode 100644 index 0000000..e2fcd66 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/ApiClient.kt @@ -0,0 +1,411 @@ +package dev.hho.android.data.apiclient.generated.infrastructure + +import okhttp3.OkHttpClient +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.asRequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import okhttp3.FormBody +import okhttp3.HttpUrl.Companion.toHttpUrlOrNull +import okhttp3.ResponseBody +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.Request +import okhttp3.Headers +import okhttp3.Headers.Builder +import okhttp3.Headers.Companion.toHeaders +import okhttp3.MultipartBody +import okhttp3.Call +import okhttp3.Callback +import okhttp3.Response +import java.io.BufferedWriter +import java.io.File +import java.io.FileWriter +import java.io.IOException +import java.net.URLConnection +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.LocalTime +import java.time.OffsetDateTime +import java.time.OffsetTime +import java.util.Locale +import java.util.regex.Pattern +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.encodeToString + +val EMPTY_REQUEST: RequestBody = ByteArray(0).toRequestBody() + +open class ApiClient(val baseUrl: String, val client: Call.Factory = defaultClient) { + companion object { + protected const val CONTENT_TYPE: String = "Content-Type" + @Deprecated( + message = "Please use the capitalized constant `CONTENT_TYPE` instead.", + replaceWith = ReplaceWith("CONTENT_TYPE") + ) + protected const val ContentType: String = CONTENT_TYPE + + protected const val ACCEPT: String = "Accept" + @Deprecated( + message = "Please use the capitalized constant `ACCEPT` instead.", + replaceWith = ReplaceWith("ACCEPT") + ) + protected const val Accept: String = ACCEPT + + protected const val AUTHORIZATION: String = "Authorization" + @Deprecated( + message = "Please use the capitalized constant `AUTHORIZATION` instead.", + replaceWith = ReplaceWith("AUTHORIZATION") + ) + protected const val Authorization: String = AUTHORIZATION + + protected const val JSON_MEDIA_TYPE: String = "application/json" + @Deprecated( + message = "Please use the capitalized constant `JSON_MEDIA_TYPE` instead.", + replaceWith = ReplaceWith("JSON_MEDIA_TYPE") + ) + protected const val JsonMediaType: String = JSON_MEDIA_TYPE + + protected const val FORM_DATA_MEDIA_TYPE: String = "multipart/form-data" + @Deprecated( + message = "Please use the capitalized constant `FORM_DATA_MEDIA_TYPE` instead.", + replaceWith = ReplaceWith("FORM_DATA_MEDIA_TYPE") + ) + protected const val FormDataMediaType: String = FORM_DATA_MEDIA_TYPE + + protected const val FORM_URL_ENC_MEDIA_TYPE: String = "application/x-www-form-urlencoded" + @Deprecated( + message = "Please use the capitalized constant `FORM_URL_ENC_MEDIA_TYPE` instead.", + replaceWith = ReplaceWith("FORM_URL_ENC_MEDIA_TYPE") + ) + protected const val FormUrlEncMediaType: String = FORM_URL_ENC_MEDIA_TYPE + + protected const val XML_MEDIA_TYPE: String = "application/xml" + @Deprecated( + message = "Please use the capitalized constant `XML_MEDIA_TYPE` instead.", + replaceWith = ReplaceWith("XML_MEDIA_TYPE") + ) + protected const val XmlMediaType: String = XML_MEDIA_TYPE + + protected const val OCTET_MEDIA_TYPE: String = "application/octet-stream" + @Deprecated( + message = "Please use the capitalized constant `OCTET_MEDIA_TYPE` instead.", + replaceWith = ReplaceWith("OCTET_MEDIA_TYPE") + ) + protected const val OctetMediaType: String = OCTET_MEDIA_TYPE + + protected const val TEXT_MEDIA_TYPE: String = "text/plain" + @Deprecated( + message = "Please use the capitalized constant `TEXT_MEDIA_TYPE` instead.", + replaceWith = ReplaceWith("TEXT_MEDIA_TYPE") + ) + protected const val TextMediaType: String = TEXT_MEDIA_TYPE + + const val BASE_URL_KEY: String = "dev.hho.android.data.apiclient.generated.baseUrl" + @Deprecated( + message = "Please use the capitalized constant `BASE_URL_KEY` instead.", + replaceWith = ReplaceWith("BASE_URL_KEY") + ) + const val baseUrlKey: String = BASE_URL_KEY + + val apiKey: MutableMap = mutableMapOf() + val apiKeyPrefix: MutableMap = mutableMapOf() + var username: String? = null + var password: String? = null + var accessToken: String? = null + + @JvmStatic + val defaultClient: OkHttpClient by lazy { + builder.build() + } + + @JvmStatic + val builder: OkHttpClient.Builder = OkHttpClient.Builder() + } + + var userCredentialsProvider: () -> Pair = { username to password } + var accessTokenProvider: () -> String? = { accessToken } + + protected fun guessContentTypeFromByteArray(byteArray: ByteArray): String { + val contentType = try { + URLConnection.guessContentTypeFromStream(byteArray.inputStream()) + } catch (_: IOException) { + "application/octet-stream" + } + return contentType + } + + protected fun guessContentTypeFromFile(file: File): String { + val contentType = URLConnection.guessContentTypeFromName(file.name) + return contentType ?: "application/octet-stream" + } + + protected fun buildPartHeaders(name: String, headers: Map, filename: String? = null): Headers { + val disposition = if (filename != null) { + "form-data; name=\"$name\"; filename=\"$filename\"" + } else { + "form-data; name=\"$name\"" + } + return (headers.filterKeys { it != "Content-Type" } + ("Content-Disposition" to disposition)).toHeaders() + } + + protected fun MultipartBody.Builder.addPartToMultiPart(name: String, headers: Map, file: File) { + val fileMediaType = guessContentTypeFromFile(file).toMediaTypeOrNull() + addPart( + buildPartHeaders(name, headers, file.name), + file.asRequestBody(fileMediaType) + ) + } + + protected fun serializePartBody(obj: Any?, contentType: String?, serializer: ((Any?) -> String)?): String { + if (serializer != null) { + return serializer(obj) + } + + return if (contentType?.contains("json") == true) { + parameterToString(obj) + } else { + parameterToString(obj) + } + } + + protected fun MultipartBody.Builder.addPartToMultiPart(name: String, headers: Map, obj: Any?, serializer: ((Any?) -> String)? = null) { + val partContentType = headers["Content-Type"] + val partMediaType = partContentType?.toMediaTypeOrNull() + val partBody = serializePartBody(obj, partContentType, serializer) + addPart( + buildPartHeaders(name, headers), + partBody.toRequestBody(partMediaType) + ) + } + + protected inline fun requestBody(content: T, mediaType: String?): RequestBody = + when { + content is ByteArray -> content.toRequestBody((mediaType ?: guessContentTypeFromByteArray(content)).toMediaTypeOrNull()) + content is File -> content.asRequestBody((mediaType ?: guessContentTypeFromFile(content)).toMediaTypeOrNull()) + mediaType == FORM_DATA_MEDIA_TYPE -> + MultipartBody.Builder() + .setType(MultipartBody.FORM) + .apply { + @Suppress("UNCHECKED_CAST") + (content as Map>).forEach { (name, part) -> + when (part.body) { + is File -> addPartToMultiPart(name, part.headers, part.body) + is List<*> -> { + part.body.forEach { + if (it is File) { + addPartToMultiPart(name, part.headers, it) + } else { + addPartToMultiPart(name, part.headers, it, part.serializer) + } + } + } + else -> addPartToMultiPart(name, part.headers, part.body, part.serializer) + } + } + }.build() + mediaType == FORM_URL_ENC_MEDIA_TYPE -> { + FormBody.Builder().apply { + @Suppress("UNCHECKED_CAST") + (content as Map>).forEach { (name, part) -> + add(name, parameterToString(part.body)) + } + }.build() + } + mediaType == null || mediaType.startsWith("application/") && mediaType.endsWith("json") -> + if (content == null) { + EMPTY_REQUEST + } else { + Serializer.kotlinxSerializationJson.encodeToString(content) + .toRequestBody((mediaType ?: JSON_MEDIA_TYPE).toMediaTypeOrNull()) + } + mediaType == XML_MEDIA_TYPE -> throw UnsupportedOperationException("xml not currently supported.") + mediaType == TEXT_MEDIA_TYPE -> { + val textualContent = when (content) { + is Char, is CharSequence -> content.toString() + is Number -> content.toString() + is Boolean -> content.toString() + else -> throw UnsupportedOperationException("requestBody currently only supports text body containing primitive types: characters, numbers, or booleans.") + } + textualContent.toRequestBody(mediaType.toMediaTypeOrNull()) + } + else -> throw UnsupportedOperationException("requestBody currently only supports JSON body, text body, byte body and File body.") + } + + protected inline fun responseBody(response: Response, mediaType: String? = JSON_MEDIA_TYPE): T? { + val body = response.body ?: return null + + if (T::class.java == Unit::class.java) { + return null + } else if (T::class.java == File::class.java) { + val contentDisposition = response.header("Content-Disposition") + + val fileName = if (contentDisposition != null) { + val pattern = Pattern.compile("filename=['\"]?([^'\"\\s]+)['\"]?") + val matcher = pattern.matcher(contentDisposition) + if (matcher.find()) { + matcher.group(1) + ?.replace(".*[/\\\\]", "") + ?.replace(";", "") + } else { + null + } + } else { + null + } + + var prefix: String? + val suffix: String? + if (fileName == null) { + prefix = "download" + suffix = "" + } else { + val pos = fileName.lastIndexOf(".") + if (pos == -1) { + prefix = fileName + suffix = null + } else { + prefix = fileName.substring(0, pos) + suffix = fileName.substring(pos) + } + if (prefix.length < 3) { + prefix = "download" + } + } + + val tempFile = java.nio.file.Files.createTempFile(prefix, suffix).toFile() + tempFile.deleteOnExit() + body.byteStream().use { inputStream -> + tempFile.outputStream().use { tempFileOutputStream -> + inputStream.copyTo(tempFileOutputStream) + } + } + return tempFile as T + } + + return when { + mediaType == null || (mediaType.startsWith("application/") && mediaType.endsWith("json")) -> { + val bodyContent = body.string() + if (bodyContent.isEmpty()) { + return null + } + Serializer.kotlinxSerializationJson.decodeFromString(bodyContent) + } + mediaType == OCTET_MEDIA_TYPE -> body.bytes() as? T + mediaType == TEXT_MEDIA_TYPE -> body.string() as? T + else -> throw UnsupportedOperationException("responseBody currently only supports JSON body, text body and byte body.") + } + } + + protected fun updateAuthParams(requestConfig: RequestConfig) { + if (apiKey["hho_session"] != null) { + if (apiKeyPrefix["hho_session"] != null) { + } else { + } + } + if (requestConfig.headers[AUTHORIZATION].isNullOrEmpty()) { + accessTokenProvider()?.let { token -> + requestConfig.headers[AUTHORIZATION] = "Bearer $token" + } + } + } + + protected inline fun request(requestConfig: RequestConfig): ApiResponse { + val httpUrl = baseUrl.toHttpUrlOrNull() ?: throw IllegalStateException("baseUrl is invalid.") + + updateAuthParams(requestConfig) + + val url = httpUrl.newBuilder() + .addEncodedPathSegments(requestConfig.path.trimStart('/')) + .apply { + requestConfig.query.forEach { query -> + query.value.forEach { queryValue -> + addQueryParameter(query.key, queryValue) + } + } + }.build() + + if (requestConfig.body != null && requestConfig.headers[CONTENT_TYPE].isNullOrEmpty()) { + requestConfig.headers[CONTENT_TYPE] = JSON_MEDIA_TYPE + } + if (requestConfig.headers[ACCEPT].isNullOrEmpty()) { + requestConfig.headers[ACCEPT] = JSON_MEDIA_TYPE + } + val headers = requestConfig.headers + + if (headers[ACCEPT].isNullOrEmpty()) { + throw kotlin.IllegalStateException("Missing ACCEPT header. This is required.") + } + + val contentType = if (headers[CONTENT_TYPE] != null) { + (headers[CONTENT_TYPE] as String).substringBefore(";").lowercase(Locale.US) + } else { + null + } + + val request = when (requestConfig.method) { + RequestMethod.DELETE -> Request.Builder().url(url).delete(requestBody(requestConfig.body, contentType)) + RequestMethod.GET -> Request.Builder().url(url) + RequestMethod.HEAD -> Request.Builder().url(url).head() + RequestMethod.PATCH -> Request.Builder().url(url).patch(requestBody(requestConfig.body, contentType)) + RequestMethod.PUT -> Request.Builder().url(url).put(requestBody(requestConfig.body, contentType)) + RequestMethod.POST -> Request.Builder().url(url).post(requestBody(requestConfig.body, contentType)) + RequestMethod.OPTIONS -> Request.Builder().url(url).method("OPTIONS", null) + }.apply { + val headersBuilder = Headers.Builder() + headers.forEach { header -> + headersBuilder.add(header.key, header.value) + } + this.headers(headersBuilder.build()) + }.build() + + val response = client.newCall(request).execute() + + val accept = response.header(CONTENT_TYPE)?.substringBefore(";")?.lowercase(Locale.US) + + @Suppress("UNNECESSARY_SAFE_CALL") + return response.use { + when { + it.isRedirect -> Redirection( + it.code, + it.headers.toMultimap() + ) + it.isInformational -> Informational( + it.message, + it.code, + it.headers.toMultimap() + ) + it.isSuccessful -> Success( + responseBody(it, accept), + it.code, + it.headers.toMultimap() + ) + it.isClientError -> ClientError( + it.message, + it.body?.string(), + it.code, + it.headers.toMultimap() + ) + else -> ServerError( + it.message, + it.body?.string(), + it.code, + it.headers.toMultimap() + ) + } + } + } + + protected fun parameterToString(value: Any?): String = when (value) { + null -> "" + is Array<*> -> toMultiValue(value, "csv").toString() + is Iterable<*> -> toMultiValue(value, "csv").toString() + is OffsetDateTime -> parseDateToQueryString(value) + is OffsetTime -> parseDateToQueryString(value) + is LocalDateTime -> parseDateToQueryString(value) + is LocalDate -> parseDateToQueryString(value) + is LocalTime -> parseDateToQueryString(value) + else -> value.toString() + } + + protected inline fun parseDateToQueryString(value : T): String { + return Serializer.kotlinxSerializationJson.encodeToString(value).replace("\"", "") + } +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/ApiResponse.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/ApiResponse.kt new file mode 100644 index 0000000..07b0ac9 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/ApiResponse.kt @@ -0,0 +1,43 @@ +package dev.hho.android.data.apiclient.generated.infrastructure + +enum class ResponseType { + Success, Informational, Redirection, ClientError, ServerError +} + +interface Response + +abstract class ApiResponse(val responseType: ResponseType): Response { + abstract val statusCode: Int + abstract val headers: Map> +} + +class Success( + val data: T, + override val statusCode: Int = -1, + override val headers: Map> = mapOf() +): ApiResponse(ResponseType.Success) + +class Informational( + val statusText: String, + override val statusCode: Int = -1, + override val headers: Map> = mapOf() +) : ApiResponse(ResponseType.Informational) + +class Redirection( + override val statusCode: Int = -1, + override val headers: Map> = mapOf() +) : ApiResponse(ResponseType.Redirection) + +class ClientError( + val message: String? = null, + val body: Any? = null, + override val statusCode: Int = -1, + override val headers: Map> = mapOf() +) : ApiResponse(ResponseType.ClientError) + +class ServerError( + val message: String? = null, + val body: Any? = null, + override val statusCode: Int = -1, + override val headers: Map> = mapOf() +): ApiResponse(ResponseType.ServerError) diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/AtomicBooleanAdapter.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/AtomicBooleanAdapter.kt new file mode 100644 index 0000000..8adf646 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/AtomicBooleanAdapter.kt @@ -0,0 +1,19 @@ +package dev.hho.android.data.apiclient.generated.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import java.util.concurrent.atomic.AtomicBoolean + +object AtomicBooleanAdapter : KSerializer { + override fun serialize(encoder: Encoder, value: AtomicBoolean) { + encoder.encodeBoolean(value.get()) + } + + override fun deserialize(decoder: Decoder): AtomicBoolean = AtomicBoolean(decoder.decodeBoolean()) + + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("AtomicBoolean", PrimitiveKind.BOOLEAN) +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/AtomicIntegerAdapter.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/AtomicIntegerAdapter.kt new file mode 100644 index 0000000..5a264ca --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/AtomicIntegerAdapter.kt @@ -0,0 +1,19 @@ +package dev.hho.android.data.apiclient.generated.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import java.util.concurrent.atomic.AtomicInteger + +object AtomicIntegerAdapter : KSerializer { + override fun serialize(encoder: Encoder, value: AtomicInteger) { + encoder.encodeInt(value.get()) + } + + override fun deserialize(decoder: Decoder): AtomicInteger = AtomicInteger(decoder.decodeInt()) + + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("AtomicInteger", PrimitiveKind.INT) +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/AtomicLongAdapter.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/AtomicLongAdapter.kt new file mode 100644 index 0000000..e06a331 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/AtomicLongAdapter.kt @@ -0,0 +1,19 @@ +package dev.hho.android.data.apiclient.generated.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import java.util.concurrent.atomic.AtomicLong + +object AtomicLongAdapter : KSerializer { + override fun serialize(encoder: Encoder, value: AtomicLong) { + encoder.encodeLong(value.get()) + } + + override fun deserialize(decoder: Decoder): AtomicLong = AtomicLong(decoder.decodeLong()) + + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("AtomicLong", PrimitiveKind.LONG) +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/BigDecimalAdapter.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/BigDecimalAdapter.kt new file mode 100644 index 0000000..19e46d9 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/BigDecimalAdapter.kt @@ -0,0 +1,15 @@ +package dev.hho.android.data.apiclient.generated.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import java.math.BigDecimal + +object BigDecimalAdapter : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("BigDecimal", PrimitiveKind.STRING) + override fun deserialize(decoder: Decoder): BigDecimal = BigDecimal(decoder.decodeString()) + override fun serialize(encoder: Encoder, value: BigDecimal) = encoder.encodeString(value.toPlainString()) +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/BigIntegerAdapter.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/BigIntegerAdapter.kt new file mode 100644 index 0000000..57cb27a --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/BigIntegerAdapter.kt @@ -0,0 +1,20 @@ +package dev.hho.android.data.apiclient.generated.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import java.math.BigInteger + +object BigIntegerAdapter : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("BigInteger", PrimitiveKind.STRING) + override fun deserialize(decoder: Decoder): BigInteger { + return BigInteger(decoder.decodeString()) + } + + override fun serialize(encoder: Encoder, value: BigInteger) { + encoder.encodeString(value.toString()) + } +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/Errors.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/Errors.kt new file mode 100644 index 0000000..506f888 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/Errors.kt @@ -0,0 +1,18 @@ +@file:Suppress("unused") +package dev.hho.android.data.apiclient.generated.infrastructure + +import java.lang.RuntimeException + +open class ClientException(message: kotlin.String? = null, val statusCode: Int = -1, val response: Response? = null) : RuntimeException(message) { + + companion object { + private const val serialVersionUID: Long = 123L + } +} + +open class ServerException(message: kotlin.String? = null, val statusCode: Int = -1, val response: Response? = null) : RuntimeException(message) { + + companion object { + private const val serialVersionUID: Long = 456L + } +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/LocalDateAdapter.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/LocalDateAdapter.kt new file mode 100644 index 0000000..2c75b6e --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/LocalDateAdapter.kt @@ -0,0 +1,22 @@ +package dev.hho.android.data.apiclient.generated.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import java.time.LocalDate +import java.time.format.DateTimeFormatter + +object LocalDateAdapter : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("LocalDate", PrimitiveKind.STRING) + + override fun serialize(encoder: Encoder, value: LocalDate) { + encoder.encodeString(DateTimeFormatter.ISO_LOCAL_DATE.format(value)) + } + + override fun deserialize(decoder: Decoder): LocalDate { + return LocalDate.parse(decoder.decodeString(), DateTimeFormatter.ISO_LOCAL_DATE) + } +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/LocalDateTimeAdapter.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/LocalDateTimeAdapter.kt new file mode 100644 index 0000000..6e4f43a --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/LocalDateTimeAdapter.kt @@ -0,0 +1,22 @@ +package dev.hho.android.data.apiclient.generated.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import java.time.LocalDateTime +import java.time.format.DateTimeFormatter + +object LocalDateTimeAdapter : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("LocalDateTime", PrimitiveKind.STRING) + + override fun serialize(encoder: Encoder, value: LocalDateTime) { + encoder.encodeString(DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(value)) + } + + override fun deserialize(decoder: Decoder): LocalDateTime { + return LocalDateTime.parse(decoder.decodeString(), DateTimeFormatter.ISO_LOCAL_DATE_TIME) + } +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/OffsetDateTimeAdapter.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/OffsetDateTimeAdapter.kt new file mode 100644 index 0000000..076702b --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/OffsetDateTimeAdapter.kt @@ -0,0 +1,22 @@ +package dev.hho.android.data.apiclient.generated.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import java.time.OffsetDateTime +import java.time.format.DateTimeFormatter + +object OffsetDateTimeAdapter : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("OffsetDateTime", PrimitiveKind.STRING) + + override fun serialize(encoder: Encoder, value: OffsetDateTime) { + encoder.encodeString(DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(value)) + } + + override fun deserialize(decoder: Decoder): OffsetDateTime { + return OffsetDateTime.parse(decoder.decodeString(), DateTimeFormatter.ISO_OFFSET_DATE_TIME) + } +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/PartConfig.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/PartConfig.kt new file mode 100644 index 0000000..afe11e1 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/PartConfig.kt @@ -0,0 +1,7 @@ +package dev.hho.android.data.apiclient.generated.infrastructure + +data class PartConfig( + val headers: MutableMap = mutableMapOf(), + val body: T? = null, + val serializer: ((Any?) -> String)? = null +) diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/RequestConfig.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/RequestConfig.kt new file mode 100644 index 0000000..3ed12fa --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/RequestConfig.kt @@ -0,0 +1,11 @@ +package dev.hho.android.data.apiclient.generated.infrastructure + +data class RequestConfig( + val method: RequestMethod, + val path: String, + val headers: MutableMap = mutableMapOf(), + val params: MutableMap = mutableMapOf(), + val query: MutableMap> = mutableMapOf(), + val requiresAuthentication: Boolean, + val body: T? = null +) diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/RequestMethod.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/RequestMethod.kt new file mode 100644 index 0000000..4856c3e --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/RequestMethod.kt @@ -0,0 +1,5 @@ +package dev.hho.android.data.apiclient.generated.infrastructure + +enum class RequestMethod { + GET, DELETE, HEAD, OPTIONS, PATCH, POST, PUT +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/ResponseExtensions.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/ResponseExtensions.kt new file mode 100644 index 0000000..7911420 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/ResponseExtensions.kt @@ -0,0 +1,12 @@ +package dev.hho.android.data.apiclient.generated.infrastructure + +import okhttp3.Response + +val Response.isInformational : Boolean get() = this.code in 100..199 + +@Suppress("EXTENSION_SHADOWED_BY_MEMBER") +val Response.isRedirect : Boolean get() = this.code in 300..399 + +val Response.isClientError : Boolean get() = this.code in 400..499 + +val Response.isServerError : Boolean get() = this.code in 500..999 diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/Serializer.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/Serializer.kt new file mode 100644 index 0000000..c20795f --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/Serializer.kt @@ -0,0 +1,73 @@ +package dev.hho.android.data.apiclient.generated.infrastructure + +import java.math.BigDecimal +import java.math.BigInteger +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.OffsetDateTime +import java.util.UUID +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonBuilder +import kotlinx.serialization.modules.SerializersModule +import kotlinx.serialization.modules.SerializersModuleBuilder +import java.net.URI +import java.net.URL +import java.util.concurrent.atomic.AtomicBoolean +import java.util.concurrent.atomic.AtomicInteger +import java.util.concurrent.atomic.AtomicLong + +object Serializer { + private var isAdaptersInitialized = false + + @JvmStatic + val kotlinxSerializationAdapters: SerializersModule by lazy { + isAdaptersInitialized = true + SerializersModule { + contextual(BigDecimal::class, BigDecimalAdapter) + contextual(BigInteger::class, BigIntegerAdapter) + contextual(LocalDate::class, LocalDateAdapter) + contextual(LocalDateTime::class, LocalDateTimeAdapter) + contextual(OffsetDateTime::class, OffsetDateTimeAdapter) + contextual(UUID::class, UUIDAdapter) + contextual(AtomicInteger::class, AtomicIntegerAdapter) + contextual(AtomicLong::class, AtomicLongAdapter) + contextual(AtomicBoolean::class, AtomicBooleanAdapter) + contextual(URI::class, URIAdapter) + contextual(URL::class, URLAdapter) + contextual(StringBuilder::class, StringBuilderAdapter) + + apply(kotlinxSerializationAdaptersConfiguration) + } + } + + var kotlinxSerializationAdaptersConfiguration: SerializersModuleBuilder.() -> Unit = {} + set(value) { + check(!isAdaptersInitialized) { + "Cannot configure kotlinxSerializationAdaptersConfiguration after kotlinxSerializationAdapters has been initialized." + } + field = value + } + + private var isJsonInitialized = false + + @JvmStatic + val kotlinxSerializationJson: Json by lazy { + isJsonInitialized = true + Json { + serializersModule = kotlinxSerializationAdapters + encodeDefaults = true + ignoreUnknownKeys = true + isLenient = true + + apply(kotlinxSerializationJsonConfiguration) + } + } + + var kotlinxSerializationJsonConfiguration: JsonBuilder.() -> Unit = {} + set(value) { + check(!isJsonInitialized) { + "Cannot configure kotlinxSerializationJsonConfiguration after kotlinxSerializationJson has been initialized." + } + field = value + } +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/StringBuilderAdapter.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/StringBuilderAdapter.kt new file mode 100644 index 0000000..ae5d66f --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/StringBuilderAdapter.kt @@ -0,0 +1,18 @@ +package dev.hho.android.data.apiclient.generated.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor + +object StringBuilderAdapter : KSerializer { + override fun serialize(encoder: Encoder, value: StringBuilder) { + encoder.encodeString(value.toString()) + } + + override fun deserialize(decoder: Decoder): StringBuilder = StringBuilder(decoder.decodeString()) + + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("StringBuilder", PrimitiveKind.STRING) +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/URIAdapter.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/URIAdapter.kt new file mode 100644 index 0000000..4f7d7fd --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/URIAdapter.kt @@ -0,0 +1,19 @@ +package dev.hho.android.data.apiclient.generated.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import java.net.URI + +object URIAdapter : KSerializer { + override fun serialize(encoder: Encoder, value: URI) { + encoder.encodeString(value.toASCIIString()) + } + + override fun deserialize(decoder: Decoder): URI = URI(decoder.decodeString()) + + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("URI", PrimitiveKind.STRING) +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/URLAdapter.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/URLAdapter.kt new file mode 100644 index 0000000..8ff7e97 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/URLAdapter.kt @@ -0,0 +1,19 @@ +package dev.hho.android.data.apiclient.generated.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import java.net.URL + +object URLAdapter : KSerializer { + override fun serialize(encoder: Encoder, value: URL) { + encoder.encodeString(value.toExternalForm()) + } + + override fun deserialize(decoder: Decoder): URL = URL(decoder.decodeString()) + + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("URL", PrimitiveKind.STRING) +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/UUIDAdapter.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/UUIDAdapter.kt new file mode 100644 index 0000000..786a4e4 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/infrastructure/UUIDAdapter.kt @@ -0,0 +1,21 @@ +package dev.hho.android.data.apiclient.generated.infrastructure + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.SerialDescriptor +import java.util.UUID + +object UUIDAdapter : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("UUID", PrimitiveKind.STRING) + + override fun serialize(encoder: Encoder, value: UUID) { + encoder.encodeString(value.toString()) + } + + override fun deserialize(decoder: Decoder): UUID { + return UUID.fromString(decoder.decodeString()) + } +} diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/Attachment.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/Attachment.kt new file mode 100644 index 0000000..2b37b36 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/Attachment.kt @@ -0,0 +1,70 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class Attachment ( + + @SerialName(value = "id") + val id: kotlin.String, + + @SerialName(value = "item_id") + val itemId: kotlin.String, + + @SerialName(value = "category") + val category: Attachment.Category, + + @SerialName(value = "original_filename") + val originalFilename: kotlin.String, + + @SerialName(value = "content_type") + val contentType: kotlin.String, + + @SerialName(value = "size_bytes") + val sizeBytes: kotlin.Long, + + @SerialName(value = "sha256") + val sha256: kotlin.String, + + @SerialName(value = "created_at") + val createdAt: kotlin.Long, + + @SerialName(value = "updated_at") + val updatedAt: kotlin.Long, + + @SerialName(value = "version") + val version: kotlin.Long, + + @SerialName(value = "has_thumbnail") + val hasThumbnail: kotlin.Boolean + +) { + @Serializable + enum class Category(val value: kotlin.String) { + @SerialName(value = "image") Image("image"), + @SerialName(value = "manual") Manual("manual"), + @SerialName(value = "warranty") Warranty("warranty"), + @SerialName(value = "receipt") Receipt("receipt"), + @SerialName(value = "general") General("general"); + } + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/AttachmentListResponse.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/AttachmentListResponse.kt new file mode 100644 index 0000000..e8c6a65 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/AttachmentListResponse.kt @@ -0,0 +1,34 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import dev.hho.android.data.apiclient.generated.models.Attachment + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class AttachmentListResponse ( + + @SerialName(value = "attachments") + val attachments: kotlin.collections.List + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/CustomFieldDef.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/CustomFieldDef.kt new file mode 100644 index 0000000..65fa315 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/CustomFieldDef.kt @@ -0,0 +1,57 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class CustomFieldDef ( + + @SerialName(value = "name") + val name: kotlin.String, + + @SerialName(value = "field_type") + val fieldType: CustomFieldDef.FieldType, + + @SerialName(value = "display_order") + val displayOrder: kotlin.Long, + + @SerialName(value = "id") + val id: kotlin.String? = null, + + @SerialName(value = "created_at") + val createdAt: kotlin.Long? = null, + + @SerialName(value = "updated_at") + val updatedAt: kotlin.Long? = null, + + @SerialName(value = "version") + val version: kotlin.Long? = null + +) { + @Serializable + enum class FieldType(val value: kotlin.String) { + @SerialName(value = "text") Text("text"), + @SerialName(value = "number") Number("number"), + @SerialName(value = "boolean") Boolean("boolean"), + @SerialName(value = "date") Date("date"); + } + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/CustomFieldDefCreateRequest.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/CustomFieldDefCreateRequest.kt new file mode 100644 index 0000000..f79d830 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/CustomFieldDefCreateRequest.kt @@ -0,0 +1,45 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class CustomFieldDefCreateRequest ( + + @SerialName(value = "name") + val name: kotlin.String, + + @SerialName(value = "field_type") + val fieldType: CustomFieldDefCreateRequest.FieldType, + + @SerialName(value = "display_order") + val displayOrder: kotlin.Long + +) { + @Serializable + enum class FieldType(val value: kotlin.String) { + @SerialName(value = "text") Text("text"), + @SerialName(value = "number") Number("number"), + @SerialName(value = "boolean") Boolean("boolean"), + @SerialName(value = "date") Date("date"); + } + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/CustomFieldDefListResponse.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/CustomFieldDefListResponse.kt new file mode 100644 index 0000000..f2c8ce4 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/CustomFieldDefListResponse.kt @@ -0,0 +1,34 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import dev.hho.android.data.apiclient.generated.models.CustomFieldDef + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class CustomFieldDefListResponse ( + + @SerialName(value = "custom_field_defs") + val customFieldDefs: kotlin.collections.List + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/CustomFieldDefUpdateRequest.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/CustomFieldDefUpdateRequest.kt new file mode 100644 index 0000000..8158441 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/CustomFieldDefUpdateRequest.kt @@ -0,0 +1,48 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class CustomFieldDefUpdateRequest ( + + @SerialName(value = "name") + val name: kotlin.String, + + @SerialName(value = "field_type") + val fieldType: CustomFieldDefUpdateRequest.FieldType, + + @SerialName(value = "display_order") + val displayOrder: kotlin.Long, + + @SerialName(value = "version") + val version: kotlin.Long + +) { + @Serializable + enum class FieldType(val value: kotlin.String) { + @SerialName(value = "text") Text("text"), + @SerialName(value = "number") Number("number"), + @SerialName(value = "boolean") Boolean("boolean"), + @SerialName(value = "date") Date("date"); + } + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/DeviceTokenIssueRequest.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/DeviceTokenIssueRequest.kt new file mode 100644 index 0000000..378c33b --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/DeviceTokenIssueRequest.kt @@ -0,0 +1,32 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class DeviceTokenIssueRequest ( + + @SerialName(value = "device_label") + val deviceLabel: kotlin.String + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/DeviceTokenIssueResponse.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/DeviceTokenIssueResponse.kt new file mode 100644 index 0000000..ff64009 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/DeviceTokenIssueResponse.kt @@ -0,0 +1,38 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class DeviceTokenIssueResponse ( + + @SerialName(value = "id") + val id: kotlin.String, + + @SerialName(value = "device_label") + val deviceLabel: kotlin.String, + + @SerialName(value = "token") + val token: kotlin.String + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/DeviceTokenListItem.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/DeviceTokenListItem.kt new file mode 100644 index 0000000..dc85d0b --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/DeviceTokenListItem.kt @@ -0,0 +1,44 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class DeviceTokenListItem ( + + @SerialName(value = "id") + val id: kotlin.String, + + @SerialName(value = "device_label") + val deviceLabel: kotlin.String, + + @SerialName(value = "created_at") + val createdAt: kotlin.Long, + + @SerialName(value = "revoked") + val revoked: kotlin.Boolean, + + @SerialName(value = "revoked_at") + val revokedAt: kotlin.Long? = null + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/DeviceTokenListResponse.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/DeviceTokenListResponse.kt new file mode 100644 index 0000000..c9fbf1f --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/DeviceTokenListResponse.kt @@ -0,0 +1,34 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import dev.hho.android.data.apiclient.generated.models.DeviceTokenListItem + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class DeviceTokenListResponse ( + + @SerialName(value = "device_tokens") + val deviceTokens: kotlin.collections.List + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/GroupMember.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/GroupMember.kt new file mode 100644 index 0000000..40a2c4e --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/GroupMember.kt @@ -0,0 +1,41 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class GroupMember ( + + @SerialName(value = "id") + val id: kotlin.String, + + @SerialName(value = "username") + val username: kotlin.String, + + @SerialName(value = "role") + val role: kotlin.String, + + @SerialName(value = "joined_at") + val joinedAt: kotlin.Long + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/GroupMembersResponse.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/GroupMembersResponse.kt new file mode 100644 index 0000000..548e95f --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/GroupMembersResponse.kt @@ -0,0 +1,34 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import dev.hho.android.data.apiclient.generated.models.GroupMember + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class GroupMembersResponse ( + + @SerialName(value = "members") + val members: kotlin.collections.List + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/GroupVisibility.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/GroupVisibility.kt new file mode 100644 index 0000000..3906361 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/GroupVisibility.kt @@ -0,0 +1,41 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class GroupVisibility ( + + @SerialName(value = "warranty_visible") + val warrantyVisible: kotlin.Boolean, + + @SerialName(value = "sale_visible") + val saleVisible: kotlin.Boolean, + + @SerialName(value = "purchase_visible") + val purchaseVisible: kotlin.Boolean, + + @SerialName(value = "version") + val version: kotlin.Long? = null + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/GroupVisibilityUpdateRequest.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/GroupVisibilityUpdateRequest.kt new file mode 100644 index 0000000..2ee2410 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/GroupVisibilityUpdateRequest.kt @@ -0,0 +1,41 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class GroupVisibilityUpdateRequest ( + + @SerialName(value = "warranty_visible") + val warrantyVisible: kotlin.Boolean, + + @SerialName(value = "sale_visible") + val saleVisible: kotlin.Boolean, + + @SerialName(value = "purchase_visible") + val purchaseVisible: kotlin.Boolean, + + @SerialName(value = "version") + val version: kotlin.Long + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/Identification.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/Identification.kt new file mode 100644 index 0000000..518c1b9 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/Identification.kt @@ -0,0 +1,57 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class Identification ( + @SerialName(value = "kind") + val kind: Identification.Kind, + + @SerialName(value = "value") + val `value`: kotlin.String, + + @SerialName(value = "id") + val id: kotlin.String? = null, + + @SerialName(value = "item_id") + val itemId: kotlin.String? = null, + + @SerialName(value = "created_at") + val createdAt: kotlin.Long? = null, + + @SerialName(value = "updated_at") + val updatedAt: kotlin.Long? = null, + + @SerialName(value = "version") + val version: kotlin.Long? = null + +) { + @Serializable + enum class Kind(val value: kotlin.String) { + @SerialName(value = "serial") Serial("serial"), + @SerialName(value = "model") Model("model"), + @SerialName(value = "asset_tag") AssetTag("asset_tag"), + @SerialName(value = "barcode") Barcode("barcode"), + @SerialName(value = "other") Other("other"); + } + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/IdentificationCreateRequest.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/IdentificationCreateRequest.kt new file mode 100644 index 0000000..ead8f6a --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/IdentificationCreateRequest.kt @@ -0,0 +1,43 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class IdentificationCreateRequest ( + + @SerialName(value = "kind") + val kind: IdentificationCreateRequest.Kind, + + @SerialName(value = "value") + val `value`: kotlin.String + +) { + @Serializable + enum class Kind(val value: kotlin.String) { + @SerialName(value = "serial") Serial("serial"), + @SerialName(value = "model") Model("model"), + @SerialName(value = "asset_tag") AssetTag("asset_tag"), + @SerialName(value = "barcode") Barcode("barcode"), + @SerialName(value = "other") Other("other"); + } + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/IdentificationListResponse.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/IdentificationListResponse.kt new file mode 100644 index 0000000..c494486 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/IdentificationListResponse.kt @@ -0,0 +1,34 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import dev.hho.android.data.apiclient.generated.models.Identification + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class IdentificationListResponse ( + + @SerialName(value = "identifications") + val identifications: kotlin.collections.List + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/IdentificationUpdateRequest.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/IdentificationUpdateRequest.kt new file mode 100644 index 0000000..d2e70e1 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/IdentificationUpdateRequest.kt @@ -0,0 +1,46 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class IdentificationUpdateRequest ( + + @SerialName(value = "kind") + val kind: IdentificationUpdateRequest.Kind, + + @SerialName(value = "value") + val `value`: kotlin.String, + + @SerialName(value = "version") + val version: kotlin.Long + +) { + @Serializable + enum class Kind(val value: kotlin.String) { + @SerialName(value = "serial") Serial("serial"), + @SerialName(value = "model") Model("model"), + @SerialName(value = "asset_tag") AssetTag("asset_tag"), + @SerialName(value = "barcode") Barcode("barcode"), + @SerialName(value = "other") Other("other"); + } + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ImportCommitCreatedItem.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ImportCommitCreatedItem.kt new file mode 100644 index 0000000..aaad5be --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ImportCommitCreatedItem.kt @@ -0,0 +1,35 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class ImportCommitCreatedItem ( + + @SerialName(value = "line") + val line: kotlin.Int, + + @SerialName(value = "item_id") + val itemId: kotlin.String + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ImportCommitRejectedResponse.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ImportCommitRejectedResponse.kt new file mode 100644 index 0000000..414af53 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ImportCommitRejectedResponse.kt @@ -0,0 +1,41 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import dev.hho.android.data.apiclient.generated.models.ImportPreviewRow +import dev.hho.android.data.apiclient.generated.models.ImportPreviewSummary + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class ImportCommitRejectedResponse ( + + @SerialName(value = "import_id") + val importId: kotlin.String, + + @SerialName(value = "rows") + val rows: kotlin.collections.List, + + @SerialName(value = "summary") + val summary: ImportPreviewSummary + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ImportCommitResponse.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ImportCommitResponse.kt new file mode 100644 index 0000000..ff96fbc --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ImportCommitResponse.kt @@ -0,0 +1,41 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import dev.hho.android.data.apiclient.generated.models.ImportCommitCreatedItem +import dev.hho.android.data.apiclient.generated.models.ImportCommitSummary + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class ImportCommitResponse ( + + @SerialName(value = "import_id") + val importId: kotlin.String, + + @SerialName(value = "summary") + val summary: ImportCommitSummary, + + @SerialName(value = "created_items") + val createdItems: kotlin.collections.List + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ImportCommitSummary.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ImportCommitSummary.kt new file mode 100644 index 0000000..b69dc67 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ImportCommitSummary.kt @@ -0,0 +1,38 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class ImportCommitSummary ( + + @SerialName(value = "created") + val created: kotlin.Int, + + @SerialName(value = "updated") + val updated: kotlin.Int, + + @SerialName(value = "unchanged") + val unchanged: kotlin.Int + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ImportPreviewResponse.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ImportPreviewResponse.kt new file mode 100644 index 0000000..30ea1aa --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ImportPreviewResponse.kt @@ -0,0 +1,41 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import dev.hho.android.data.apiclient.generated.models.ImportPreviewRow +import dev.hho.android.data.apiclient.generated.models.ImportPreviewSummary + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class ImportPreviewResponse ( + + @SerialName(value = "import_id") + val importId: kotlin.String, + + @SerialName(value = "rows") + val rows: kotlin.collections.List, + + @SerialName(value = "summary") + val summary: ImportPreviewSummary + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ImportPreviewRow.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ImportPreviewRow.kt new file mode 100644 index 0000000..c766648 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ImportPreviewRow.kt @@ -0,0 +1,68 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import dev.hho.android.data.apiclient.generated.models.ImportPreviewRowError + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class ImportPreviewRow ( + @SerialName(value = "line") + val line: kotlin.Int, + + @SerialName(value = "action") + val action: ImportPreviewRow.Action, + + @SerialName(value = "item_id") + val itemId: kotlin.String? = null, + + @SerialName(value = "name") + val name: kotlin.String? = null, + + @SerialName(value = "changes") + val changes: kotlin.collections.List? = null, + + @SerialName(value = "errors") + val errors: kotlin.collections.List? = null + +) { + @Serializable + enum class Action(val value: kotlin.String) { + @SerialName(value = "create") Create("create"), + @SerialName(value = "update") Update("update"), + @SerialName(value = "unchanged") Unchanged("unchanged"), + @SerialName(value = "error") Error("error"); + } + @Serializable + enum class Changes(val value: kotlin.String) { + @SerialName(value = "name") Name("name"), + @SerialName(value = "description") Description("description"), + @SerialName(value = "quantity") Quantity("quantity"), + @SerialName(value = "location_id") LocationId("location_id"), + @SerialName(value = "labels") Labels("labels"), + @SerialName(value = "identifications") Identifications("identifications"), + @SerialName(value = "warranty") Warranty("warranty"), + @SerialName(value = "purchase") Purchase("purchase"), + @SerialName(value = "sale") Sale("sale"), + @SerialName(value = "custom_fields") CustomFields("custom_fields"); + } + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ImportPreviewRowError.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ImportPreviewRowError.kt new file mode 100644 index 0000000..96e2165 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ImportPreviewRowError.kt @@ -0,0 +1,37 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class ImportPreviewRowError ( + @SerialName(value = "line") + val line: kotlin.Int, + + @SerialName(value = "message") + val message: kotlin.String, + + @SerialName(value = "column") + val column: kotlin.String? = null + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ImportPreviewSummary.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ImportPreviewSummary.kt new file mode 100644 index 0000000..0fe0480 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ImportPreviewSummary.kt @@ -0,0 +1,41 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class ImportPreviewSummary ( + + @SerialName(value = "create") + val create: kotlin.Int, + + @SerialName(value = "update") + val update: kotlin.Int, + + @SerialName(value = "unchanged") + val unchanged: kotlin.Int, + + @SerialName(value = "error") + val error: kotlin.Int + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ImportUploadResponse.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ImportUploadResponse.kt new file mode 100644 index 0000000..df2bc8c --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ImportUploadResponse.kt @@ -0,0 +1,31 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class ImportUploadResponse ( + @SerialName(value = "import_id") + val importId: kotlin.String + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/InviteCreateResponse.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/InviteCreateResponse.kt new file mode 100644 index 0000000..4f0cef7 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/InviteCreateResponse.kt @@ -0,0 +1,38 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class InviteCreateResponse ( + + @SerialName(value = "id") + val id: kotlin.String, + + @SerialName(value = "token") + val token: kotlin.String, + + @SerialName(value = "expires_at") + val expiresAt: kotlin.Long + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/InviteListItem.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/InviteListItem.kt new file mode 100644 index 0000000..8ae6e04 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/InviteListItem.kt @@ -0,0 +1,50 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class InviteListItem ( + + @SerialName(value = "id") + val id: kotlin.String, + + @SerialName(value = "created_by_user_id") + val createdByUserId: kotlin.String, + + @SerialName(value = "created_at") + val createdAt: kotlin.Long, + + @SerialName(value = "expires_at") + val expiresAt: kotlin.Long, + + @SerialName(value = "redeemed") + val redeemed: kotlin.Boolean, + + @SerialName(value = "redeemed_at") + val redeemedAt: kotlin.Long? = null, + + @SerialName(value = "redeemed_by_user_id") + val redeemedByUserId: kotlin.String? = null + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/InviteListResponse.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/InviteListResponse.kt new file mode 100644 index 0000000..6325d96 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/InviteListResponse.kt @@ -0,0 +1,34 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import dev.hho.android.data.apiclient.generated.models.InviteListItem + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class InviteListResponse ( + + @SerialName(value = "invites") + val invites: kotlin.collections.List + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/InviteRedeemRequest.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/InviteRedeemRequest.kt new file mode 100644 index 0000000..e3f5a5c --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/InviteRedeemRequest.kt @@ -0,0 +1,37 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class InviteRedeemRequest ( + @SerialName(value = "token") + val token: kotlin.String, + + @SerialName(value = "username") + val username: kotlin.String, + + @SerialName(value = "password") + val password: kotlin.String + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/InviteRedeemResponse.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/InviteRedeemResponse.kt new file mode 100644 index 0000000..e00c42f --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/InviteRedeemResponse.kt @@ -0,0 +1,38 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class InviteRedeemResponse ( + + @SerialName(value = "group_id") + val groupId: kotlin.String, + + @SerialName(value = "user_id") + val userId: kotlin.String, + + @SerialName(value = "username") + val username: kotlin.String + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/Item.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/Item.kt new file mode 100644 index 0000000..a034392 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/Item.kt @@ -0,0 +1,56 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class Item ( + + @SerialName(value = "name") + val name: kotlin.String, + + @SerialName(value = "id") + val id: kotlin.String? = null, + + @SerialName(value = "description") + val description: kotlin.String? = null, + + @SerialName(value = "location_id") + val locationId: kotlin.String? = null, + + @SerialName(value = "quantity") + val quantity: kotlin.Long? = null, + + @SerialName(value = "short_code") + val shortCode: kotlin.String? = null, + + @SerialName(value = "created_at") + val createdAt: kotlin.Long? = null, + + @SerialName(value = "updated_at") + val updatedAt: kotlin.Long? = null, + + @SerialName(value = "version") + val version: kotlin.Long? = null + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ItemCustomField.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ItemCustomField.kt new file mode 100644 index 0000000..01fbc16 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ItemCustomField.kt @@ -0,0 +1,72 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class ItemCustomField ( + + @SerialName(value = "name") + val name: kotlin.String, + + @SerialName(value = "field_type") + val fieldType: ItemCustomField.FieldType, + + @SerialName(value = "id") + val id: kotlin.String? = null, + + @SerialName(value = "item_id") + val itemId: kotlin.String? = null, + + @SerialName(value = "field_def_id") + val fieldDefId: kotlin.String? = null, + + @SerialName(value = "text_value") + val textValue: kotlin.String? = null, + + @Contextual @SerialName(value = "number_value") + val numberValue: java.math.BigDecimal? = null, + + @SerialName(value = "bool_value") + val boolValue: kotlin.Boolean? = null, + + @Contextual @SerialName(value = "date_value") + val dateValue: java.time.LocalDate? = null, + + @SerialName(value = "created_at") + val createdAt: kotlin.Long? = null, + + @SerialName(value = "updated_at") + val updatedAt: kotlin.Long? = null, + + @SerialName(value = "version") + val version: kotlin.Long? = null + +) { + @Serializable + enum class FieldType(val value: kotlin.String) { + @SerialName(value = "text") Text("text"), + @SerialName(value = "number") Number("number"), + @SerialName(value = "boolean") Boolean("boolean"), + @SerialName(value = "date") Date("date"); + } + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ItemCustomFieldCreateRequest.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ItemCustomFieldCreateRequest.kt new file mode 100644 index 0000000..6929f28 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ItemCustomFieldCreateRequest.kt @@ -0,0 +1,56 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class ItemCustomFieldCreateRequest ( + @SerialName(value = "field_def_id") + val fieldDefId: kotlin.String, + + @SerialName(value = "name") + val name: kotlin.String, + + @SerialName(value = "field_type") + val fieldType: ItemCustomFieldCreateRequest.FieldType, + + @SerialName(value = "text_value") + val textValue: kotlin.String?, + + @Contextual @SerialName(value = "number_value") + val numberValue: java.math.BigDecimal?, + + @SerialName(value = "bool_value") + val boolValue: kotlin.Boolean?, + + @Contextual @SerialName(value = "date_value") + val dateValue: java.time.LocalDate? + +) { + @Serializable + enum class FieldType(val value: kotlin.String) { + @SerialName(value = "text") Text("text"), + @SerialName(value = "number") Number("number"), + @SerialName(value = "boolean") Boolean("boolean"), + @SerialName(value = "date") Date("date"); + } + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ItemCustomFieldListResponse.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ItemCustomFieldListResponse.kt new file mode 100644 index 0000000..233c4a4 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ItemCustomFieldListResponse.kt @@ -0,0 +1,34 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import dev.hho.android.data.apiclient.generated.models.ItemCustomField + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class ItemCustomFieldListResponse ( + + @SerialName(value = "custom_fields") + val customFields: kotlin.collections.List + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ItemCustomFieldUpdateRequest.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ItemCustomFieldUpdateRequest.kt new file mode 100644 index 0000000..184312c --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ItemCustomFieldUpdateRequest.kt @@ -0,0 +1,60 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class ItemCustomFieldUpdateRequest ( + + @SerialName(value = "field_def_id") + val fieldDefId: kotlin.String, + + @SerialName(value = "name") + val name: kotlin.String, + + @SerialName(value = "field_type") + val fieldType: ItemCustomFieldUpdateRequest.FieldType, + + @SerialName(value = "text_value") + val textValue: kotlin.String?, + + @Contextual @SerialName(value = "number_value") + val numberValue: java.math.BigDecimal?, + + @SerialName(value = "bool_value") + val boolValue: kotlin.Boolean?, + + @Contextual @SerialName(value = "date_value") + val dateValue: java.time.LocalDate?, + + @SerialName(value = "version") + val version: kotlin.Long + +) { + @Serializable + enum class FieldType(val value: kotlin.String) { + @SerialName(value = "text") Text("text"), + @SerialName(value = "number") Number("number"), + @SerialName(value = "boolean") Boolean("boolean"), + @SerialName(value = "date") Date("date"); + } + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ItemLabelAssignment.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ItemLabelAssignment.kt new file mode 100644 index 0000000..3382b6f --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ItemLabelAssignment.kt @@ -0,0 +1,35 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class ItemLabelAssignment ( + + @SerialName(value = "item_id") + val itemId: kotlin.String, + + @SerialName(value = "label_id") + val labelId: kotlin.String + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ItemListResponse.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ItemListResponse.kt new file mode 100644 index 0000000..49982b3 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ItemListResponse.kt @@ -0,0 +1,34 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import dev.hho.android.data.apiclient.generated.models.Item + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class ItemListResponse ( + + @SerialName(value = "items") + val items: kotlin.collections.List + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ItemUpdateRequest.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ItemUpdateRequest.kt new file mode 100644 index 0000000..d6aa4ac --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/ItemUpdateRequest.kt @@ -0,0 +1,44 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class ItemUpdateRequest ( + + @SerialName(value = "name") + val name: kotlin.String, + + @SerialName(value = "version") + val version: kotlin.Long, + + @SerialName(value = "description") + val description: kotlin.String? = null, + + @SerialName(value = "location_id") + val locationId: kotlin.String? = null, + + @SerialName(value = "quantity") + val quantity: kotlin.Long? = null + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/Label.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/Label.kt new file mode 100644 index 0000000..d5a540a --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/Label.kt @@ -0,0 +1,47 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class Label ( + + @SerialName(value = "id") + val id: kotlin.String, + + @SerialName(value = "name") + val name: kotlin.String, + + @SerialName(value = "color") + val color: kotlin.String, + + @SerialName(value = "created_at") + val createdAt: kotlin.Long, + + @SerialName(value = "updated_at") + val updatedAt: kotlin.Long, + + @SerialName(value = "version") + val version: kotlin.Long + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/LabelCreateRequest.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/LabelCreateRequest.kt new file mode 100644 index 0000000..92eb281 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/LabelCreateRequest.kt @@ -0,0 +1,35 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class LabelCreateRequest ( + + @SerialName(value = "name") + val name: kotlin.String, + + @SerialName(value = "color") + val color: kotlin.String + +) { + +} + diff --git a/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/LabelListResponse.kt b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/LabelListResponse.kt new file mode 100644 index 0000000..88df4c2 --- /dev/null +++ b/android-app/app/src/main/kotlin/dev/hho/android/data/apiclient/generated/models/LabelListResponse.kt @@ -0,0 +1,34 @@ +@file:Suppress( + "ArrayInDataClass", + "DuplicatedCode", + "EnumEntryName", + "RemoveRedundantQualifierName", + "RemoveRedundantCallsOfConversionMethods", + "REDUNDANT_CALL_OF_CONVERSION_METHOD", + "RedundantUnitReturnType", + "RemoveEmptyClassBody", + "UnnecessaryVariable", + "UnusedImport", + "UnnecessaryVariable", + "unused" +) + +package dev.hho.android.data.apiclient.generated.models + +import dev.hho.android.data.apiclient.generated.models.Label + +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerialName +import kotlinx.serialization.Contextual + +@Serializable + +data class LabelListResponse ( + + @SerialName(value = "labels") + val labels: kotlin.collections.List