From 3185eac8f8074c4122d3d21cd5fd90f6f68696c6 Mon Sep 17 00:00:00 2001 From: OCA Bot Date: Tue, 8 Oct 2024 12:43:33 +0000 Subject: [PATCH 001/152] Initial commit --- .copier-answers.yml | 27 ++ .editorconfig | 20 + .eslintrc.yml | 188 +++++++++ .github/workflows/pre-commit.yml | 46 +++ .github/workflows/stale.yml | 69 ++++ .github/workflows/test.yml | 73 ++++ .gitignore | 88 ++++ .pre-commit-config.yaml | 127 ++++++ .prettierrc.yml | 8 + .pylintrc | 123 ++++++ .pylintrc-mandatory | 98 +++++ .ruff.toml | 30 ++ LICENSE | 661 +++++++++++++++++++++++++++++++ README.md | 37 ++ 14 files changed, 1595 insertions(+) create mode 100644 .copier-answers.yml create mode 100644 .editorconfig create mode 100644 .eslintrc.yml create mode 100644 .github/workflows/pre-commit.yml create mode 100644 .github/workflows/stale.yml create mode 100644 .github/workflows/test.yml create mode 100644 .gitignore create mode 100644 .pre-commit-config.yaml create mode 100644 .prettierrc.yml create mode 100644 .pylintrc create mode 100644 .pylintrc-mandatory create mode 100644 .ruff.toml create mode 100644 LICENSE create mode 100644 README.md diff --git a/.copier-answers.yml b/.copier-answers.yml new file mode 100644 index 000000000000..bda1955d8c1c --- /dev/null +++ b/.copier-answers.yml @@ -0,0 +1,27 @@ +# Do NOT update manually; changes here will be overwritten by Copier +_commit: v1.26 +_src_path: git+https://github.com/OCA/oca-addons-repo-template +additional_ruff_rules: [] +ci: GitHub +convert_readme_fragments_to_markdown: true +enable_checklog_odoo: true +generate_requirements_txt: true +github_check_license: true +github_ci_extra_env: {} +github_enable_codecov: true +github_enable_makepot: true +github_enable_stale_action: true +github_enforce_dev_status_compatibility: true +include_wkhtmltopdf: false +odoo_test_flavor: Both +odoo_version: 18.0 +org_name: Odoo Community Association (OCA) +org_slug: OCA +rebel_module_groups: [] +repo_description: l10n-italy +repo_name: l10n-italy +repo_slug: l10n-italy +repo_website: https://github.com/OCA/l10n-italy +use_pyproject_toml: true +use_ruff: true + diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000000..bfd7ac53df9f --- /dev/null +++ b/.editorconfig @@ -0,0 +1,20 @@ +# Configuration for known file extensions +[*.{css,js,json,less,md,py,rst,sass,scss,xml,yaml,yml}] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.{json,yml,yaml,rst,md}] +indent_size = 2 + +# Do not configure editor for libs and autogenerated content +[{*/static/{lib,src/lib}/**,*/static/description/index.html,*/readme/../README.rst}] +charset = unset +end_of_line = unset +indent_size = unset +indent_style = unset +insert_final_newline = false +trim_trailing_whitespace = false diff --git a/.eslintrc.yml b/.eslintrc.yml new file mode 100644 index 000000000000..0b382039586a --- /dev/null +++ b/.eslintrc.yml @@ -0,0 +1,188 @@ +env: + browser: true + es6: true + +# See https://github.com/OCA/odoo-community.org/issues/37#issuecomment-470686449 +parserOptions: + ecmaVersion: 2022 + +overrides: + - files: + - "**/*.esm.js" + parserOptions: + sourceType: module + +# Globals available in Odoo that shouldn't produce errorings +globals: + _: readonly + $: readonly + fuzzy: readonly + jQuery: readonly + moment: readonly + odoo: readonly + openerp: readonly + owl: readonly + luxon: readonly + +# Styling is handled by Prettier, so we only need to enable AST rules; +# see https://github.com/OCA/maintainer-quality-tools/pull/618#issuecomment-558576890 +rules: + accessor-pairs: warn + array-callback-return: warn + callback-return: warn + capitalized-comments: + - warn + - always + - ignoreConsecutiveComments: true + ignoreInlineComments: true + complexity: + - warn + - 15 + constructor-super: warn + dot-notation: warn + eqeqeq: warn + global-require: warn + handle-callback-err: warn + id-blacklist: warn + id-match: warn + init-declarations: error + max-depth: warn + max-nested-callbacks: warn + max-statements-per-line: warn + no-alert: warn + no-array-constructor: warn + no-caller: warn + no-case-declarations: warn + no-class-assign: warn + no-cond-assign: error + no-const-assign: error + no-constant-condition: warn + no-control-regex: warn + no-debugger: error + no-delete-var: warn + no-div-regex: warn + no-dupe-args: error + no-dupe-class-members: error + no-dupe-keys: error + no-duplicate-case: error + no-duplicate-imports: error + no-else-return: warn + no-empty-character-class: warn + no-empty-function: error + no-empty-pattern: error + no-empty: warn + no-eq-null: error + no-eval: error + no-ex-assign: error + no-extend-native: warn + no-extra-bind: warn + no-extra-boolean-cast: warn + no-extra-label: warn + no-fallthrough: warn + no-func-assign: error + no-global-assign: error + no-implicit-coercion: + - warn + - allow: ["~"] + no-implicit-globals: warn + no-implied-eval: warn + no-inline-comments: warn + no-inner-declarations: warn + no-invalid-regexp: warn + no-irregular-whitespace: warn + no-iterator: warn + no-label-var: warn + no-labels: warn + no-lone-blocks: warn + no-lonely-if: error + no-mixed-requires: error + no-multi-str: warn + no-native-reassign: error + no-negated-condition: warn + no-negated-in-lhs: error + no-new-func: warn + no-new-object: warn + no-new-require: warn + no-new-symbol: warn + no-new-wrappers: warn + no-new: warn + no-obj-calls: warn + no-octal-escape: warn + no-octal: warn + no-param-reassign: warn + no-path-concat: warn + no-process-env: warn + no-process-exit: warn + no-proto: warn + no-prototype-builtins: warn + no-redeclare: warn + no-regex-spaces: warn + no-restricted-globals: warn + no-restricted-imports: warn + no-restricted-modules: warn + no-restricted-syntax: warn + no-return-assign: error + no-script-url: warn + no-self-assign: warn + no-self-compare: warn + no-sequences: warn + no-shadow-restricted-names: warn + no-shadow: warn + no-sparse-arrays: warn + no-sync: warn + no-this-before-super: warn + no-throw-literal: warn + no-undef-init: warn + no-undef: error + no-unmodified-loop-condition: warn + no-unneeded-ternary: error + no-unreachable: error + no-unsafe-finally: error + no-unused-expressions: error + no-unused-labels: error + no-unused-vars: error + no-use-before-define: error + no-useless-call: warn + no-useless-computed-key: warn + no-useless-concat: warn + no-useless-constructor: warn + no-useless-escape: warn + no-useless-rename: warn + no-void: warn + no-with: warn + operator-assignment: [error, always] + prefer-const: warn + radix: warn + require-yield: warn + sort-imports: warn + spaced-comment: [error, always] + strict: [error, function] + use-isnan: error + valid-jsdoc: + - warn + - prefer: + arg: param + argument: param + augments: extends + constructor: class + exception: throws + func: function + method: function + prop: property + return: returns + virtual: abstract + yield: yields + preferType: + array: Array + bool: Boolean + boolean: Boolean + number: Number + object: Object + str: String + string: String + requireParamDescription: false + requireReturn: false + requireReturnDescription: false + requireReturnType: false + valid-typeof: warn + yoda: warn diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 000000000000..b53a386cf5fa --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,46 @@ +name: pre-commit + +on: + pull_request: + branches: + - "18.0*" + push: + branches: + - "18.0" + - "18.0-ocabot-*" + +jobs: + pre-commit: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v2 + with: + python-version: "3.11" + - name: Get python version + run: echo "PY=$(python -VV | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV + - uses: actions/cache@v1 + with: + path: ~/.cache/pre-commit + key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }} + - name: Install pre-commit + run: pip install pre-commit + - name: Run pre-commit + run: pre-commit run --all-files --show-diff-on-failure --color=always + env: + # Consider valid a PR that changes README fragments but doesn't + # change the README.rst file itself. It's not really a problem + # because the bot will update it anyway after merge. This way, we + # lower the barrier for functional contributors that want to fix the + # readme fragments, while still letting developers get README + # auto-generated (which also helps functionals when using runboat). + # DOCS https://pre-commit.com/#temporarily-disabling-hooks + SKIP: oca-gen-addon-readme + - name: Check that all files generated by pre-commit are in git + run: | + newfiles="$(git ls-files --others --exclude-from=.gitignore)" + if [ "$newfiles" != "" ] ; then + echo "Please check-in the following files:" + echo "$newfiles" + exit 1 + fi diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 000000000000..fa17fcd4e854 --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,69 @@ +name: Mark stale issues and pull requests + +on: + schedule: + - cron: "0 12 * * 0" + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - name: Stale PRs and issues policy + uses: actions/stale@v9 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + # General settings. + ascending: true + remove-stale-when-updated: true + # Pull Requests settings. + # 120+30 day stale policy for PRs + # * Except PRs marked as "no stale" + days-before-pr-stale: 120 + days-before-pr-close: 30 + exempt-pr-labels: "no stale" + stale-pr-label: "stale" + stale-pr-message: > + There hasn't been any activity on this pull request in the past 4 months, so + it has been marked as stale and it will be closed automatically if no + further activity occurs in the next 30 days. + + If you want this PR to never become stale, please ask a PSC member to apply + the "no stale" label. + # Issues settings. + # 180+30 day stale policy for open issues + # * Except Issues marked as "no stale" + days-before-issue-stale: 180 + days-before-issue-close: 30 + exempt-issue-labels: "no stale,needs more information" + stale-issue-label: "stale" + stale-issue-message: > + There hasn't been any activity on this issue in the past 6 months, so it has + been marked as stale and it will be closed automatically if no further + activity occurs in the next 30 days. + + If you want this issue to never become stale, please ask a PSC member to + apply the "no stale" label. + + # 15+30 day stale policy for issues pending more information + # * Issues that are pending more information + # * Except Issues marked as "no stale" + - name: Needs more information stale issues policy + uses: actions/stale@v9 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + ascending: true + only-labels: "needs more information" + exempt-issue-labels: "no stale" + days-before-stale: 15 + days-before-close: 30 + days-before-pr-stale: -1 + days-before-pr-close: -1 + remove-stale-when-updated: true + stale-issue-label: "stale" + stale-issue-message: > + This issue needs more information and there hasn't been any activity + recently, so it has been marked as stale and it will be closed automatically + if no further activity occurs in the next 30 days. + + If you think this is a mistake, please ask a PSC member to remove the "needs + more information" label. diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 000000000000..6f4b2fd523cc --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,73 @@ +name: tests + +on: + pull_request: + branches: + - "18.0*" + push: + branches: + - "18.0" + - "18.0-ocabot-*" + +jobs: + unreleased-deps: + runs-on: ubuntu-latest + name: Detect unreleased dependencies + steps: + - uses: actions/checkout@v3 + - run: | + for reqfile in requirements.txt test-requirements.txt ; do + if [ -f ${reqfile} ] ; then + result=0 + # reject non-comment lines that contain a / (i.e. URLs, relative paths) + grep "^[^#].*/" ${reqfile} || result=$? + if [ $result -eq 0 ] ; then + echo "Unreleased dependencies found in ${reqfile}." + exit 1 + fi + fi + done + test: + runs-on: ubuntu-22.04 + container: ${{ matrix.container }} + name: ${{ matrix.name }} + strategy: + fail-fast: false + matrix: + include: + - container: ghcr.io/oca/oca-ci/py3.10-odoo18.0:latest + name: test with Odoo + - container: ghcr.io/oca/oca-ci/py3.10-ocb18.0:latest + name: test with OCB + makepot: "true" + services: + postgres: + image: postgres:12.0 + env: + POSTGRES_USER: odoo + POSTGRES_PASSWORD: odoo + POSTGRES_DB: odoo + ports: + - 5432:5432 + env: + OCA_ENABLE_CHECKLOG_ODOO: "1" + steps: + - uses: actions/checkout@v3 + with: + persist-credentials: false + - name: Install addons and dependencies + run: oca_install_addons + - name: Check licenses + run: manifestoo -d . check-licenses + - name: Check development status + run: manifestoo -d . check-dev-status --default-dev-status=Beta + - name: Initialize test db + run: oca_init_test_database + - name: Run tests + run: oca_run_tests + - uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} + - name: Update .pot files + run: oca_export_and_push_pot https://x-access-token:${{ secrets.GIT_PUSH_TOKEN }}@github.com/${{ github.repository }} + if: ${{ matrix.makepot == 'true' && github.event_name == 'push' && github.repository_owner == 'OCA' }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000000..6ec07a054bd2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,88 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +/.venv +/.pytest_cache +/.ruff_cache + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +bin/ +build/ +develop-eggs/ +dist/ +eggs/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg +*.eggs + +# Windows installers +*.msi + +# Debian packages +*.deb + +# Redhat packages +*.rpm + +# MacOS packages +*.dmg +*.pkg + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.cache +nosetests.xml +coverage.xml + +# Translations +*.mo + +# Pycharm +.idea + +# Eclipse +.settings + +# Visual Studio cache/options directory +.vs/ +.vscode + +# OSX Files +.DS_Store + +# Django stuff: +*.log + +# Mr Developer +.mr.developer.cfg +.project +.pydevproject + +# Rope +.ropeproject + +# Sphinx documentation +docs/_build/ + +# Backup files +*~ +*.swp + +# OCA rules +!static/lib/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 000000000000..a9879eb87688 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,127 @@ +exclude: | + (?x) + # NOT INSTALLABLE ADDONS + # END NOT INSTALLABLE ADDONS + # Files and folders generated by bots, to avoid loops + ^setup/|/static/description/index\.html$| + # We don't want to mess with tool-generated files + .svg$|/tests/([^/]+/)?cassettes/|^.copier-answers.yml$|^.github/| + # Maybe reactivate this when all README files include prettier ignore tags? + ^README\.md$| + # Library files can have extraneous formatting (even minimized) + /static/(src/)?lib/| + # Repos using Sphinx to generate docs don't need prettying + ^docs/_templates/.*\.html$| + # Don't bother non-technical authors with formatting issues in docs + readme/.*\.(rst|md)$| + # Ignore build and dist directories in addons + /build/|/dist/| + # Ignore test files in addons + /tests/samples/.*| + # You don't usually want a bot to modify your legal texts + (LICENSE.*|COPYING.*) +default_language_version: + python: python3 + node: "16.17.0" +repos: + - repo: local + hooks: + # These files are most likely copier diff rejection junks; if found, + # review them manually, fix the problem (if needed) and remove them + - id: forbidden-files + name: forbidden files + entry: found forbidden files; remove them + language: fail + files: "\\.rej$" + - id: en-po-files + name: en.po files cannot exist + entry: found a en.po file + language: fail + files: '[a-zA-Z0-9_]*/i18n/en\.po$' + - repo: https://github.com/sbidoul/whool + rev: v1.2 + hooks: + - id: whool-init + - repo: https://github.com/oca/maintainer-tools + rev: bf9ecb9938b6a5deca0ff3d870fbd3f33341fded + hooks: + # update the NOT INSTALLABLE ADDONS section above + - id: oca-update-pre-commit-excluded-addons + - id: oca-fix-manifest-website + args: ["https://github.com/OCA/l10n-italy"] + - id: oca-gen-addon-readme + args: + - --addons-dir=. + - --branch=18.0 + - --org-name=OCA + - --repo-name=l10n-italy + - --if-source-changed + - --keep-source-digest + - --convert-fragments-to-markdown + - id: oca-gen-external-dependencies + - repo: https://github.com/OCA/odoo-pre-commit-hooks + rev: v0.0.33 + hooks: + - id: oca-checks-odoo-module + - id: oca-checks-po + args: + - --disable=po-pretty-format + - repo: https://github.com/pre-commit/mirrors-prettier + rev: v2.7.1 + hooks: + - id: prettier + name: prettier (with plugin-xml) + additional_dependencies: + - "prettier@2.7.1" + - "@prettier/plugin-xml@2.2.0" + args: + - --plugin=@prettier/plugin-xml + files: \.(css|htm|html|js|json|jsx|less|md|scss|toml|ts|xml|yaml|yml)$ + - repo: https://github.com/pre-commit/mirrors-eslint + rev: v8.24.0 + hooks: + - id: eslint + verbose: true + args: + - --color + - --fix + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.6.0 + hooks: + - id: trailing-whitespace + # exclude autogenerated files + exclude: /README\.rst$|\.pot?$ + - id: end-of-file-fixer + # exclude autogenerated files + exclude: /README\.rst$|\.pot?$ + - id: debug-statements + - id: fix-encoding-pragma + args: ["--remove"] + - id: check-case-conflict + - id: check-docstring-first + - id: check-executables-have-shebangs + - id: check-merge-conflict + # exclude files where underlines are not distinguishable from merge conflicts + exclude: /README\.rst$|^docs/.*\.rst$ + - id: check-symlinks + - id: check-xml + - id: mixed-line-ending + args: ["--fix=lf"] + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.6.8 + hooks: + - id: ruff + args: [--fix, --exit-non-zero-on-fix] + - id: ruff-format + - repo: https://github.com/OCA/pylint-odoo + rev: v9.0.4 + hooks: + - id: pylint_odoo + name: pylint with optional checks + args: + - --rcfile=.pylintrc + - --exit-zero + verbose: true + - id: pylint_odoo + args: + - --rcfile=.pylintrc-mandatory diff --git a/.prettierrc.yml b/.prettierrc.yml new file mode 100644 index 000000000000..5b6d4b361ace --- /dev/null +++ b/.prettierrc.yml @@ -0,0 +1,8 @@ +# Defaults for all prettier-supported languages. +# Prettier will complete this with settings from .editorconfig file. +bracketSpacing: false +printWidth: 88 +proseWrap: always +semi: true +trailingComma: "es5" +xmlWhitespaceSensitivity: "strict" diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 000000000000..7c62b6d2edde --- /dev/null +++ b/.pylintrc @@ -0,0 +1,123 @@ + + +[MASTER] +load-plugins=pylint_odoo +score=n + +[ODOOLINT] +readme-template-url="https://github.com/OCA/maintainer-tools/blob/master/template/module/README.rst" +manifest-required-authors=Odoo Community Association (OCA) +manifest-required-keys=license +manifest-deprecated-keys=description,active +license-allowed=AGPL-3,GPL-2,GPL-2 or any later version,GPL-3,GPL-3 or any later version,LGPL-3 +valid-odoo-versions=18.0 + +[MESSAGES CONTROL] +disable=all + +# This .pylintrc contains optional AND mandatory checks and is meant to be +# loaded in an IDE to have it check everything, in the hope this will make +# optional checks more visible to contributors who otherwise never look at a +# green travis to see optional checks that failed. +# .pylintrc-mandatory containing only mandatory checks is used the pre-commit +# config as a blocking check. + +enable=anomalous-backslash-in-string, + api-one-deprecated, + api-one-multi-together, + assignment-from-none, + attribute-deprecated, + class-camelcase, + dangerous-default-value, + dangerous-view-replace-wo-priority, + development-status-allowed, + duplicate-id-csv, + duplicate-key, + duplicate-xml-fields, + duplicate-xml-record-id, + eval-referenced, + eval-used, + incoherent-interpreter-exec-perm, + license-allowed, + manifest-author-string, + manifest-deprecated-key, + manifest-required-author, + manifest-required-key, + manifest-version-format, + method-compute, + method-inverse, + method-required-super, + method-search, + openerp-exception-warning, + pointless-statement, + pointless-string-statement, + print-used, + redundant-keyword-arg, + redundant-modulename-xml, + reimported, + relative-import, + return-in-init, + rst-syntax-error, + sql-injection, + too-few-format-args, + translation-field, + translation-required, + unreachable, + use-vim-comment, + wrong-tabs-instead-of-spaces, + xml-syntax-error, + attribute-string-redundant, + character-not-valid-in-resource-link, + consider-merging-classes-inherited, + context-overridden, + create-user-wo-reset-password, + dangerous-filter-wo-user, + dangerous-qweb-replace-wo-priority, + deprecated-data-xml-node, + deprecated-openerp-xml-node, + duplicate-po-message-definition, + except-pass, + file-not-used, + invalid-commit, + manifest-maintainers-list, + missing-newline-extrafiles, + missing-readme, + missing-return, + odoo-addons-relative-import, + old-api7-method-defined, + po-msgstr-variables, + po-syntax-error, + renamed-field-parameter, + resource-not-exist, + str-format-used, + test-folder-imported, + translation-contains-variable, + translation-positional-used, + unnecessary-utf8-coding-comment, + website-manifest-key-not-valid-uri, + xml-attribute-translatable, + xml-deprecated-qweb-directive, + xml-deprecated-tree-attribute, + external-request-timeout, + # messages that do not cause the lint step to fail + consider-merging-classes-inherited, + create-user-wo-reset-password, + dangerous-filter-wo-user, + deprecated-module, + file-not-used, + invalid-commit, + missing-manifest-dependency, + missing-newline-extrafiles, + missing-readme, + no-utf8-coding-comment, + odoo-addons-relative-import, + old-api7-method-defined, + redefined-builtin, + too-complex, + unnecessary-utf8-coding-comment + + +[REPORTS] +msg-template={path}:{line}: [{msg_id}({symbol}), {obj}] {msg} +output-format=colorized +reports=no diff --git a/.pylintrc-mandatory b/.pylintrc-mandatory new file mode 100644 index 000000000000..018fd61cdd70 --- /dev/null +++ b/.pylintrc-mandatory @@ -0,0 +1,98 @@ + +[MASTER] +load-plugins=pylint_odoo +score=n + +[ODOOLINT] +readme-template-url="https://github.com/OCA/maintainer-tools/blob/master/template/module/README.rst" +manifest-required-authors=Odoo Community Association (OCA) +manifest-required-keys=license +manifest-deprecated-keys=description,active +license-allowed=AGPL-3,GPL-2,GPL-2 or any later version,GPL-3,GPL-3 or any later version,LGPL-3 +valid-odoo-versions=18.0 + +[MESSAGES CONTROL] +disable=all + +enable=anomalous-backslash-in-string, + api-one-deprecated, + api-one-multi-together, + assignment-from-none, + attribute-deprecated, + class-camelcase, + dangerous-default-value, + dangerous-view-replace-wo-priority, + development-status-allowed, + duplicate-id-csv, + duplicate-key, + duplicate-xml-fields, + duplicate-xml-record-id, + eval-referenced, + eval-used, + incoherent-interpreter-exec-perm, + license-allowed, + manifest-author-string, + manifest-deprecated-key, + manifest-required-author, + manifest-required-key, + manifest-version-format, + method-compute, + method-inverse, + method-required-super, + method-search, + openerp-exception-warning, + pointless-statement, + pointless-string-statement, + print-used, + redundant-keyword-arg, + redundant-modulename-xml, + reimported, + relative-import, + return-in-init, + rst-syntax-error, + sql-injection, + too-few-format-args, + translation-field, + translation-required, + unreachable, + use-vim-comment, + wrong-tabs-instead-of-spaces, + xml-syntax-error, + attribute-string-redundant, + character-not-valid-in-resource-link, + consider-merging-classes-inherited, + context-overridden, + create-user-wo-reset-password, + dangerous-filter-wo-user, + dangerous-qweb-replace-wo-priority, + deprecated-data-xml-node, + deprecated-openerp-xml-node, + duplicate-po-message-definition, + except-pass, + file-not-used, + invalid-commit, + manifest-maintainers-list, + missing-newline-extrafiles, + missing-readme, + missing-return, + odoo-addons-relative-import, + old-api7-method-defined, + po-msgstr-variables, + po-syntax-error, + renamed-field-parameter, + resource-not-exist, + str-format-used, + test-folder-imported, + translation-contains-variable, + translation-positional-used, + unnecessary-utf8-coding-comment, + website-manifest-key-not-valid-uri, + xml-attribute-translatable, + xml-deprecated-qweb-directive, + xml-deprecated-tree-attribute, + external-request-timeout + +[REPORTS] +msg-template={path}:{line}: [{msg_id}({symbol}), {obj}] {msg} +output-format=colorized +reports=no diff --git a/.ruff.toml b/.ruff.toml new file mode 100644 index 000000000000..0f1e35f24803 --- /dev/null +++ b/.ruff.toml @@ -0,0 +1,30 @@ + +target-version = "py310" +fix = true + +[lint] +extend-select = [ + "B", + "C90", + "E501", # line too long (default 88) + "I", # isort + "UP", # pyupgrade +] +exclude = ["setup/*"] + +[format] +exclude = ["setup/*"] + +[lint.per-file-ignores] +"__init__.py" = ["F401", "I001"] # ignore unused and unsorted imports in __init__.py +"__manifest__.py" = ["B018"] # useless expression + +[lint.isort] +section-order = ["future", "standard-library", "third-party", "odoo", "odoo-addons", "first-party", "local-folder"] + +[lint.isort.sections] +"odoo" = ["odoo"] +"odoo-addons" = ["odoo.addons"] + +[lint.mccabe] +max-complexity = 16 diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000000..be3f7b28e564 --- /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 new file mode 100644 index 000000000000..2d48d36f6d6a --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ + +[![Runboat](https://img.shields.io/badge/runboat-Try%20me-875A7B.png)](https://runboat.odoo-community.org/builds?repo=OCA/l10n-italy&target_branch=18.0) +[![Pre-commit Status](https://github.com/OCA/l10n-italy/actions/workflows/pre-commit.yml/badge.svg?branch=18.0)](https://github.com/OCA/l10n-italy/actions/workflows/pre-commit.yml?query=branch%3A18.0) +[![Build Status](https://github.com/OCA/l10n-italy/actions/workflows/test.yml/badge.svg?branch=18.0)](https://github.com/OCA/l10n-italy/actions/workflows/test.yml?query=branch%3A18.0) +[![codecov](https://codecov.io/gh/OCA/l10n-italy/branch/18.0/graph/badge.svg)](https://codecov.io/gh/OCA/l10n-italy) +[![Translation Status](https://translation.odoo-community.org/widgets/l10n-italy-18-0/-/svg-badge.svg)](https://translation.odoo-community.org/engage/l10n-italy-18-0/?utm_source=widget) + + + +# l10n-italy + +l10n-italy + + + + + +[//]: # (addons) + +This part will be replaced when running the oca-gen-addons-table script from OCA/maintainer-tools. + +[//]: # (end addons) + + + +## Licenses + +This repository is licensed under [AGPL-3.0](LICENSE). + +However, each module can have a totally different license, as long as they adhere to Odoo Community Association (OCA) +policy. Consult each module's `__manifest__.py` file, which contains a `license` key +that explains its license. + +---- +OCA, or the [Odoo Community Association](http://odoo-community.org/), is a nonprofit +organization whose mission is to support the collaborative development of Odoo features +and promote its widespread use. From 3c74d8d038e809406116c35e9c02066aee4ff661 Mon Sep 17 00:00:00 2001 From: Simone Rubino Date: Thu, 17 Oct 2024 16:13:21 +0200 Subject: [PATCH 002/152] Updated from template --- .copier-answers.yml | 2 +- .eslintrc.yml | 188 ------------------------------------- .pre-commit-config.yaml | 34 ++++--- .prettierrc.yml | 8 -- eslint.config.cjs | 202 ++++++++++++++++++++++++++++++++++++++++ prettier.config.cjs | 14 +++ 6 files changed, 239 insertions(+), 209 deletions(-) delete mode 100644 .eslintrc.yml delete mode 100644 .prettierrc.yml create mode 100644 eslint.config.cjs create mode 100644 prettier.config.cjs diff --git a/.copier-answers.yml b/.copier-answers.yml index bda1955d8c1c..c0bce998ce3f 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -1,5 +1,5 @@ # Do NOT update manually; changes here will be overwritten by Copier -_commit: v1.26 +_commit: v1.27 _src_path: git+https://github.com/OCA/oca-addons-repo-template additional_ruff_rules: [] ci: GitHub diff --git a/.eslintrc.yml b/.eslintrc.yml deleted file mode 100644 index 0b382039586a..000000000000 --- a/.eslintrc.yml +++ /dev/null @@ -1,188 +0,0 @@ -env: - browser: true - es6: true - -# See https://github.com/OCA/odoo-community.org/issues/37#issuecomment-470686449 -parserOptions: - ecmaVersion: 2022 - -overrides: - - files: - - "**/*.esm.js" - parserOptions: - sourceType: module - -# Globals available in Odoo that shouldn't produce errorings -globals: - _: readonly - $: readonly - fuzzy: readonly - jQuery: readonly - moment: readonly - odoo: readonly - openerp: readonly - owl: readonly - luxon: readonly - -# Styling is handled by Prettier, so we only need to enable AST rules; -# see https://github.com/OCA/maintainer-quality-tools/pull/618#issuecomment-558576890 -rules: - accessor-pairs: warn - array-callback-return: warn - callback-return: warn - capitalized-comments: - - warn - - always - - ignoreConsecutiveComments: true - ignoreInlineComments: true - complexity: - - warn - - 15 - constructor-super: warn - dot-notation: warn - eqeqeq: warn - global-require: warn - handle-callback-err: warn - id-blacklist: warn - id-match: warn - init-declarations: error - max-depth: warn - max-nested-callbacks: warn - max-statements-per-line: warn - no-alert: warn - no-array-constructor: warn - no-caller: warn - no-case-declarations: warn - no-class-assign: warn - no-cond-assign: error - no-const-assign: error - no-constant-condition: warn - no-control-regex: warn - no-debugger: error - no-delete-var: warn - no-div-regex: warn - no-dupe-args: error - no-dupe-class-members: error - no-dupe-keys: error - no-duplicate-case: error - no-duplicate-imports: error - no-else-return: warn - no-empty-character-class: warn - no-empty-function: error - no-empty-pattern: error - no-empty: warn - no-eq-null: error - no-eval: error - no-ex-assign: error - no-extend-native: warn - no-extra-bind: warn - no-extra-boolean-cast: warn - no-extra-label: warn - no-fallthrough: warn - no-func-assign: error - no-global-assign: error - no-implicit-coercion: - - warn - - allow: ["~"] - no-implicit-globals: warn - no-implied-eval: warn - no-inline-comments: warn - no-inner-declarations: warn - no-invalid-regexp: warn - no-irregular-whitespace: warn - no-iterator: warn - no-label-var: warn - no-labels: warn - no-lone-blocks: warn - no-lonely-if: error - no-mixed-requires: error - no-multi-str: warn - no-native-reassign: error - no-negated-condition: warn - no-negated-in-lhs: error - no-new-func: warn - no-new-object: warn - no-new-require: warn - no-new-symbol: warn - no-new-wrappers: warn - no-new: warn - no-obj-calls: warn - no-octal-escape: warn - no-octal: warn - no-param-reassign: warn - no-path-concat: warn - no-process-env: warn - no-process-exit: warn - no-proto: warn - no-prototype-builtins: warn - no-redeclare: warn - no-regex-spaces: warn - no-restricted-globals: warn - no-restricted-imports: warn - no-restricted-modules: warn - no-restricted-syntax: warn - no-return-assign: error - no-script-url: warn - no-self-assign: warn - no-self-compare: warn - no-sequences: warn - no-shadow-restricted-names: warn - no-shadow: warn - no-sparse-arrays: warn - no-sync: warn - no-this-before-super: warn - no-throw-literal: warn - no-undef-init: warn - no-undef: error - no-unmodified-loop-condition: warn - no-unneeded-ternary: error - no-unreachable: error - no-unsafe-finally: error - no-unused-expressions: error - no-unused-labels: error - no-unused-vars: error - no-use-before-define: error - no-useless-call: warn - no-useless-computed-key: warn - no-useless-concat: warn - no-useless-constructor: warn - no-useless-escape: warn - no-useless-rename: warn - no-void: warn - no-with: warn - operator-assignment: [error, always] - prefer-const: warn - radix: warn - require-yield: warn - sort-imports: warn - spaced-comment: [error, always] - strict: [error, function] - use-isnan: error - valid-jsdoc: - - warn - - prefer: - arg: param - argument: param - augments: extends - constructor: class - exception: throws - func: function - method: function - prop: property - return: returns - virtual: abstract - yield: yields - preferType: - array: Array - bool: Boolean - boolean: Boolean - number: Number - object: Object - str: String - string: String - requireParamDescription: false - requireReturn: false - requireReturnDescription: false - requireReturnType: false - valid-typeof: warn - yoda: warn diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a9879eb87688..9e8b1fe7e9ed 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,7 +5,7 @@ exclude: | # Files and folders generated by bots, to avoid loops ^setup/|/static/description/index\.html$| # We don't want to mess with tool-generated files - .svg$|/tests/([^/]+/)?cassettes/|^.copier-answers.yml$|^.github/| + .svg$|/tests/([^/]+/)?cassettes/|^.copier-answers.yml$|^.github/|^eslint.config.cjs|^prettier.config.cjs| # Maybe reactivate this when all README files include prettier ignore tags? ^README\.md$| # Library files can have extraneous formatting (even minimized) @@ -22,7 +22,7 @@ exclude: | (LICENSE.*|COPYING.*) default_language_version: python: python3 - node: "16.17.0" + node: "22.9.0" repos: - repo: local hooks: @@ -66,25 +66,35 @@ repos: - id: oca-checks-po args: - --disable=po-pretty-format - - repo: https://github.com/pre-commit/mirrors-prettier - rev: v2.7.1 + - repo: local hooks: - id: prettier name: prettier (with plugin-xml) - additional_dependencies: - - "prettier@2.7.1" - - "@prettier/plugin-xml@2.2.0" + entry: prettier args: - - --plugin=@prettier/plugin-xml + - --write + - --list-different + - --ignore-unknown + types: [text] files: \.(css|htm|html|js|json|jsx|less|md|scss|toml|ts|xml|yaml|yml)$ - - repo: https://github.com/pre-commit/mirrors-eslint - rev: v8.24.0 + language: node + additional_dependencies: + - "prettier@3.3.3" + - "@prettier/plugin-xml@3.4.1" + - repo: local hooks: - id: eslint - verbose: true + name: eslint + entry: eslint args: - --color - --fix + verbose: true + types: [javascript] + language: node + additional_dependencies: + - "eslint@9.12.0" + - "eslint-plugin-jsdoc@50.3.1" - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.6.0 hooks: @@ -114,7 +124,7 @@ repos: args: [--fix, --exit-non-zero-on-fix] - id: ruff-format - repo: https://github.com/OCA/pylint-odoo - rev: v9.0.4 + rev: v9.1.3 hooks: - id: pylint_odoo name: pylint with optional checks diff --git a/.prettierrc.yml b/.prettierrc.yml deleted file mode 100644 index 5b6d4b361ace..000000000000 --- a/.prettierrc.yml +++ /dev/null @@ -1,8 +0,0 @@ -# Defaults for all prettier-supported languages. -# Prettier will complete this with settings from .editorconfig file. -bracketSpacing: false -printWidth: 88 -proseWrap: always -semi: true -trailingComma: "es5" -xmlWhitespaceSensitivity: "strict" diff --git a/eslint.config.cjs b/eslint.config.cjs new file mode 100644 index 000000000000..0d5731f89a8b --- /dev/null +++ b/eslint.config.cjs @@ -0,0 +1,202 @@ +jsdoc = require("eslint-plugin-jsdoc"); + +const config = [{ + plugins: { + jsdoc, + }, + + languageOptions: { + globals: { + _: "readonly", + $: "readonly", + fuzzy: "readonly", + jQuery: "readonly", + moment: "readonly", + odoo: "readonly", + openerp: "readonly", + owl: "readonly", + luxon: "readonly", + }, + + ecmaVersion: 2024, + sourceType: "script", + }, + + rules: { + "accessor-pairs": "warn", + "array-callback-return": "warn", + "callback-return": "warn", + "capitalized-comments": ["warn", "always", { + ignoreConsecutiveComments: true, + ignoreInlineComments: true, + }], + complexity: ["warn", 15], + "constructor-super": "warn", + "dot-notation": "warn", + eqeqeq: "warn", + "global-require": "warn", + "handle-callback-err": "warn", + "id-blacklist": "warn", + "id-match": "warn", + "init-declarations": "error", + "max-depth": "warn", + "max-nested-callbacks": "warn", + "max-statements-per-line": "warn", + "no-alert": "warn", + "no-array-constructor": "warn", + "no-caller": "warn", + "no-case-declarations": "warn", + "no-class-assign": "warn", + "no-cond-assign": "error", + "no-const-assign": "error", + "no-constant-condition": "warn", + "no-control-regex": "warn", + "no-debugger": "error", + "no-delete-var": "warn", + "no-div-regex": "warn", + "no-dupe-args": "error", + "no-dupe-class-members": "error", + "no-dupe-keys": "error", + "no-duplicate-case": "error", + "no-duplicate-imports": "error", + "no-else-return": "warn", + "no-empty-character-class": "warn", + "no-empty-function": "error", + "no-empty-pattern": "error", + "no-empty": "warn", + "no-eq-null": "error", + "no-eval": "error", + "no-ex-assign": "error", + "no-extend-native": "warn", + "no-extra-bind": "warn", + "no-extra-boolean-cast": "warn", + "no-extra-label": "warn", + "no-fallthrough": "warn", + "no-func-assign": "error", + "no-global-assign": "error", + "no-implicit-coercion": ["warn", { + allow: ["~"], + }], + "no-implicit-globals": "warn", + "no-implied-eval": "warn", + "no-inline-comments": "warn", + "no-inner-declarations": "warn", + "no-invalid-regexp": "warn", + "no-irregular-whitespace": "warn", + "no-iterator": "warn", + "no-label-var": "warn", + "no-labels": "warn", + "no-lone-blocks": "warn", + "no-lonely-if": "error", + "no-mixed-requires": "error", + "no-multi-str": "warn", + "no-native-reassign": "error", + "no-negated-condition": "warn", + "no-negated-in-lhs": "error", + "no-new-func": "warn", + "no-new-object": "warn", + "no-new-require": "warn", + "no-new-symbol": "warn", + "no-new-wrappers": "warn", + "no-new": "warn", + "no-obj-calls": "warn", + "no-octal-escape": "warn", + "no-octal": "warn", + "no-param-reassign": "warn", + "no-path-concat": "warn", + "no-process-env": "warn", + "no-process-exit": "warn", + "no-proto": "warn", + "no-prototype-builtins": "warn", + "no-redeclare": "warn", + "no-regex-spaces": "warn", + "no-restricted-globals": "warn", + "no-restricted-imports": "warn", + "no-restricted-modules": "warn", + "no-restricted-syntax": "warn", + "no-return-assign": "error", + "no-script-url": "warn", + "no-self-assign": "warn", + "no-self-compare": "warn", + "no-sequences": "warn", + "no-shadow-restricted-names": "warn", + "no-shadow": "warn", + "no-sparse-arrays": "warn", + "no-sync": "warn", + "no-this-before-super": "warn", + "no-throw-literal": "warn", + "no-undef-init": "warn", + "no-undef": "error", + "no-unmodified-loop-condition": "warn", + "no-unneeded-ternary": "error", + "no-unreachable": "error", + "no-unsafe-finally": "error", + "no-unused-expressions": "error", + "no-unused-labels": "error", + "no-unused-vars": "error", + "no-use-before-define": "error", + "no-useless-call": "warn", + "no-useless-computed-key": "warn", + "no-useless-concat": "warn", + "no-useless-constructor": "warn", + "no-useless-escape": "warn", + "no-useless-rename": "warn", + "no-void": "warn", + "no-with": "warn", + "operator-assignment": ["error", "always"], + "prefer-const": "warn", + radix: "warn", + "require-yield": "warn", + "sort-imports": "warn", + "spaced-comment": ["error", "always"], + strict: ["error", "function"], + "use-isnan": "error", + + "jsdoc/check-tag-names": "warn", + "jsdoc/check-types": "warn", + "jsdoc/require-param-description": "off", + "jsdoc/require-return": "off", + "jsdoc/require-return-description": "off", + "jsdoc/require-return-type": "off", + + "valid-typeof": "warn", + yoda: "warn", + }, + + settings: { + jsdoc: { + tagNamePreference: { + arg: "param", + argument: "param", + augments: "extends", + constructor: "class", + exception: "throws", + func: "function", + method: "function", + prop: "property", + return: "returns", + virtual: "abstract", + yield: "yields", + }, + preferredTypes: { + array: "Array", + bool: "Boolean", + boolean: "Boolean", + number: "Number", + object: "Object", + str: "String", + string: "String", + }, + }, + }, + +}, { + files: ["**/*.esm.js"], + + languageOptions: { + ecmaVersion: 2024, + sourceType: "module", + }, +}]; + +module.exports = config diff --git a/prettier.config.cjs b/prettier.config.cjs new file mode 100644 index 000000000000..e66cd82cc1e4 --- /dev/null +++ b/prettier.config.cjs @@ -0,0 +1,14 @@ +/** @type {import('prettier').Config} */ + +const config = { + // https://github.com/prettier/prettier/issues/15388#issuecomment-1717746872 + plugins: [require.resolve("@prettier/plugin-xml")], + bracketSpacing: false, + printWidth: 88, + proseWrap: "always", + semi: true, + trailingComma: "es5", + xmlWhitespaceSensitivity: "preserve", +}; + +module.exports = config; From 0be59fdbbd999bc9d54b6bfdd99311ef4e616199 Mon Sep 17 00:00:00 2001 From: "gborruso@dinamicheaziendali.it" Date: Mon, 26 Oct 2020 17:06:28 +0100 Subject: [PATCH 003/152] [ADD] Aggiunto modulo ddt avanzato --- l10n_it_delivery_note/README.rst | 212 +++ l10n_it_delivery_note/__init__.py | 4 + l10n_it_delivery_note/__manifest__.py | 52 + l10n_it_delivery_note/cli/__init__.py | 3 + l10n_it_delivery_note/cli/core.py | 99 ++ .../cli/migrate_l10n_it_ddt.py | 309 ++++ l10n_it_delivery_note/i18n/it.po | 1543 +++++++++++++++++ .../i18n/l10n_it_delivery_note.pot | 1453 ++++++++++++++++ l10n_it_delivery_note/mixins/__init__.py | 2 + .../mixins/picking_checker.py | 118 ++ .../mixins/shipping_updater.py | 61 + l10n_it_delivery_note/models/__init__.py | 7 + .../models/account_invoice.py | 116 ++ l10n_it_delivery_note/models/res_company.py | 8 + .../models/res_config_settings.py | 17 + l10n_it_delivery_note/models/res_partner.py | 21 + l10n_it_delivery_note/models/sale_order.py | 199 +++ .../models/stock_delivery_note.py | 712 ++++++++ l10n_it_delivery_note/models/stock_picking.py | 343 ++++ l10n_it_delivery_note/readme/CONFIGURE.rst | 18 + l10n_it_delivery_note/readme/CONTRIBUTORS.rst | 8 + l10n_it_delivery_note/readme/DESCRIPTION.rst | 31 + l10n_it_delivery_note/readme/USAGE.rst | 63 + .../report/report_delivery_note.xml | 334 ++++ .../security/ir.model.access.csv | 15 + l10n_it_delivery_note/security/ir_rule.xml | 18 + l10n_it_delivery_note/security/res_groups.xml | 20 + l10n_it_delivery_note/security/res_users.xml | 21 + .../static/description/icon.jpg | Bin 0 -> 3386 bytes .../static/description/icon.png | Bin 0 -> 9455 bytes .../static/description/index.html | 530 ++++++ .../static/src/scss/stock_delivery_note.scss | 147 ++ l10n_it_delivery_note/tests/__init__.py | 1 + .../test_stock_delivery_note_invoicing.py | 1300 ++++++++++++++ .../views/account_invoice.xml | 28 + l10n_it_delivery_note/views/assets.xml | 18 + .../views/res_config_settings.xml | 53 + l10n_it_delivery_note/views/res_partner.xml | 26 + l10n_it_delivery_note/views/sale_order.xml | 24 + .../views/stock_delivery_note.xml | 419 +++++ l10n_it_delivery_note/views/stock_picking.xml | 339 ++++ l10n_it_delivery_note/wizard/__init__.py | 4 + .../wizard/delivery_note_base.py | 83 + .../wizard/delivery_note_create.py | 87 + .../wizard/delivery_note_create.xml | 74 + .../wizard/delivery_note_select.py | 48 + .../wizard/delivery_note_select.xml | 84 + .../wizard/delivery_note_template.xml | 26 + .../wizard/sale_advance_payment_inv.py | 53 + .../wizard/sale_advance_payment_inv.xml | 70 + 50 files changed, 9221 insertions(+) create mode 100644 l10n_it_delivery_note/README.rst create mode 100644 l10n_it_delivery_note/__init__.py create mode 100644 l10n_it_delivery_note/__manifest__.py create mode 100644 l10n_it_delivery_note/cli/__init__.py create mode 100644 l10n_it_delivery_note/cli/core.py create mode 100644 l10n_it_delivery_note/cli/migrate_l10n_it_ddt.py create mode 100644 l10n_it_delivery_note/i18n/it.po create mode 100644 l10n_it_delivery_note/i18n/l10n_it_delivery_note.pot create mode 100644 l10n_it_delivery_note/mixins/__init__.py create mode 100644 l10n_it_delivery_note/mixins/picking_checker.py create mode 100644 l10n_it_delivery_note/mixins/shipping_updater.py create mode 100644 l10n_it_delivery_note/models/__init__.py create mode 100644 l10n_it_delivery_note/models/account_invoice.py create mode 100644 l10n_it_delivery_note/models/res_company.py create mode 100644 l10n_it_delivery_note/models/res_config_settings.py create mode 100644 l10n_it_delivery_note/models/res_partner.py create mode 100644 l10n_it_delivery_note/models/sale_order.py create mode 100644 l10n_it_delivery_note/models/stock_delivery_note.py create mode 100644 l10n_it_delivery_note/models/stock_picking.py create mode 100644 l10n_it_delivery_note/readme/CONFIGURE.rst create mode 100644 l10n_it_delivery_note/readme/CONTRIBUTORS.rst create mode 100644 l10n_it_delivery_note/readme/DESCRIPTION.rst create mode 100644 l10n_it_delivery_note/readme/USAGE.rst create mode 100644 l10n_it_delivery_note/report/report_delivery_note.xml create mode 100644 l10n_it_delivery_note/security/ir.model.access.csv create mode 100644 l10n_it_delivery_note/security/ir_rule.xml create mode 100644 l10n_it_delivery_note/security/res_groups.xml create mode 100644 l10n_it_delivery_note/security/res_users.xml create mode 100644 l10n_it_delivery_note/static/description/icon.jpg create mode 100644 l10n_it_delivery_note/static/description/icon.png create mode 100644 l10n_it_delivery_note/static/description/index.html create mode 100644 l10n_it_delivery_note/static/src/scss/stock_delivery_note.scss create mode 100644 l10n_it_delivery_note/tests/__init__.py create mode 100644 l10n_it_delivery_note/tests/test_stock_delivery_note_invoicing.py create mode 100644 l10n_it_delivery_note/views/account_invoice.xml create mode 100644 l10n_it_delivery_note/views/assets.xml create mode 100644 l10n_it_delivery_note/views/res_config_settings.xml create mode 100644 l10n_it_delivery_note/views/res_partner.xml create mode 100644 l10n_it_delivery_note/views/sale_order.xml create mode 100644 l10n_it_delivery_note/views/stock_delivery_note.xml create mode 100644 l10n_it_delivery_note/views/stock_picking.xml create mode 100644 l10n_it_delivery_note/wizard/__init__.py create mode 100644 l10n_it_delivery_note/wizard/delivery_note_base.py create mode 100644 l10n_it_delivery_note/wizard/delivery_note_create.py create mode 100644 l10n_it_delivery_note/wizard/delivery_note_create.xml create mode 100644 l10n_it_delivery_note/wizard/delivery_note_select.py create mode 100644 l10n_it_delivery_note/wizard/delivery_note_select.xml create mode 100644 l10n_it_delivery_note/wizard/delivery_note_template.xml create mode 100644 l10n_it_delivery_note/wizard/sale_advance_payment_inv.py create mode 100644 l10n_it_delivery_note/wizard/sale_advance_payment_inv.xml diff --git a/l10n_it_delivery_note/README.rst b/l10n_it_delivery_note/README.rst new file mode 100644 index 000000000000..9ac4abb529a0 --- /dev/null +++ b/l10n_it_delivery_note/README.rst @@ -0,0 +1,212 @@ +============================ +ITA - Documento di trasporto +============================ + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fl10n--italy-lightgray.png?logo=github + :target: https://github.com/OCA/l10n-italy/tree/12.0/l10n_it_delivery_note + :alt: OCA/l10n-italy +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/l10n-italy-12-0/l10n-italy-12-0-l10n_it_delivery_note + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/122/12.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +**English** + +This module manage the Italian DDT (Delivery note). + +From a picking is possible to generate a Delivery Note and group more picking in one delivery note. It's also possible to invoice from the delivery note form. + +This module is alternative to :code:`l10n_it_ddt`, it follows the Odoo way to process sale orders, pickings and invoices. + +You can't have both :code:`l10n_it_ddt` and :code:`l10n_it_delivery_note` installed together. + +There are two available settings: + +- Base (default): one picking, one DN. +- Advanced: more picking in one DN. + + +**Italiano** + +Questo modulo consente di gestire i DDT. + +Da un prelievo è possibile generare un DDT e raggruppare più prelievi in un DDT. È anche possibile fatturare dalla scheda del DDT. + +Questo modulo è un alternativa al modulo :code:`l10n_it_ddt`, segue la modalità Odoo di gestire ordini di vendita, prelievi e fatture. + +Non è possibile avere installati contemporaneamente :code:`l10n_it_ddt` e :code:`l10n_it_delivery_note`. + +Ci sono due impostazioni possibili. + +- Base (predefinita): un prelievo, un DDT. +- Avanzata: più prelievi in un DDT. + + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +To configure this module, go to: + +1. *Inventory → Configuration → Settings - Delivery Notes* + + Checking 'Use Advanced DN Features' allows you to manage more picking on one delivery note. + +2. *Inventory → Configuration → Warehouse Management → Delivery Note Types* + + In delivery note type you can specify if the product price have to be printed in the delivery note report/slip. + + - *Inventory → Configuration → Delivery Notes → Conditions of Transport* + - *Inventory → Configuration → Delivery Notes → Appearances of Goods* + - *Inventory → Configuration → Delivery Notes → Reasons of Transport* + - *Inventory → Configuration → Delivery Notes → Methods of Transport* + +3. *Settings → User & Companies → Users* + + In the user profile settings, "Show product information in DN lines" allows showing prices in the form. + +Usage +===== + +Funzionalità base +~~~~~~~~~~~~~~~~~ + +Quando un prelievo viene validato compare una scheda DDT. + +Nella scheda fare clic su "Crea nuovo", si apre un procedura guidata dove scegliere il tipo di DDT, quindi confermare. Immettere i dati richiesti e poi fare clic su "Valida" per numerare il DDT. + +Una volta validato, è possibile emettere fattura direttamente dal DDT se il DDT stesso è di tipo consegna a cliente (In uscita) e si hanno i permessi sull'utente. + +È possibile annullare il DDT, reimpostarlo a bozza e poi modificarlo. Se il DDT è fatturato il numero e la data non sono modificabili. + +Per i trasferimenti tra magazzini creare un prelievo di tipo interno con le relative ubicazioni. Validare il prelievo visualizza la scheda DDT. + +È possibile anche avere DDT in ingresso, ovvero dopo la validazione del prelievo selezionare la scheda per indicare il numero del DDT fornitore e la data. + +Funzionalità avanzata +~~~~~~~~~~~~~~~~~~~~~ + +Vengono attivate varie funzionalità aggiuntive: + +- più prelievi per un DDT +- selezione multipla di prelievi e generazione dei DDT +- aggiunta righe nota e righe sezione descrittive. +- lista dei DDT. + +Il report DDT stampa in righe aggiuntive i lotti/seriali e le scadenze del prodotto. + +Il prezzo può essere indicato anche nel report DDT se nel tipo DDT è indicata la stampa prezzi. +La visibilità dei prezzi si trova nei permessi dell'utente. + +Le fatture generate dai DDT contengono i riferimenti al DDT stesso nelle righe nota. + + +Migrazione dei dati da *l10n_it_ddt* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Il modulo presenta una funzione di migrazione dei dati dal modulo OCA *l10n_it_ddt* da eseguire manualmente. +Al momento, non è ancora presente un menù oppure una voce da interfaccia che permetta di eseguire questa operazione; bensì, è stato definito un comando da CLI da eseguire all’avvio di Odoo. +Di seguito, una piccola lista di passi da seguire per portare a termine la migrazione: + +1. Eseguire un back-up del database. + + Questa procedura di migrazione dei dati è stata sì sviluppata e testata, MA solamente per un numero limitato di casi. + NON è consigliata in alcun modo come funzionalità production-ready. + +2. Installare il modulo *l10n_it_delivery_note* SENZA prima disinstallare il modulo OCA *l10n_it_ddt*. + + N.B.: NON iniziare ad usare il modulo *l10n_it_delivery_note* senza aver prima migrato i dati. + Potrebbero verificarsi, in prima battuta, problemi legati alla numerazione dei documenti creati. + Inoltre, la procedura di migrazione stessa è progettata affinché verifichi che non siano presenti documenti di *l10n_it_delivery_note*; qualora ne rilevi alcuni, si interromperà non eseguendo alcuna migrazione. + +3. Terminata l’installazione del modulo, terminare in sicurezza il processo di Odoo. + +4. Lanciare Odoo, nella maniera in cui si è soliti fare, aggiungendo alcuni parametri al comando d’avvio: + + `./odoo-bin migrate_ddt_data --database [...]` + +5. Una volta terminata l’esecuzione della procedura, verificare che tutti i documenti siano stati migrati con successo e nel modo atteso. + +6. Verificata l’esattezza dei dati migrati, disinstallare il modulo *l10n_it_ddt*. + +È possibile iniziare ad utilizzare *l10n_it_delivery_note*. + + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Marco Calcagni +* Gianmarco Conte +* Link IT Europe Srl + +Contributors +~~~~~~~~~~~~ + +* Riccardo Bellanova +* Matteo Bilotta +* Giuseppe Borruso +* Marco Calcagni +* Marco Colombo +* Gianmarco Conte +* Letizia Freda +* Andrea Piovesana + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +.. |maintainer-As400it| image:: https://github.com/As400it.png?size=40px + :target: https://github.com/As400it + :alt: As400it +.. |maintainer-Byloth| image:: https://github.com/Byloth.png?size=40px + :target: https://github.com/Byloth + :alt: Byloth + +Current `maintainers `__: + +|maintainer-As400it| |maintainer-Byloth| + +This module is part of the `OCA/l10n-italy `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/l10n_it_delivery_note/__init__.py b/l10n_it_delivery_note/__init__.py new file mode 100644 index 000000000000..08b82294f530 --- /dev/null +++ b/l10n_it_delivery_note/__init__.py @@ -0,0 +1,4 @@ +from . import cli +from . import mixins +from . import models +from . import wizard diff --git a/l10n_it_delivery_note/__manifest__.py b/l10n_it_delivery_note/__manifest__.py new file mode 100644 index 000000000000..0cedab65f7fc --- /dev/null +++ b/l10n_it_delivery_note/__manifest__.py @@ -0,0 +1,52 @@ +# Copyright 2014-2019 Dinamiche Aziendali srl +# (http://www.dinamicheaziendali.it/) +# @author: Marco Calcagni +# @author: Gianmarco Conte +# Copyright (c) 2019, Link IT Europe Srl +# @author: Matteo Bilotta +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +# noinspection PyStatementEffect +{ + 'name': "ITA - Documento di trasporto", + 'summary': "Crea, gestisce e fattura i DDT partendo dalle consegne", + + 'author': "Marco Calcagni, Gianmarco Conte, Link IT Europe Srl, " + "Odoo Community Association (OCA)", + 'website': 'https://github.com/OCA/l10n-italy/tree/12.0/' + 'l10n_it_delivery_note', + 'version': '12.0.1.0.0', + 'category': "Localization", + 'license': 'AGPL-3', + 'maintainers': ['As400it', 'Byloth'], + + 'depends': [ + 'delivery', + 'l10n_it_delivery_note_base', + 'mail', + 'sale_stock', + 'stock_account' + ], + + 'data': [ + 'security/ir.model.access.csv', + 'security/ir_rule.xml', + 'security/res_groups.xml', + 'security/res_users.xml', + + 'report/report_delivery_note.xml', + + 'views/account_invoice.xml', + 'views/assets.xml', + 'views/res_config_settings.xml', + 'views/res_partner.xml', + 'views/sale_order.xml', + 'views/stock_delivery_note.xml', + 'views/stock_picking.xml', + + 'wizard/delivery_note_create.xml', + 'wizard/delivery_note_select.xml', + 'wizard/delivery_note_template.xml', + 'wizard/sale_advance_payment_inv.xml' + ] +} diff --git a/l10n_it_delivery_note/cli/__init__.py b/l10n_it_delivery_note/cli/__init__.py new file mode 100644 index 000000000000..76b5467d965d --- /dev/null +++ b/l10n_it_delivery_note/cli/__init__.py @@ -0,0 +1,3 @@ +from . import core + +from . import migrate_l10n_it_ddt diff --git a/l10n_it_delivery_note/cli/core.py b/l10n_it_delivery_note/cli/core.py new file mode 100644 index 000000000000..627e51508bda --- /dev/null +++ b/l10n_it_delivery_note/cli/core.py @@ -0,0 +1,99 @@ +# Copyright (c) 2020, Link IT Europe Srl +# @author: Matteo Bilotta +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import argparse +import functools +import logging +import odoo + +from odoo import SUPERUSER_ID +from odoo.cli import Command + +_logger = logging.getLogger(__name__) + + +def environment(funct=None, parser_args_method=None): + if not funct: + return functools.partial(environment, + parser_args_method=parser_args_method) + + @functools.wraps(funct) + def env_enabler(self, args): + command_args = unknown_args = args + + if parser_args_method: + command_args, unknown_args = parser_args_method(self, args) + + odoo.tools.config._parse_config(unknown_args) + odoo.netsvc.init_logger() + + config = odoo.tools.config + + with odoo.api.Environment.manage(): + cr = odoo.registry(config['db_name']).cursor() + env = odoo.api.Environment(cr, SUPERUSER_ID, {}) + + funct(self, command_args, env) + + return env_enabler + + +class EasyCommand(Command): + args = None + env = None + + is_debugging = None + + def __init__(self): + self.is_debugging = False + + def _commit(self): + self.env.cr.commit() # pylint: disable=invalid-commit + + def _rollback(self): + self.env.cr.rollback() + + def _close(self): + self.env.cr.close() + + def initialize(self, args, env): + self.args = args + self.env = env + + if args: + self.is_debugging = args.debug + + def execute(self): + raise NotImplementedError("This method hasn't yet been implemented.") + + # noinspection PyMethodMayBeStatic + def get_args_parser(self): + args_parser = argparse.ArgumentParser() + args_parser.add_argument('--debug', action='store_true', default=False) + + return args_parser + + def parse_args(self, args): + arg_parser = self.get_args_parser() + + return arg_parser.parse_known_args(args) + + @environment(parser_args_method=parse_args) + def run(self, args, env): + try: + self.initialize(args, env) + self.execute() + + _logger.info("Execution completed successfully! Committing...") + + self._commit() + + except: + _logger.exception("Something went wrong during command execution. " + "Rolling back...") + + self._rollback() + + finally: + self._close() diff --git a/l10n_it_delivery_note/cli/migrate_l10n_it_ddt.py b/l10n_it_delivery_note/cli/migrate_l10n_it_ddt.py new file mode 100644 index 000000000000..ed43a5c59070 --- /dev/null +++ b/l10n_it_delivery_note/cli/migrate_l10n_it_ddt.py @@ -0,0 +1,309 @@ +# Copyright (c) 2019, Link IT Europe Srl +# @author: Matteo Bilotta +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import logging + +from odoo.exceptions import UserError, ValidationError +from odoo import _ + +from .core import EasyCommand + +_logger = logging.getLogger(__name__) + +STATES_MAPPING = { + 'draft': 'draft', + 'cancel': 'cancel', + 'in_pack': 'draft', + 'done': 'confirm' +} + + +# noinspection PyPep8Naming +class MigrateL10nItDdt(EasyCommand): + _carriage_conditions = None + _goods_descriptions = None + _transportation_reasons = None + _transportation_methods = None + _document_types = None + + def __init__(self): + super().__init__() + + self._carriage_conditions = {} + self._goods_descriptions = {} + self._transportation_reasons = {} + self._transportation_methods = {} + self._document_types = {} + + @property + def _default_volume_uom(self): + return self.env.ref('uom.product_uom_litre', raise_if_not_found=False) + + @property + def _default_weight_uom(self): + return self.env.ref('uom.product_uom_kgm', raise_if_not_found=False) + + # noinspection PyMethodMayBeStatic + def _map_create(self, map_dict, old_records, Model, vals_getter=None): + if not old_records: + return + + def default_getter(record): + return { + 'name': record.name, + 'note': record.note + } + + if not vals_getter: + vals_getter = default_getter + + for old_record in old_records: + vals = vals_getter(old_record) + new_record = Model.create(vals) + + map_dict[old_record] = new_record + + def _map_ref(self, map_dict, old_ext_id, new_ext_id): + old_record = self.env.ref('l10n_it_ddt.{}'.format(old_ext_id)) + new_record = self.env.ref('l10n_it_delivery_note_base.{}'.format(new_ext_id)) + + map_dict[old_record] = new_record + + return old_record + + def check_database_integrity(self): + _logger.info("Checking database integrity before run data migration..") + + self.env.cr.execute(""" + SELECT "id", "state" FROM "ir_module_module" + WHERE "name" = 'l10n_it_ddt'; + """) + old_module = self.env.cr.fetchone() + if not old_module or old_module[1] != 'installed': + raise UserError(_( + "Module `l10n_it_ddt` isn't installed on this database. " + "You don't need to run this command." + )) + + old_sequence = self.env.ref('l10n_it_ddt.seq_ddt') + if old_sequence.number_next_actual == 1: + raise UserError(_( + "It seems that there are no documents to migrate. " + "You don't need to run this command." + )) + + new_sequence = self.env.ref('l10n_it_delivery_note.delivery_note_sequence_ddt') + if new_sequence.number_next_actual > 1: + raise ValidationError(_( + "It seems that at least one delivery note has been " + "already created. " + "You can't migrate any data on an already used database." + )) + + _logger.info("Database integrity check successfully passed.") + + def migrate_carriage_conditions(self): + _logger.info("Migrating carriage conditions data...") + + CarriageCondition = self.env['stock.picking.carriage_condition'] + TransportCondition = self.env['stock.picking.transport.condition'] + + pf = self._map_ref(self._carriage_conditions, + 'carriage_condition_PF', + 'transport_condition_PF') + pa = self._map_ref(self._carriage_conditions, + 'carriage_condition_PA', + 'transport_condition_PA') + paf = self._map_ref(self._carriage_conditions, + 'carriage_condition_PAF', + 'transport_condition_PAF') + + records = \ + CarriageCondition.search([('id', 'not in', [pf.id, pa.id, paf.id])], + order='id ASC') + + self._map_create(self._carriage_conditions, + records, TransportCondition) + + _logger.info("Carriage conditions data successfully migrated.") + + def migrate_goods_descriptions(self): + _logger.info("Migrating goods descriptions data...") + + GoodsDescription = self.env['stock.picking.goods_description'] + GoodsAppearance = self.env['stock.picking.goods.appearance'] + + car = self._map_ref(self._goods_descriptions, + 'goods_description_CAR', + 'goods_appearance_CAR') + ban = self._map_ref(self._goods_descriptions, + 'goods_description_BAN', + 'goods_appearance_BAN') + sfu = self._map_ref(self._goods_descriptions, + 'goods_description_SFU', + 'goods_appearance_SFU') + cba = self._map_ref(self._goods_descriptions, + 'goods_description_CBA', + 'goods_appearance_CBA') + + records = GoodsDescription.search( + [('id', 'not in', [car.id, ban.id, sfu.id, cba.id])], + order='id ASC') + + self._map_create(self._goods_descriptions, records, GoodsAppearance) + + _logger.info("Goods descriptions data successfully migrated.") + + def migrate_transportation_reasons(self): + _logger.info("Migrating transportation reasons data...") + + TransportationReason = self.env['stock.picking.transportation_reason'] + TransportReason = self.env['stock.picking.transport.reason'] + + ven = self._map_ref(self._transportation_reasons, + 'transportation_reason_VEN', + 'transport_reason_VEN') + vis = self._map_ref(self._transportation_reasons, + 'transportation_reason_VIS', + 'transport_reason_VIS') + res = self._map_ref(self._transportation_reasons, + 'transportation_reason_RES', + 'transport_reason_RES') + + records = \ + TransportationReason.search([('id', 'not in', [ven.id, vis.id, res.id])], + order='id ASC') + + self._map_create(self._transportation_reasons, + records, TransportReason) + + _logger.info("Transportation reasons data successfully migrated.") + + def migrate_transportation_methods(self): + _logger.info("Migrating transportation methods data...") + + TransportationMethod = self.env['stock.picking.transportation_method'] + TransportMethod = self.env['stock.picking.transport.method'] + + mit = self._map_ref(self._transportation_methods, + 'transportation_method_MIT', + 'transport_method_MIT') + des = self._map_ref(self._transportation_methods, + 'transportation_method_DES', + 'transport_method_DES') + cor = self._map_ref(self._transportation_methods, + 'transportation_method_COR', + 'transport_method_COR') + + records = \ + TransportationMethod.search([('id', 'not in', [mit.id, des.id, cor.id])], + order='id ASC') + + self._map_create(self._transportation_methods, + records, TransportMethod) + + _logger.info("Transportation methods data successfully migrated.") + + def migrate_document_types(self): + _logger.info("Migrating document types data...") + + DocumentType = self.env['stock.ddt.type'] + DeliveryNoteType = self.env['stock.delivery.note.type'] + + old_type = self.env.ref('l10n_it_ddt.ddt_type_ddt') + new_type = self.env.ref('l10n_it_delivery_note.delivery_note_type_ddt') + new_type.write({'sequence_id': old_type.sequence_id.id}) + + self.env.cr.execute(""" + DELETE FROM "ir_model_data" + WHERE "module" = 'l10n_it_ddt' AND "name" = 'seq_ddt'; + """) + + self._document_types[old_type] = new_type + + records = DocumentType.search([('id', 'not in', [old_type.id])], + order='id ASC') + + self._map_create(self._document_types, + records, + DeliveryNoteType, + lambda r: { + 'name': r.name, + 'sequence_id': r.sequence_id.id, + 'default_goods_appearance_id': + self._goods_descriptions[ + r.default_goods_description_id].id, + 'default_transport_reason_id': + self._transportation_reasons[ + r.default_transportation_reason_id].id, + 'default_transport_condition_id': + self._carriage_conditions[ + r.default_carriage_condition_id].id, + 'default_transport_method_id': + self._transportation_methods[ + r.default_transportation_method_id].id, + 'note': r.note + }) + + _logger.info("Document types data successfully migrated.") + + def migrate_documents(self): + def vals_getter(record): + return { + 'state': STATES_MAPPING[record.state], + 'name': record.ddt_number, + 'partner_sender_id': record.company_id.id, + 'partner_id': record.partner_id.id, + 'partner_shipping_id': record.partner_shipping_id.id, + 'type_id': self._document_types[record.ddt_type_id].id, + 'date': record.date, + 'carrier_id': record.carrier_id.id, + 'delivery_method_id': + record.partner_id.property_delivery_carrier_id.id, + 'transport_datetime': record.date_done, + 'packages': record.parcels, + 'volume': record.volume, + 'volume_uom_id': + record.volume_uom_id.id or self._default_volume_uom.id, + 'gross_weight': record.gross_weight or record.weight, + 'gross_weight_uom_id': + record.gross_weight_uom_id.id or + self._default_weight_uom.id, + 'net_weight': record.weight_manual or record.weight, + 'net_weight_uom_id': + record.weight_manual_uom_id.id or + self._default_weight_uom.id, + 'goods_appearance_id': + self._goods_descriptions[record.goods_description_id].id, + 'transport_reason_id': + self._transportation_reasons[record.transportation_reason_id].id, + 'transport_condition_id': + self._carriage_conditions[record.carriage_condition_id].id, + 'transport_method_id': + self._transportation_methods[record.transportation_method_id].id, + 'picking_ids': [(4, p.id) for p in record.picking_ids], + 'invoice_ids': + [(4, record.invoice_id.id)] if record.invoice_id else [], + 'note': record.note + } + + _logger.info("Migrating documents data...") + + Document = self.env['stock.picking.package.preparation'] + DeliveryNote = self.env['stock.delivery.note'] + + documents = Document.search([], order='id ASC') + for document in documents: + DeliveryNote.create(vals_getter(document)) + + _logger.info("Documents data successfully migrated.") + + def execute(self): + self.check_database_integrity() + self.migrate_carriage_conditions() + self.migrate_goods_descriptions() + self.migrate_transportation_reasons() + self.migrate_transportation_methods() + self.migrate_document_types() + self.migrate_documents() diff --git a/l10n_it_delivery_note/i18n/it.po b/l10n_it_delivery_note/i18n/it.po new file mode 100644 index 000000000000..b0444c4859e0 --- /dev/null +++ b/l10n_it_delivery_note/i18n/it.po @@ -0,0 +1,1543 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * l10n_it_delivery_note +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-10-15 08:35+0000\n" +"PO-Revision-Date: 2020-10-15 08:35+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.res_config_settings_form_view +msgid "(e.g. link multiple pickings to a single DN)" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.sale_advance_payment_inv_form_view +msgid " Warning!" +msgstr " Attenzione!" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Phone:" +msgstr "Telefono:" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "VAT:" +msgstr "Partita IVA:" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "" +"\n" +" " +"Warning!\n" +" \n" +" Inconsistent DN info in sale orders!" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "" +" Delivery Note: \n" +" Under the terms of Italian Presidential Decree 472-96 of " +"14.08.1996" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Customer:" +msgstr "Cliente:" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Delivery address:" +msgstr "Indirizzo di consegna:" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.sale_advance_payment_inv_form_view +msgid "" +"N.B.: there will be no way, subsequently, to restore\n" +" this binding between the delivery note lines with " +"the related sales order." +msgstr "" +"N.B.: non ci sarà modo, a posteriori, di ripristinare\n" +" il legame tra righe del DdT con il rispettivo ordine " +"di vendita." + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Warehouse:" +msgstr "Magazzino:" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,help:l10n_it_delivery_note.field_stock_delivery_note_line__product_description +msgid "" +"A description of the Product that you want to communicate to your customers. " +"This description will be copied to every Sales Order, Delivery Order and " +"Customer Invoice/Credit Note" +msgstr "" +"Una descrizione del prodotto da mostrare ai clienti. La descrizione sarà " +"inserita in ogni ordine di vendita, ordine di spedizione e fatturazione/nota " +"di credito del cliente" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__message_needaction +msgid "Action Needed" +msgstr "Azione richiesta" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__active +msgid "Active" +msgstr "Attivo" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__activity_ids +msgid "Activities" +msgstr "Attività" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__activity_state +msgid "Activity State" +msgstr "Stato attività" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "Add a note" +msgstr "Aggiungi un commento" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "Add a section" +msgstr "Aggiungi una sezione" + +#. module: l10n_it_delivery_note +#: model:res.groups,name:l10n_it_delivery_note.can_change_number +msgid "Allow to change delivery note number" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_res_partner__default_goods_appearance_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_res_users__default_goods_appearance_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_sale_order__default_goods_appearance_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__goods_appearance_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__goods_appearance_id +msgid "Appearance of goods" +msgstr "Aspetto dei beni" + +#. module: l10n_it_delivery_note +#: model:ir.actions.act_window,name:l10n_it_delivery_note.stock_picking_goods_appearance_action +#: model:ir.ui.menu,name:l10n_it_delivery_note.stock_picking_good_appearance_menu +msgid "Appearances of goods" +msgstr "Aspetti dei beni" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +msgid "Archived" +msgstr "Archiviati" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/mixins/picking_checker.py:106 +#, python-format +msgid "" +"At least one picking you've selected appears to be already related to " +"another delivery note." +msgstr "" +"Almeno un prelievo tra quelli selezionati è già legato ad un altro DdT." + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/mixins/picking_checker.py:33 +#, python-format +msgid "At least one picking you've selected doesn't appear to be completed." +msgstr "Almeno un prelievo tra quelli selezionati non è stato completato." + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__message_attachment_count +msgid "Attachment Count" +msgstr "Numero allegati" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__can_be_invoiced +msgid "Can Be Invoiced" +msgstr "Può essere fatturato" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__can_change_number +msgid "Can Change Number" +msgstr "Può cambiare numero" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_create_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_select_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +msgid "Cancel" +msgstr "Annulla" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +#: selection:stock.delivery.note,state:0 +msgid "Cancelled" +msgstr "Annullato" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Carriage Condition" +msgstr "Condizione di trasporto" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__carrier_id +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +msgid "Carrier" +msgstr "Vettore" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Carrier's Signature" +msgstr "Firma del corriere" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +msgid "Carriers" +msgstr "Corrieri" + +#. module: l10n_it_delivery_note +#: model:ir.model,name:l10n_it_delivery_note.model_res_company +msgid "Companies" +msgstr "Aziende" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__company_id +msgid "Company" +msgstr "Azienda" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_res_partner__default_transport_condition_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_res_users__default_transport_condition_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_sale_order__default_transport_condition_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__transport_condition_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__transport_condition_id +msgid "Condition of transport" +msgstr "Condizione di trasporto" + +#. module: l10n_it_delivery_note +#: model:ir.actions.act_window,name:l10n_it_delivery_note.stock_picking_transport_condition_action +#: model:ir.ui.menu,name:l10n_it_delivery_note.stock_picking_transport_condition_menu +msgid "Conditions of transport" +msgstr "Condizioni di trasporto" + +#. module: l10n_it_delivery_note +#: model:ir.model,name:l10n_it_delivery_note.model_res_config_settings +msgid "Config Settings" +msgstr "Impostazioni di configurazione" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_create_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_select_form_view +#: selection:sale.advance.payment.inv,step:0 +msgid "Confirm" +msgstr "Conferma" + +#. module: l10n_it_delivery_note +#: model:ir.model,name:l10n_it_delivery_note.model_res_partner +msgid "Contact" +msgstr "Contatto" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/models/stock_picking.py:184 +#: model:ir.actions.act_window,name:l10n_it_delivery_note.stock_delivery_note_create_action +#, python-format +msgid "Create a new delivery note" +msgstr "Crea un nuovo DdT" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +msgid "Create invoice" +msgstr "Crea fattura" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +msgid "Create new" +msgstr "Crea nuovo" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__create_uid +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_create_wizard__create_uid +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__create_uid +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard__create_uid +msgid "Created by" +msgstr "Creato da" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__create_date +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_create_wizard__create_date +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__create_date +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard__create_date +msgid "Created on" +msgstr "Creato il" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__currency_id +msgid "Currency" +msgstr "Valuta" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_sale_advance_payment_inv__step +msgid "Current step" +msgstr "Passo corrente" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_carrier_id +msgid "DN Carrier" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_date +msgid "DN Date" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__picking_type_code +msgid "DN Operation Type" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__packages +msgid "DN Packages" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_state +msgid "DN State" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_volume +msgid "DN Volume" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "DN date" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__date +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_base_wizard__date +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_create_wizard__date +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard__date +msgid "Date" +msgstr "Data" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +msgid "Dates" +msgstr "Date" + +#. module: l10n_it_delivery_note +#: model:ir.actions.report,name:l10n_it_delivery_note.delivery_note_report_action +#: model:ir.model,name:l10n_it_delivery_note.model_stock_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_account_invoice_line__delivery_note_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_sale_order__delivery_note_ids +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__delivery_note_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard__delivery_note_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_id +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +msgid "Delivery Note" +msgstr "DdT" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/models/account_invoice.py:103 +#, python-format +msgid "Delivery Note \"{}\" of {}" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model,name:l10n_it_delivery_note.model_stock_delivery_note_base_wizard +msgid "Delivery Note Base" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_account_invoice__delivery_note_count +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_sale_order__delivery_note_count +msgid "Delivery Note Count" +msgstr "Conto DdT" + +#. module: l10n_it_delivery_note +#: model:ir.model,name:l10n_it_delivery_note.model_stock_delivery_note_create_wizard +msgid "Delivery Note Creator" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_draft +msgid "Delivery Note Draft" +msgstr "DdT in bozza" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_exists +msgid "Delivery Note Exists" +msgstr "Esiste DdT" + +#. module: l10n_it_delivery_note +#: model:ir.model,name:l10n_it_delivery_note.model_stock_delivery_note_line +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_sale_order_line__delivery_note_line_ids +msgid "Delivery Note Line" +msgstr "Riga DdT" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_readonly +msgid "Delivery Note Readonly" +msgstr "DdT in sola-lettura" + +#. module: l10n_it_delivery_note +#: model:ir.model,name:l10n_it_delivery_note.model_stock_delivery_note_select_wizard +msgid "Delivery Note Selector" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.actions.act_window,name:l10n_it_delivery_note.stock_delivery_note_type_action +#: model:ir.ui.menu,name:l10n_it_delivery_note.stock_delivery_note_type_menu +msgid "Delivery Note Types" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_visible +msgid "Delivery Note Visible" +msgstr "DdT visibile" + +#. module: l10n_it_delivery_note +#: model:ir.actions.act_window,name:l10n_it_delivery_note.stock_delivery_note_action +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_account_invoice__delivery_note_ids +#: model:ir.ui.menu,name:l10n_it_delivery_note.stock_delivery_note_config_menu +#: model:ir.ui.menu,name:l10n_it_delivery_note.stock_delivery_note_menu +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.account_invoice_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.res_config_settings_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +msgid "Delivery Notes" +msgstr "DdT" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_sale_order_line__delivery_picking_id +msgid "Delivery Picking" +msgstr "Prelievo DdT" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__delivery_method_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_method_id +msgid "Delivery method" +msgstr "Metodo di consegna" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__name +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Description" +msgstr "Descrizione" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "Details" +msgstr "Dettagli" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__discount +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Discount" +msgstr "Sconto" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_shipping_information_updater_mixin__display_name +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__display_name +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_base_wizard__display_name +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_create_wizard__display_name +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__display_name +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard__display_name +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking_checker_mixin__display_name +msgid "Display Name" +msgstr "Nome visualizzato" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "Document" +msgstr "Documento" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Document:" +msgstr "Documento:" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +#: selection:stock.delivery.note,state:0 +msgid "Done" +msgstr "Completato" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +#: selection:stock.delivery.note,state:0 +msgid "Draft" +msgstr "Bozza" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_search_view +msgid "Draft DN" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "Draft document" +msgstr "Documento in bozza" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Draft document:" +msgstr "Documento in bozza:" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Driver's Signature" +msgstr "Firma del corriere" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_base_wizard__error_message +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_create_wizard__error_message +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard__error_message +msgid "Error Message" +msgstr "Messaggio di errore" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__message_follower_ids +msgid "Followers" +msgstr "Follower" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__message_channel_ids +msgid "Followers (Channels)" +msgstr "Chi sta seguendo (canali)" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__message_partner_ids +msgid "Followers (Partners)" +msgstr "Chi sta seguendo (partner)" + +#. module: l10n_it_delivery_note +#: selection:stock.delivery.note,invoice_status:0 +#: selection:stock.delivery.note.line,invoice_status:0 +msgid "Fully invoiced" +msgstr "Interamente fatturato" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_tree_view +msgid "Go to delivery note" +msgstr "Vai al DdT" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "Go to invoice" +msgstr "Vai alla fattura" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Goods Description" +msgstr "Descrizione dei beni" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Gross Weight" +msgstr "Peso lordo" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__gross_weight +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__gross_weight +msgid "Gross weight" +msgstr "Peso lordo" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__gross_weight_uom_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__gross_weight_uom_id +msgid "Gross weight UoM" +msgstr "UdM del peso lordo" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_shipping_information_updater_mixin__id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_base_wizard__id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_create_wizard__id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard__id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking_checker_mixin__id +msgid "ID" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,help:l10n_it_delivery_note.field_stock_delivery_note__message_unread +msgid "If checked new messages require your attention." +msgstr "Se selezionato, nuovi messaggi richiedono attenzione." + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,help:l10n_it_delivery_note.field_stock_delivery_note__message_needaction +msgid "If checked, new messages require your attention." +msgstr "Se selezionato, nuovi messaggi richiedono attenzione." + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,help:l10n_it_delivery_note.field_stock_delivery_note__message_has_error +msgid "If checked, some messages have a delivery error." +msgstr "Se selezionato, alcuni messaggi presentano un errore di consegna." + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_wizard_error_message_template +msgid "If these problems persist, don't hesitate to contact the helpdesk." +msgstr "Se questi problemi persistono, non esitate a contattare l'helpdesk." + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +#: selection:stock.delivery.note,picking_type:0 +msgid "Incoming" +msgstr "In entrata" + +#. module: l10n_it_delivery_note +#: selection:sale.advance.payment.inv,step:0 +msgid "Initial" +msgstr "Iniziale" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +#: selection:stock.delivery.note,picking_type:0 +msgid "Internal" +msgstr "Interno" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_note +msgid "Internal note" +msgstr "Nota interna" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "Internal notes" +msgstr "Note interne" + +#. module: l10n_it_delivery_note +#: model:ir.model,name:l10n_it_delivery_note.model_account_invoice +msgid "Invoice" +msgstr "Fattura" + +#. module: l10n_it_delivery_note +#: model:ir.model,name:l10n_it_delivery_note.model_account_invoice_line +msgid "Invoice Line" +msgstr "Riga fattura" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/wizard/sale_advance_payment_inv.py:44 +#, python-format +msgid "Invoice Order" +msgstr "Ordine fattura" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__invoice_status +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__invoice_status +msgid "Invoice status" +msgstr "Stato fatturazione" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +msgid "Invoice statuses" +msgstr "Stati fatturazione" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +#: selection:stock.delivery.note,state:0 +msgid "Invoiced" +msgstr "Fatturate" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__invoice_ids +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "Invoices" +msgstr "Fatture" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__message_is_follower +msgid "Is Follower" +msgstr "Sta seguendo" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.res_config_settings_form_view +msgid "" +"It allows to prompt a confirmation to the user\n" +" during the invoicing action if there's " +"at\n" +" least one unconfirmed delivery note." +msgstr "" +"Consente di mostrare una richiesta di conferma all'utente\n" +" durante l'azione di fatturazione di un " +"ordine se\n" +" è presente almeno un DdT non confermato." + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.res_config_settings_form_view +msgid "" +"It extends the standard behaviour of DNs\n" +" management by introducing additional " +"functions." +msgstr "" +"Estende il comportamento standard della gestione dei\n" +" DdT introducendo funzionalità aggiuntive." + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/cli/migrate_l10n_it_ddt.py:98 +#, python-format +msgid "" +"It seems that at least one delivery note has been already created. You can't " +"migrate any data on an already used database." +msgstr "" +"Sembra che sia stato già creato almeno un DdT. Non puoi migrare nessun dato " +"se il database è già in uso." + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/cli/migrate_l10n_it_ddt.py:91 +#, python-format +msgid "" +"It seems that there are no documents to migrate. You don't need to run this " +"command." +msgstr "" +"Sembra che non ci siano documenti da migrare. Non si necessita di eseguire " +"questo comando." + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_shipping_information_updater_mixin____last_update +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note____last_update +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_base_wizard____last_update +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_create_wizard____last_update +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line____last_update +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard____last_update +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking_checker_mixin____last_update +msgid "Last Modified on" +msgstr "Ultima modifica il" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__write_uid +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_create_wizard__write_uid +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__write_uid +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard__write_uid +msgid "Last Updated by" +msgstr "Ultimo aggiornamento di" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__write_date +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_create_wizard__write_date +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__write_date +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard__write_date +msgid "Last Updated on" +msgstr "Ultimo aggiornamento il" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__display_type +msgid "Line type" +msgstr "Tipo riga" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__line_ids +msgid "Lines" +msgstr "Righe" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__message_main_attachment_id +msgid "Main Attachment" +msgstr "Allegato principale" + +#. module: l10n_it_delivery_note +#: selection:stock.delivery.note,picking_type:0 +msgid "Manufacturing Operation" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__message_has_error +msgid "Message Delivery error" +msgstr "Errore di consegna messaggio" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__message_ids +msgid "Messages" +msgstr "Messaggi" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Method of Transport / Carrier" +msgstr "Metodo di trasporto / Corriere" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_res_partner__default_transport_method_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_res_users__default_transport_method_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_sale_order__default_transport_method_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__transport_method_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__transport_method_id +msgid "Method of transport" +msgstr "Metodo di trasporto" + +#. module: l10n_it_delivery_note +#: model:ir.actions.act_window,name:l10n_it_delivery_note.stock_picking_transport_method_action +#: model:ir.ui.menu,name:l10n_it_delivery_note.stock_picking_transport_method_menu +msgid "Methods of transport" +msgstr "Metodi di trasporto" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/cli/migrate_l10n_it_ddt.py:84 +#, python-format +msgid "" +"Module `l10n_it_ddt` isn't installed on this database. You don't need to run " +"this command." +msgstr "" +"Il modulo `l10n_it_ddt` non è installato in questo database. Non si " +"necessita di eseguire questo comando." + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__name +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_tree_view +msgid "Name" +msgstr "Nome" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Net Weight" +msgstr "Peso netto" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__net_weight +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__net_weight +msgid "Net weight" +msgstr "Peso netto" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__net_weight_uom_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__net_weight_uom_id +msgid "Net weight UoM" +msgstr "UdM del peso netto" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__activity_date_deadline +msgid "Next Activity Deadline" +msgstr "Scadenza attività successiva" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__activity_summary +msgid "Next Activity Summary" +msgstr "Riepilogo prossima attività" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__activity_type_id +msgid "Next Activity Type" +msgstr "Tipologia prossima attività" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_search_view +msgid "No DN" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +#: selection:stock.delivery.note.line,display_type:0 +msgid "Note" +msgstr "Nota" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Notes" +msgstr "Note" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +#: selection:stock.delivery.note,invoice_status:0 +#: selection:stock.delivery.note.line,invoice_status:0 +msgid "Nothing to invoice" +msgstr "Niente da fatturare" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_res_company__draft_delivery_note_invoicing_notify +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_res_config_settings__draft_delivery_note_invoicing_notify +msgid "Notify if delivery note isn't validated" +msgstr "Notifica se il DdT non è validato" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__message_needaction_counter +msgid "Number of Actions" +msgstr "Numero di azioni" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__message_has_error_counter +msgid "Number of error" +msgstr "Numero di errori" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,help:l10n_it_delivery_note.field_stock_delivery_note__message_needaction_counter +msgid "Number of messages which requires an action" +msgstr "Numero di messaggi che richiedono un'azione" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,help:l10n_it_delivery_note.field_stock_delivery_note__message_has_error_counter +msgid "Number of messages with delivery error" +msgstr "Numero di messaggi con errore di consegna" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,help:l10n_it_delivery_note.field_stock_delivery_note__message_unread_counter +msgid "Number of unread messages" +msgstr "Numero di messaggi non letti" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "Open picking" +msgstr "Apri consegna" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +#: selection:stock.delivery.note,picking_type:0 +msgid "Outgoing" +msgstr "In uscita" + +#. module: l10n_it_delivery_note +#: selection:stock.delivery.note,activity_state:0 +msgid "Overdue" +msgstr "In ritardo" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__packages +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Packages" +msgstr "Colli" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "Partner document" +msgstr "Contatto del documento" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__partner_ref +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_partner_ref +msgid "Partner reference" +msgstr "Referenza del contatto" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard__picking_ids +msgid "Picking" +msgstr "Prelievo" + +#. module: l10n_it_delivery_note +#: model:ir.model,name:l10n_it_delivery_note.model_stock_picking_checker_mixin +msgid "Picking Checker Mixin" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__picking_type +msgid "Picking type" +msgstr "Tipo di consegna" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +msgid "Picking types" +msgstr "Tipi di consegna" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__picking_ids +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_create_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_select_form_view +msgid "Pickings" +msgstr "Consegne" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__pickings_picker +msgid "Pickings Picker" +msgstr "Raccoglitore prelievi" + +#. module: l10n_it_delivery_note +#: selection:stock.delivery.note,activity_state:0 +msgid "Planned" +msgstr "Pianificato" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_wizard_error_message_template +msgid "Please, check and solve these problems before trying again." +msgstr "Prego, controllare e risolvere questi problemi prima di riprovare." + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +msgid "Print" +msgstr "Stampa" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__product_id +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Product" +msgstr "Prodotto" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__product_qty +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Quantity" +msgstr "Quantità" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Reason of Transport" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_res_partner__default_transport_reason_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_res_users__default_transport_reason_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_sale_order__default_transport_reason_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__transport_reason_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__transport_reason_id +msgid "Reason of transport" +msgstr "Causale di trasporto" + +#. module: l10n_it_delivery_note +#: model:ir.actions.act_window,name:l10n_it_delivery_note.stock_picking_transport_reason_action +#: model:ir.ui.menu,name:l10n_it_delivery_note.stock_picking_transport_reason_menu +msgid "Reasons of transport" +msgstr "Motivi di trasporto" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__partner_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_base_wizard__partner_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_create_wizard__partner_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard__partner_id +msgid "Recipient" +msgstr "Destinatario" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Recipient's Signature" +msgstr "Firma del destinatario" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +msgid "Recipients" +msgstr "Destinatari" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +msgid "Reset to draft" +msgstr "Reimposta a bozza" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__activity_user_id +msgid "Responsible User" +msgstr "Utente responsabile" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__sale_ids +msgid "Sale" +msgstr "Vendita" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__sale_count +msgid "Sale Count" +msgstr "Numero vendite" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__product_description +msgid "Sale Description" +msgstr "Descrizione vendita" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__sale_line_id +msgid "Sale Line" +msgstr "Riga di vendita" + +#. module: l10n_it_delivery_note +#: model:ir.model,name:l10n_it_delivery_note.model_sale_order +msgid "Sale Order" +msgstr "Ordine di vendita" + +#. module: l10n_it_delivery_note +#: model:ir.model,name:l10n_it_delivery_note.model_sale_advance_payment_inv +msgid "Sales Advance Payment Invoice" +msgstr "Anticipo su fattura di vendita" + +#. module: l10n_it_delivery_note +#: model:ir.model,name:l10n_it_delivery_note.model_sale_order_line +msgid "Sales Order Line" +msgstr "Riga ordine di vendita" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__sales_transport_check +msgid "Sales Transport Check" +msgstr "Controllo Ordine Trasporto" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "Sales orders" +msgstr "Ordini di vendita" + +#. module: l10n_it_delivery_note +#: selection:stock.delivery.note.line,display_type:0 +msgid "Section" +msgstr "Sezione" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "Section name (e.g. Products, Services)" +msgstr "Nome sezione (es. Prodotti, Servizi)" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/models/stock_picking.py:197 +#: model:ir.actions.act_window,name:l10n_it_delivery_note.stock_delivery_note_select_action +#, python-format +msgid "Select an existing delivery note" +msgstr "Seleziona un DdT esistente" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +msgid "Select existing" +msgstr "Seleziona esistente" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_base_wizard__selected_picking_ids +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_create_wizard__selected_picking_ids +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard__selected_picking_ids +msgid "Selected Picking" +msgstr "Prelievi selezionati" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__partner_sender_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_base_wizard__partner_sender_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_create_wizard__partner_sender_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard__partner_sender_id +msgid "Sender" +msgstr "Mittente" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +msgid "Senders" +msgstr "Mittenti" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__sequence_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__sequence +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_sequence_id +msgid "Sequence" +msgstr "Sequenza" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +msgid "Set done" +msgstr "Segna come completato" + +#. module: l10n_it_delivery_note +#: model:ir.model,name:l10n_it_delivery_note.model_shipping_information_updater_mixin +msgid "Shipping Information Updater Mixin" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__partner_shipping_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_base_wizard__partner_shipping_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_create_wizard__partner_shipping_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard__partner_shipping_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_partner_shipping_id +msgid "Shipping address" +msgstr "Indirizzo di spedizione" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.res_partner_form_view +msgid "Shipping information" +msgstr "Informazioni spedizione" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__show_product_information +msgid "Show Product Information" +msgstr "Mostra le informazioni di prodotto" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__print_prices +msgid "Show prices on printed DN" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__state +msgid "State" +msgstr "Provincia" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +msgid "States" +msgstr "Condizioni" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,help:l10n_it_delivery_note.field_stock_delivery_note__activity_state +msgid "" +"Status based on activities\n" +"Overdue: Due date is already passed\n" +"Today: Activity date is today\n" +"Planned: Future activities." +msgstr "" +"Stato basato sulle attività\n" +"In ritardo: data di scadenza già superata\n" +"Oggi: attività in data odierna\n" +"Pianificato: attività future." + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_create_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_select_form_view +msgid "Summary" +msgstr "Sommario" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "Tax" +msgstr "Imposta" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "Tax excluded" +msgstr "Imponibile" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__tax_ids +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Taxes" +msgstr "Imposte" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/mixins/picking_checker.py:76 +#, python-format +msgid "" +"The pickings you've selected don't seem to have any location of departure." +msgstr "" +"I prelievi che hai selezionato non sembrano avere nessun luogo di partenza." + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/mixins/picking_checker.py:92 +#, python-format +msgid "" +"The pickings you've selected don't seem to have any location of destination." +msgstr "" +"I prelievi che hai selezionato non sembrano avere nessun luogo di " +"destinazione." + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/mixins/picking_checker.py:61 +#, python-format +msgid "" +"The pickings you've selected don't seem to have any partner or the selected " +"warehouse doesn't have a valid address." +msgstr "" +"I prelievi che hai selezionato non sembrano avere nessun partner oppure il " +"magazzino selezionato non ha un indirizzo valido." + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/mixins/picking_checker.py:43 +#, python-format +msgid "The pickings you've selected don't seem to have any type." +msgstr "I prelievi che hai selezionato non sembrano avere nessun tipo." + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.sale_advance_payment_inv_form_view +msgid "" +"There appears to be one or more delivery notes in \"Draft\" state.
\n" +" If you proceed with the creation of an invoice " +"(other than the downpayment one),\n" +" the affected delivery note lines will be detached " +"from the sales order and\n" +" will not appear linked to the generated invoice." +msgstr "" +"Sembra siano presenti uno o più DdT in stato \"Bozza\".
\n" +" Se si proseguirà con la creazione di una fattura " +"(diversa da quella di acconto),\n" +" le righe interessate di suddetti DdT verranno " +"scollegate dall'ordine di vendita e\n" +" non risulteranno associate alla fattura generata." + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_wizard_error_message_template +msgid "There are one or more problems with the pickings you've selected:" +msgstr "Sono presenti uno o più problemi con i prelievi che hai selezionato:" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.sale_advance_payment_inv_form_view +msgid "" +"This behaviour just described may not be wrong in some very specific cases." +"
\n" +" Proceed only if you are absolutely sure and aware of " +"what you're doing." +msgstr "" +"Questo comportamento appena descritto potrebbe non essere\n" +" necessariamente scorretto in alcuni casi molto " +"specifici.
\n" +" Proseguire solo ed esclusivamente se si è " +"assolutamente\n" +" sicuri e consci di quello che si sta facendo." + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +#: selection:stock.delivery.note,invoice_status:0 +#: selection:stock.delivery.note.line,invoice_status:0 +msgid "To invoice" +msgstr "Da fatturare" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "To pay" +msgstr "Da pagare" + +#. module: l10n_it_delivery_note +#: selection:stock.delivery.note,activity_state:0 +msgid "Today" +msgstr "Oggi" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "Total" +msgstr "Totale" + +#. module: l10n_it_delivery_note +#: model:ir.model,name:l10n_it_delivery_note.model_stock_picking +msgid "Transfer" +msgstr "Trasferimento" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__transport_datetime +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__transport_datetime +msgid "Transport date" +msgstr "Data di trasporto" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__type_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_base_wizard__type_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_create_wizard__type_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard__type_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_type_id +msgid "Type" +msgstr "Tipologia" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +msgid "Type codes" +msgstr "Codici tipo" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__type_code +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_type_code +msgid "Type of Operation" +msgstr "Tipo di operazione" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +msgid "Types" +msgstr "Tipi" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.sale_advance_payment_inv_form_view +msgid "Understood, continue anyway" +msgstr "Ho capito, continua ugualmente" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__price_unit +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Unit price" +msgstr "Prezzo unitario" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__message_unread +msgid "Unread Messages" +msgstr "Messaggi non letti" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__message_unread_counter +msgid "Unread Messages Counter" +msgstr "Numero messaggi non letti" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__product_uom_id +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "UoM" +msgstr "UdM" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +msgid "Update to now" +msgstr "Aggiorna ad adesso" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__use_advanced_behaviour +msgid "Use Advanced Behaviour" +msgstr "Usa funzioni avanzate" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_res_config_settings__group_use_advanced_delivery_notes +#: model:res.groups,name:l10n_it_delivery_note.use_advanced_delivery_notes +msgid "Use Advanced DN Features" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__use_delivery_note +msgid "Use Delivery Note" +msgstr "Usa il DdT" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__valid_move_ids +msgid "Valid Move" +msgstr "Movimenti validi" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +msgid "Validate" +msgstr "Valida" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +#: selection:stock.delivery.note,state:0 +msgid "Validated" +msgstr "Validato" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_search_view +msgid "Validated DN" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__volume +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +msgid "Volume" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__volume_uom_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_volume_uom_id +msgid "Volume UoM" +msgstr "UdM del volume" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__move_id +msgid "Warehouse movement" +msgstr "Movimento di magazzino" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/models/stock_delivery_note.py:325 +#: code:addons/l10n_it_delivery_note/models/stock_delivery_note.py:361 +#: code:addons/l10n_it_delivery_note/models/stock_picking.py:142 +#: code:addons/l10n_it_delivery_note/models/stock_picking.py:161 +#: code:addons/l10n_it_delivery_note/wizard/delivery_note_base.py:65 +#, python-format +msgid "Warning!" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__website_message_ids +msgid "Website Messages" +msgstr "Messaggi sito web" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,help:l10n_it_delivery_note.field_stock_delivery_note__website_message_ids +msgid "Website communication history" +msgstr "Cronologia comunicazioni sito web" + +#. module: l10n_it_delivery_note +#: sql_constraint:stock.delivery.note.line:0 +msgid "" +"You cannot assign the same warehouse movement to different delivery notes!" +msgstr "Non puoi assegnare lo stesso movimento di magazzino a DdT differenti!" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/models/stock_delivery_note.py:382 +#, python-format +msgid "" +"You cannot cancel this delivery note. There is at least one invoice related " +"to this delivery note." +msgstr "" +"Non puoi cancellare questo DdT. È presente, almeno, una fattura legata a " +"questo DdT." + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/models/stock_delivery_note.py:699 +#, python-format +msgid "" +"You cannot change the type of a delivery note line. Instead you should " +"delete the current line and create a new line of the proper type." +msgstr "" +"Non puoi cambiare il tipo della riga del DdT. Dovresti, invece, eliminare la " +"riga corrente e creare una riga nuova del tipo corretto." + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/models/stock_delivery_note.py:319 +#: code:addons/l10n_it_delivery_note/models/stock_picking.py:136 +#, python-format +msgid "" +"You cannot set this delivery note type due of a different numerator " +"configuration." +msgstr "" +"Non puoi cambiare il tipo del DdT a causa dell'uso di un numeratore " +"differente." + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/mixins/picking_checker.py:82 +#, python-format +msgid "You need to select pickings with all the same location of departure." +msgstr "È necessario selezionare prelievi con lo stesso luogo di destinazione." + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/mixins/picking_checker.py:98 +#, python-format +msgid "You need to select pickings with all the same location of destination." +msgstr "È necessario selezionare prelievi con lo stesso luogo di destinazione." + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/mixins/picking_checker.py:67 +#, python-format +msgid "You need to select pickings with all the same recipient." +msgstr "È necessario selezionare prelievi con lo stesso destinatario." + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/mixins/picking_checker.py:48 +#, python-format +msgid "You need to select pickings with all the same type." +msgstr "È necessario selezionare prelievi con lo stesso tipo." + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/mixins/picking_checker.py:25 +#, python-format +msgid "" +"You shouldn't be able to launch this wizard without selecting any pickings." +msgstr "" +"Non dovresti essere in grado di lanciare questo wizard senza selezionare " +"alcun prelievo." + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "best before" +msgstr "data di scadenza" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "lot / sn :" +msgstr "lotto / numero di serie:" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "of:" +msgstr "di:" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "qty" +msgstr "q.tà" diff --git a/l10n_it_delivery_note/i18n/l10n_it_delivery_note.pot b/l10n_it_delivery_note/i18n/l10n_it_delivery_note.pot new file mode 100644 index 000000000000..98bbf1c2e2c8 --- /dev/null +++ b/l10n_it_delivery_note/i18n/l10n_it_delivery_note.pot @@ -0,0 +1,1453 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * l10n_it_delivery_note +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.res_config_settings_form_view +msgid "(e.g. link multiple pickings to a single DN)" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.sale_advance_payment_inv_form_view +msgid " Warning!" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Phone:" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "VAT:" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "\n" +" Warning!\n" +" \n" +" Inconsistent DN info in sale orders!" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid " Delivery Note: \n" +" Under the terms of Italian Presidential Decree 472-96 of 14.08.1996" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Customer:" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Delivery address:" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.sale_advance_payment_inv_form_view +msgid "N.B.: there will be no way, subsequently, to restore\n" +" this binding between the delivery note lines with the related sales order." +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Warehouse:" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,help:l10n_it_delivery_note.field_stock_delivery_note_line__product_description +msgid "A description of the Product that you want to communicate to your customers. This description will be copied to every Sales Order, Delivery Order and Customer Invoice/Credit Note" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__message_needaction +msgid "Action Needed" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__active +msgid "Active" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__activity_ids +msgid "Activities" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__activity_state +msgid "Activity State" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "Add a note" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "Add a section" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:res.groups,name:l10n_it_delivery_note.can_change_number +msgid "Allow to change delivery note number" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_res_partner__default_goods_appearance_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_res_users__default_goods_appearance_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_sale_order__default_goods_appearance_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__goods_appearance_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__goods_appearance_id +msgid "Appearance of goods" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.actions.act_window,name:l10n_it_delivery_note.stock_picking_goods_appearance_action +#: model:ir.ui.menu,name:l10n_it_delivery_note.stock_picking_good_appearance_menu +msgid "Appearances of goods" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +msgid "Archived" +msgstr "" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/mixins/picking_checker.py:106 +#, python-format +msgid "At least one picking you've selected appears to be already related to another delivery note." +msgstr "" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/mixins/picking_checker.py:33 +#, python-format +msgid "At least one picking you've selected doesn't appear to be completed." +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__message_attachment_count +msgid "Attachment Count" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__can_be_invoiced +msgid "Can Be Invoiced" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__can_change_number +msgid "Can Change Number" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_create_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_select_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +msgid "Cancel" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +#: selection:stock.delivery.note,state:0 +msgid "Cancelled" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Carriage Condition" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__carrier_id +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +msgid "Carrier" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Carrier's Signature" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +msgid "Carriers" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model,name:l10n_it_delivery_note.model_res_company +msgid "Companies" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__company_id +msgid "Company" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_res_partner__default_transport_condition_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_res_users__default_transport_condition_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_sale_order__default_transport_condition_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__transport_condition_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__transport_condition_id +msgid "Condition of transport" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.actions.act_window,name:l10n_it_delivery_note.stock_picking_transport_condition_action +#: model:ir.ui.menu,name:l10n_it_delivery_note.stock_picking_transport_condition_menu +msgid "Conditions of transport" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model,name:l10n_it_delivery_note.model_res_config_settings +msgid "Config Settings" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_create_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_select_form_view +#: selection:sale.advance.payment.inv,step:0 +msgid "Confirm" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model,name:l10n_it_delivery_note.model_res_partner +msgid "Contact" +msgstr "" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/models/stock_picking.py:184 +#: model:ir.actions.act_window,name:l10n_it_delivery_note.stock_delivery_note_create_action +#, python-format +msgid "Create a new delivery note" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +msgid "Create invoice" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +msgid "Create new" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__create_uid +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_create_wizard__create_uid +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__create_uid +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard__create_uid +msgid "Created by" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__create_date +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_create_wizard__create_date +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__create_date +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard__create_date +msgid "Created on" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__currency_id +msgid "Currency" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_sale_advance_payment_inv__step +msgid "Current step" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_carrier_id +msgid "DN Carrier" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_date +msgid "DN Date" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__picking_type_code +msgid "DN Operation Type" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__packages +msgid "DN Packages" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_state +msgid "DN State" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_volume +msgid "DN Volume" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "DN date" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__date +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_base_wizard__date +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_create_wizard__date +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard__date +msgid "Date" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +msgid "Dates" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.actions.report,name:l10n_it_delivery_note.delivery_note_report_action +#: model:ir.model,name:l10n_it_delivery_note.model_stock_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_account_invoice_line__delivery_note_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_sale_order__delivery_note_ids +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__delivery_note_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard__delivery_note_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_id +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +msgid "Delivery Note" +msgstr "" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/models/account_invoice.py:103 +#, python-format +msgid "Delivery Note \"{}\" of {}" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model,name:l10n_it_delivery_note.model_stock_delivery_note_base_wizard +msgid "Delivery Note Base" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_account_invoice__delivery_note_count +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_sale_order__delivery_note_count +msgid "Delivery Note Count" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model,name:l10n_it_delivery_note.model_stock_delivery_note_create_wizard +msgid "Delivery Note Creator" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_draft +msgid "Delivery Note Draft" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_exists +msgid "Delivery Note Exists" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model,name:l10n_it_delivery_note.model_stock_delivery_note_line +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_sale_order_line__delivery_note_line_ids +msgid "Delivery Note Line" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_readonly +msgid "Delivery Note Readonly" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model,name:l10n_it_delivery_note.model_stock_delivery_note_select_wizard +msgid "Delivery Note Selector" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.actions.act_window,name:l10n_it_delivery_note.stock_delivery_note_type_action +#: model:ir.ui.menu,name:l10n_it_delivery_note.stock_delivery_note_type_menu +msgid "Delivery Note Types" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_visible +msgid "Delivery Note Visible" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.actions.act_window,name:l10n_it_delivery_note.stock_delivery_note_action +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_account_invoice__delivery_note_ids +#: model:ir.ui.menu,name:l10n_it_delivery_note.stock_delivery_note_config_menu +#: model:ir.ui.menu,name:l10n_it_delivery_note.stock_delivery_note_menu +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.account_invoice_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.res_config_settings_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +msgid "Delivery Notes" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_sale_order_line__delivery_picking_id +msgid "Delivery Picking" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__delivery_method_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_method_id +msgid "Delivery method" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__name +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Description" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "Details" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__discount +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Discount" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_shipping_information_updater_mixin__display_name +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__display_name +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_base_wizard__display_name +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_create_wizard__display_name +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__display_name +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard__display_name +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking_checker_mixin__display_name +msgid "Display Name" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "Document" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Document:" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +#: selection:stock.delivery.note,state:0 +msgid "Done" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +#: selection:stock.delivery.note,state:0 +msgid "Draft" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_search_view +msgid "Draft DN" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "Draft document" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Draft document:" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Driver's Signature" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_base_wizard__error_message +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_create_wizard__error_message +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard__error_message +msgid "Error Message" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__message_follower_ids +msgid "Followers" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__message_channel_ids +msgid "Followers (Channels)" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__message_partner_ids +msgid "Followers (Partners)" +msgstr "" + +#. module: l10n_it_delivery_note +#: selection:stock.delivery.note,invoice_status:0 +#: selection:stock.delivery.note.line,invoice_status:0 +msgid "Fully invoiced" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_tree_view +msgid "Go to delivery note" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "Go to invoice" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Goods Description" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Gross Weight" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__gross_weight +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__gross_weight +msgid "Gross weight" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__gross_weight_uom_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__gross_weight_uom_id +msgid "Gross weight UoM" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_shipping_information_updater_mixin__id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_base_wizard__id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_create_wizard__id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard__id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking_checker_mixin__id +msgid "ID" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,help:l10n_it_delivery_note.field_stock_delivery_note__message_unread +msgid "If checked new messages require your attention." +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,help:l10n_it_delivery_note.field_stock_delivery_note__message_needaction +msgid "If checked, new messages require your attention." +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,help:l10n_it_delivery_note.field_stock_delivery_note__message_has_error +msgid "If checked, some messages have a delivery error." +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_wizard_error_message_template +msgid "If these problems persist, don't hesitate to contact the helpdesk." +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +#: selection:stock.delivery.note,picking_type:0 +msgid "Incoming" +msgstr "" + +#. module: l10n_it_delivery_note +#: selection:sale.advance.payment.inv,step:0 +msgid "Initial" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +#: selection:stock.delivery.note,picking_type:0 +msgid "Internal" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_note +msgid "Internal note" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "Internal notes" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model,name:l10n_it_delivery_note.model_account_invoice +msgid "Invoice" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model,name:l10n_it_delivery_note.model_account_invoice_line +msgid "Invoice Line" +msgstr "" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/wizard/sale_advance_payment_inv.py:44 +#, python-format +msgid "Invoice Order" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__invoice_status +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__invoice_status +msgid "Invoice status" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +msgid "Invoice statuses" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +#: selection:stock.delivery.note,state:0 +msgid "Invoiced" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__invoice_ids +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "Invoices" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__message_is_follower +msgid "Is Follower" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.res_config_settings_form_view +msgid "It allows to prompt a confirmation to the user\n" +" during the invoicing action if there's at\n" +" least one unconfirmed delivery note." +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.res_config_settings_form_view +msgid "It extends the standard behaviour of DNs\n" +" management by introducing additional functions." +msgstr "" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/cli/migrate_l10n_it_ddt.py:98 +#, python-format +msgid "It seems that at least one delivery note has been already created. You can't migrate any data on an already used database." +msgstr "" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/cli/migrate_l10n_it_ddt.py:91 +#, python-format +msgid "It seems that there are no documents to migrate. You don't need to run this command." +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_shipping_information_updater_mixin____last_update +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note____last_update +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_base_wizard____last_update +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_create_wizard____last_update +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line____last_update +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard____last_update +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking_checker_mixin____last_update +msgid "Last Modified on" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__write_uid +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_create_wizard__write_uid +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__write_uid +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__write_date +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_create_wizard__write_date +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__write_date +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard__write_date +msgid "Last Updated on" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__display_type +msgid "Line type" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__line_ids +msgid "Lines" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__message_main_attachment_id +msgid "Main Attachment" +msgstr "" + +#. module: l10n_it_delivery_note +#: selection:stock.delivery.note,picking_type:0 +msgid "Manufacturing Operation" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__message_has_error +msgid "Message Delivery error" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__message_ids +msgid "Messages" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Method of Transport / Carrier" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_res_partner__default_transport_method_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_res_users__default_transport_method_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_sale_order__default_transport_method_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__transport_method_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__transport_method_id +msgid "Method of transport" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.actions.act_window,name:l10n_it_delivery_note.stock_picking_transport_method_action +#: model:ir.ui.menu,name:l10n_it_delivery_note.stock_picking_transport_method_menu +msgid "Methods of transport" +msgstr "" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/cli/migrate_l10n_it_ddt.py:84 +#, python-format +msgid "Module `l10n_it_ddt` isn't installed on this database. You don't need to run this command." +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__name +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_tree_view +msgid "Name" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Net Weight" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__net_weight +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__net_weight +msgid "Net weight" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__net_weight_uom_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__net_weight_uom_id +msgid "Net weight UoM" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__activity_date_deadline +msgid "Next Activity Deadline" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__activity_summary +msgid "Next Activity Summary" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__activity_type_id +msgid "Next Activity Type" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_search_view +msgid "No DN" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +#: selection:stock.delivery.note.line,display_type:0 +msgid "Note" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Notes" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +#: selection:stock.delivery.note,invoice_status:0 +#: selection:stock.delivery.note.line,invoice_status:0 +msgid "Nothing to invoice" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_res_company__draft_delivery_note_invoicing_notify +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_res_config_settings__draft_delivery_note_invoicing_notify +msgid "Notify if delivery note isn't validated" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__message_needaction_counter +msgid "Number of Actions" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__message_has_error_counter +msgid "Number of error" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,help:l10n_it_delivery_note.field_stock_delivery_note__message_needaction_counter +msgid "Number of messages which requires an action" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,help:l10n_it_delivery_note.field_stock_delivery_note__message_has_error_counter +msgid "Number of messages with delivery error" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,help:l10n_it_delivery_note.field_stock_delivery_note__message_unread_counter +msgid "Number of unread messages" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "Open picking" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +#: selection:stock.delivery.note,picking_type:0 +msgid "Outgoing" +msgstr "" + +#. module: l10n_it_delivery_note +#: selection:stock.delivery.note,activity_state:0 +msgid "Overdue" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__packages +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Packages" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "Partner document" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__partner_ref +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_partner_ref +msgid "Partner reference" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard__picking_ids +msgid "Picking" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model,name:l10n_it_delivery_note.model_stock_picking_checker_mixin +msgid "Picking Checker Mixin" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__picking_type +msgid "Picking type" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +msgid "Picking types" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__picking_ids +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_create_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_select_form_view +msgid "Pickings" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__pickings_picker +msgid "Pickings Picker" +msgstr "" + +#. module: l10n_it_delivery_note +#: selection:stock.delivery.note,activity_state:0 +msgid "Planned" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_wizard_error_message_template +msgid "Please, check and solve these problems before trying again." +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +msgid "Print" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__product_id +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Product" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__product_qty +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Quantity" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Reason of Transport" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_res_partner__default_transport_reason_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_res_users__default_transport_reason_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_sale_order__default_transport_reason_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__transport_reason_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__transport_reason_id +msgid "Reason of transport" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.actions.act_window,name:l10n_it_delivery_note.stock_picking_transport_reason_action +#: model:ir.ui.menu,name:l10n_it_delivery_note.stock_picking_transport_reason_menu +msgid "Reasons of transport" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__partner_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_base_wizard__partner_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_create_wizard__partner_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard__partner_id +msgid "Recipient" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Recipient's Signature" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +msgid "Recipients" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +msgid "Reset to draft" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__activity_user_id +msgid "Responsible User" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__sale_ids +msgid "Sale" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__sale_count +msgid "Sale Count" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__product_description +msgid "Sale Description" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__sale_line_id +msgid "Sale Line" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model,name:l10n_it_delivery_note.model_sale_order +msgid "Sale Order" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model,name:l10n_it_delivery_note.model_sale_advance_payment_inv +msgid "Sales Advance Payment Invoice" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model,name:l10n_it_delivery_note.model_sale_order_line +msgid "Sales Order Line" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__sales_transport_check +msgid "Sales Transport Check" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "Sales orders" +msgstr "" + +#. module: l10n_it_delivery_note +#: selection:stock.delivery.note.line,display_type:0 +msgid "Section" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "Section name (e.g. Products, Services)" +msgstr "" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/models/stock_picking.py:197 +#: model:ir.actions.act_window,name:l10n_it_delivery_note.stock_delivery_note_select_action +#, python-format +msgid "Select an existing delivery note" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +msgid "Select existing" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_base_wizard__selected_picking_ids +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_create_wizard__selected_picking_ids +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard__selected_picking_ids +msgid "Selected Picking" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__partner_sender_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_base_wizard__partner_sender_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_create_wizard__partner_sender_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard__partner_sender_id +msgid "Sender" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +msgid "Senders" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__sequence_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__sequence +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_sequence_id +msgid "Sequence" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +msgid "Set done" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model,name:l10n_it_delivery_note.model_shipping_information_updater_mixin +msgid "Shipping Information Updater Mixin" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__partner_shipping_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_base_wizard__partner_shipping_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_create_wizard__partner_shipping_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard__partner_shipping_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_partner_shipping_id +msgid "Shipping address" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.res_partner_form_view +msgid "Shipping information" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__show_product_information +msgid "Show Product Information" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__print_prices +msgid "Show prices on printed DN" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__state +msgid "State" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +msgid "States" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,help:l10n_it_delivery_note.field_stock_delivery_note__activity_state +msgid "Status based on activities\n" +"Overdue: Due date is already passed\n" +"Today: Activity date is today\n" +"Planned: Future activities." +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_create_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_select_form_view +msgid "Summary" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "Tax" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "Tax excluded" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__tax_ids +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Taxes" +msgstr "" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/mixins/picking_checker.py:76 +#, python-format +msgid "The pickings you've selected don't seem to have any location of departure." +msgstr "" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/mixins/picking_checker.py:92 +#, python-format +msgid "The pickings you've selected don't seem to have any location of destination." +msgstr "" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/mixins/picking_checker.py:61 +#, python-format +msgid "The pickings you've selected don't seem to have any partner or the selected warehouse doesn't have a valid address." +msgstr "" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/mixins/picking_checker.py:43 +#, python-format +msgid "The pickings you've selected don't seem to have any type." +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.sale_advance_payment_inv_form_view +msgid "There appears to be one or more delivery notes in \"Draft\" state.
\n" +" If you proceed with the creation of an invoice (other than the downpayment one),\n" +" the affected delivery note lines will be detached from the sales order and\n" +" will not appear linked to the generated invoice." +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_wizard_error_message_template +msgid "There are one or more problems with the pickings you've selected:" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.sale_advance_payment_inv_form_view +msgid "This behaviour just described may not be wrong in some very specific cases.
\n" +" Proceed only if you are absolutely sure and aware of what you're doing." +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +#: selection:stock.delivery.note,invoice_status:0 +#: selection:stock.delivery.note.line,invoice_status:0 +msgid "To invoice" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "To pay" +msgstr "" + +#. module: l10n_it_delivery_note +#: selection:stock.delivery.note,activity_state:0 +msgid "Today" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +msgid "Total" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model,name:l10n_it_delivery_note.model_stock_picking +msgid "Transfer" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__transport_datetime +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__transport_datetime +msgid "Transport date" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__type_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_base_wizard__type_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_create_wizard__type_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_select_wizard__type_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_type_id +msgid "Type" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +msgid "Type codes" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__type_code +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_type_code +msgid "Type of Operation" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +msgid "Types" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.sale_advance_payment_inv_form_view +msgid "Understood, continue anyway" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__price_unit +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "Unit price" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__message_unread +msgid "Unread Messages" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__message_unread_counter +msgid "Unread Messages Counter" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__product_uom_id +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "UoM" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +msgid "Update to now" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__use_advanced_behaviour +msgid "Use Advanced Behaviour" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_res_config_settings__group_use_advanced_delivery_notes +#: model:res.groups,name:l10n_it_delivery_note.use_advanced_delivery_notes +msgid "Use Advanced DN Features" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__use_delivery_note +msgid "Use Delivery Note" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__valid_move_ids +msgid "Valid Move" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_form_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +msgid "Validate" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_delivery_note_search_view +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +#: selection:stock.delivery.note,state:0 +msgid "Validated" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_search_view +msgid "Validated DN" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__volume +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.stock_picking_form_view +msgid "Volume" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__volume_uom_id +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_picking__delivery_note_volume_uom_id +msgid "Volume UoM" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note_line__move_id +msgid "Warehouse movement" +msgstr "" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/models/stock_delivery_note.py:325 +#: code:addons/l10n_it_delivery_note/models/stock_delivery_note.py:361 +#: code:addons/l10n_it_delivery_note/models/stock_picking.py:142 +#: code:addons/l10n_it_delivery_note/models/stock_picking.py:161 +#: code:addons/l10n_it_delivery_note/wizard/delivery_note_base.py:65 +#, python-format +msgid "Warning!" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,field_description:l10n_it_delivery_note.field_stock_delivery_note__website_message_ids +msgid "Website Messages" +msgstr "" + +#. module: l10n_it_delivery_note +#: model:ir.model.fields,help:l10n_it_delivery_note.field_stock_delivery_note__website_message_ids +msgid "Website communication history" +msgstr "" + +#. module: l10n_it_delivery_note +#: sql_constraint:stock.delivery.note.line:0 +msgid "You cannot assign the same warehouse movement to different delivery notes!" +msgstr "" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/models/stock_delivery_note.py:382 +#, python-format +msgid "You cannot cancel this delivery note. There is at least one invoice related to this delivery note." +msgstr "" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/models/stock_delivery_note.py:699 +#, python-format +msgid "You cannot change the type of a delivery note line. Instead you should delete the current line and create a new line of the proper type." +msgstr "" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/models/stock_delivery_note.py:319 +#: code:addons/l10n_it_delivery_note/models/stock_picking.py:136 +#, python-format +msgid "You cannot set this delivery note type due of a different numerator configuration." +msgstr "" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/mixins/picking_checker.py:82 +#, python-format +msgid "You need to select pickings with all the same location of departure." +msgstr "" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/mixins/picking_checker.py:98 +#, python-format +msgid "You need to select pickings with all the same location of destination." +msgstr "" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/mixins/picking_checker.py:67 +#, python-format +msgid "You need to select pickings with all the same recipient." +msgstr "" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/mixins/picking_checker.py:48 +#, python-format +msgid "You need to select pickings with all the same type." +msgstr "" + +#. module: l10n_it_delivery_note +#: code:addons/l10n_it_delivery_note/mixins/picking_checker.py:25 +#, python-format +msgid "You shouldn't be able to launch this wizard without selecting any pickings." +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "best before" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "lot / sn :" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "of:" +msgstr "" + +#. module: l10n_it_delivery_note +#: model_terms:ir.ui.view,arch_db:l10n_it_delivery_note.delivery_note_report_template +msgid "qty" +msgstr "" + diff --git a/l10n_it_delivery_note/mixins/__init__.py b/l10n_it_delivery_note/mixins/__init__.py new file mode 100644 index 000000000000..5fb6adab4175 --- /dev/null +++ b/l10n_it_delivery_note/mixins/__init__.py @@ -0,0 +1,2 @@ +from . import picking_checker +from . import shipping_updater diff --git a/l10n_it_delivery_note/mixins/picking_checker.py b/l10n_it_delivery_note/mixins/picking_checker.py new file mode 100644 index 000000000000..4dba4895ba1d --- /dev/null +++ b/l10n_it_delivery_note/mixins/picking_checker.py @@ -0,0 +1,118 @@ +# Copyright (c) 2019, Link IT Europe Srl +# @author: Matteo Bilotta + +from odoo import _, api, models +from odoo.exceptions import ValidationError + +DONE_PICKING_STATE = 'done' + +PICKING_TYPES = [ + ('incoming', "Incoming"), + ('outgoing', "Outgoing"), + ('internal', "Internal"), + ('mrp_operation', "Manufacturing Operation") +] +DOMAIN_PICKING_TYPES = [t[0] for t in PICKING_TYPES] + + +class StockPickingCheckerMixin(models.AbstractModel): + _name = 'stock.picking.checker.mixin' + _description = "Picking Checker Mixin" + + @api.model + def _check_pickings(self, pickings): + if not pickings: + raise ValidationError(_( + "You shouldn't be able to launch this wizard " + "without selecting any pickings." + )) + + @api.model + def _check_pickings_state(self, pickings): + if pickings.filtered(lambda p: p.state != DONE_PICKING_STATE): + raise ValidationError(_( + "At least one picking you've selected doesn't " + "appear to be completed." + )) + + @api.model + def _check_pickings_types(self, pickings): + types = set(pickings.mapped('picking_type_code')) + + if not types: + raise ValidationError(_( + "The pickings you've selected don't seem to have any type." + )) + + if len(types) > 1: + raise ValidationError(_( + "You need to select pickings with all the same type." + )) + + @api.model + def _check_pickings_partners(self, pickings): + types = set(pickings.mapped('picking_type_code')) + if 'internal' in types: + return + + partners = pickings.mapped('partner_id') + + if not partners: + raise ValidationError(_( + "The pickings you've selected don't seem to have any partner" + " or the selected warehouse doesn't have a valid address." + )) + + if len(partners) > 1: + raise ValidationError(_( + "You need to select pickings with all the same recipient." + )) + + @api.model + def _check_pickings_src_locations(self, pickings): + src_locations = pickings.mapped('location_id') + + if not src_locations: + raise ValidationError(_( + "The pickings you've selected don't seem to " + "have any location of departure." + )) + + if len(src_locations) > 1: + raise ValidationError(_( + "You need to select pickings with all the same " + "location of departure." + )) + + @api.model + def _check_pickings_dest_locations(self, pickings): + dest_locations = pickings.mapped('location_dest_id') + + if not dest_locations: + raise ValidationError(_( + "The pickings you've selected don't seem to have any " + "location of destination." + )) + + if len(dest_locations) > 1: + raise ValidationError(_( + "You need to select pickings with all the same location " + "of destination." + )) + + @api.model + def _check_delivery_notes(self, pickings): + if pickings.filtered(lambda p: p.delivery_note_id): + raise ValidationError(_( + "At least one picking you've selected appears to" + " be already related to another delivery note." + )) + + @api.model + def check_compliance(self, pickings): + self._check_pickings(pickings) + self._check_pickings_state(pickings) + self._check_pickings_types(pickings) + self._check_pickings_partners(pickings) + self._check_pickings_src_locations(pickings) + self._check_pickings_dest_locations(pickings) diff --git a/l10n_it_delivery_note/mixins/shipping_updater.py b/l10n_it_delivery_note/mixins/shipping_updater.py new file mode 100644 index 000000000000..ac60be5c6378 --- /dev/null +++ b/l10n_it_delivery_note/mixins/shipping_updater.py @@ -0,0 +1,61 @@ +# Copyright (c) 2020, Link IT Europe Srl +# @author: Matteo Bilotta + +from odoo import models + + +class ShippingInformationUpdaterMixin(models.AbstractModel): + _name = 'shipping.information.updater.mixin' + _description = "Shipping Information Updater Mixin" + + def _update_generic_shipping_information(self, record): + changed = False + + if record.default_transport_condition_id and \ + self.transport_condition_id != \ + record.default_transport_condition_id: + if self.transport_condition_id: + changed = True + + self.transport_condition_id = record.default_transport_condition_id + + if record.default_goods_appearance_id and \ + self.goods_appearance_id != \ + record.default_goods_appearance_id: + if self.goods_appearance_id: + changed = True + + self.goods_appearance_id = record.default_goods_appearance_id + + if record.default_transport_reason_id and \ + self.transport_reason_id != \ + record.default_transport_reason_id: + if self.transport_reason_id: + changed = True + + self.transport_reason_id = record.default_transport_reason_id + + if record.default_transport_method_id and \ + self.transport_method_id != \ + record.default_transport_method_id: + if self.transport_method_id: + changed = True + + self.transport_method_id = record.default_transport_method_id + + return changed + + def _update_partner_shipping_information(self, partner): + changed = False + + if partner.property_delivery_carrier_id and \ + self.delivery_method_id != \ + partner.property_delivery_carrier_id: + if self.delivery_method_id: + changed = True + + self.delivery_method_id = partner.property_delivery_carrier_id + + changed |= self._update_generic_shipping_information(partner) + + return changed diff --git a/l10n_it_delivery_note/models/__init__.py b/l10n_it_delivery_note/models/__init__.py new file mode 100644 index 000000000000..d8e086570206 --- /dev/null +++ b/l10n_it_delivery_note/models/__init__.py @@ -0,0 +1,7 @@ +from . import account_invoice +from . import res_company +from . import res_config_settings +from . import res_partner +from . import sale_order +from . import stock_delivery_note +from . import stock_picking diff --git a/l10n_it_delivery_note/models/account_invoice.py b/l10n_it_delivery_note/models/account_invoice.py new file mode 100644 index 000000000000..cf099023d735 --- /dev/null +++ b/l10n_it_delivery_note/models/account_invoice.py @@ -0,0 +1,116 @@ +# Copyright 2014-2019 Dinamiche Aziendali srl +# (http://www.dinamicheaziendali.it/) +# @author: Marco Calcagni +# @author: Gianmarco Conte +# Copyright (c) 2019, Link IT Europe Srl +# @author: Matteo Bilotta +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import _, api, fields, models + +from .stock_delivery_note import DATE_FORMAT + + +class AccountInvoice(models.Model): + _inherit = 'account.invoice' + + delivery_note_ids = \ + fields.Many2many('stock.delivery.note', + 'stock_delivery_note_account_invoice_rel', + 'invoice_id', + 'delivery_note_id', + string="Delivery Notes", copy=False) + + delivery_note_count = \ + fields.Integer(compute='_compute_delivery_note_count') + + @api.multi + def _compute_delivery_note_count(self): + for invoice in self: + invoice.delivery_note_count = len(invoice.delivery_note_ids) + + @api.multi + def goto_delivery_notes(self, **kwargs): + delivery_notes = self.mapped('delivery_note_ids') + action = self.env.ref('l10n_it_delivery_note.' + 'stock_delivery_note_action').read()[0] + action.update(kwargs) + + if len(delivery_notes) > 1: + action['domain'] = [('id', 'in', delivery_notes.ids)] + + elif len(delivery_notes) == 1: + action['views'] = \ + [(self.env.ref('l10n_it_delivery_note.' + 'stock_delivery_note_form_view').id, 'form')] + action['res_id'] = delivery_notes.id + + else: + action = {'type': 'ir.actions.act_window_close'} + + return action + + def goto_invoice(self, **kwargs): + self.ensure_one() + + if self.type.startswith('out_'): + view_id = self.env.ref('account.invoice_form').id + + else: + view_id = False + + return { + 'type': 'ir.actions.act_window', + 'res_model': 'account.invoice', + 'res_id': self.id, + 'views': [(view_id, 'form')], + 'view_type': 'form', + 'view_mode': 'form', + 'target': 'current', + **kwargs + } + + @api.multi + def update_delivery_note_lines(self): + context = {} + + for invoice in self.filtered(lambda i: i.delivery_note_ids): + new_lines = [] + old_lines = \ + invoice.invoice_line_ids.filtered(lambda l: l.delivery_note_id) + old_lines.unlink() + + # + # TODO: Come bisogna comportarsi nel caso in + # cui il DdT non sia un DdT "valido"? + # Al momento, potrebbe essere possibile avere + # sia sei DdT senza numero (non ancora confermati) + # così come è possibile avere dei DdT senza, necessariamente, + # data di trasporto (non è un campo obbligatorio). + # + + # + # THIS ALLOWS TO CHANGE TRANSLATION LANGUAGE FOR EVERY INVOICE! + # + # See: odoo/tools/translate.py -> 'def _get_lang(self, frame):' + # + context['lang'] = invoice.partner_id.lang + + for note in invoice.delivery_note_ids: + new_lines.append((0, False, { + 'sequence': 99, 'display_type': 'line_note', + 'name': + _("""Delivery Note "{}" of {}"""). + format(note.name, note.date.strftime(DATE_FORMAT)), + 'delivery_note_id': note.id + })) + + invoice.write({'invoice_line_ids': new_lines}) + + +class AccountInvoiceLine(models.Model): + _inherit = 'account.invoice.line' + + delivery_note_id = fields.Many2one('stock.delivery.note', + string="Delivery Note", + readonly=True, copy=False) diff --git a/l10n_it_delivery_note/models/res_company.py b/l10n_it_delivery_note/models/res_company.py new file mode 100644 index 000000000000..757287698de0 --- /dev/null +++ b/l10n_it_delivery_note/models/res_company.py @@ -0,0 +1,8 @@ +from odoo import fields, models + + +class ResCompany(models.Model): + _inherit = 'res.company' + + draft_delivery_note_invoicing_notify = \ + fields.Boolean(string="Notify if delivery note isn't validated") diff --git a/l10n_it_delivery_note/models/res_config_settings.py b/l10n_it_delivery_note/models/res_config_settings.py new file mode 100644 index 000000000000..e6c7877fbbbb --- /dev/null +++ b/l10n_it_delivery_note/models/res_config_settings.py @@ -0,0 +1,17 @@ +# Copyright (c) 2019, Link IT Europe Srl +# @author: Matteo Bilotta + +from odoo import fields, models + + +class ResConfigSettings(models.TransientModel): + _inherit = 'res.config.settings' + + group_use_advanced_delivery_notes = fields.Boolean( + string="Use Advanced DN Features", + implied_group='l10n_it_delivery_note.' + 'use_advanced_delivery_notes') + + draft_delivery_note_invoicing_notify = fields.Boolean( + related='company_id.draft_delivery_note_invoicing_notify', + readonly=False) diff --git a/l10n_it_delivery_note/models/res_partner.py b/l10n_it_delivery_note/models/res_partner.py new file mode 100644 index 000000000000..88a16819cef5 --- /dev/null +++ b/l10n_it_delivery_note/models/res_partner.py @@ -0,0 +1,21 @@ +# Copyright (c) 2019, Link IT Europe Srl +# @author: Matteo Bilotta + +from odoo import fields, models + + +class ResPartner(models.Model): + _inherit = 'res.partner' + + default_transport_condition_id = fields.Many2one( + 'stock.picking.transport.condition', + string="Condition of transport") + default_goods_appearance_id = fields.Many2one( + 'stock.picking.goods.appearance', + string="Appearance of goods") + default_transport_reason_id = fields.Many2one( + 'stock.picking.transport.reason', + string="Reason of transport") + default_transport_method_id = fields.Many2one( + 'stock.picking.transport.method', + string="Method of transport") diff --git a/l10n_it_delivery_note/models/sale_order.py b/l10n_it_delivery_note/models/sale_order.py new file mode 100644 index 000000000000..d40dbc30396c --- /dev/null +++ b/l10n_it_delivery_note/models/sale_order.py @@ -0,0 +1,199 @@ +# Copyright (c) 2019, Link IT Europe Srl +# @author: Matteo Bilotta + +from odoo import api, fields, models + +from .stock_delivery_note import \ + DOMAIN_DELIVERY_NOTE_STATES, DOMAIN_INVOICE_STATUSES + + +class SaleOrder(models.Model): + _inherit = 'sale.order' + + delivery_note_ids = fields.Many2many( + 'stock.delivery.note', + compute='_compute_delivery_notes') + delivery_note_count = fields.Integer(compute='_compute_delivery_notes') + + default_transport_condition_id = fields.Many2one( + 'stock.picking.transport.condition', + string="Condition of transport", + default=False) + default_goods_appearance_id = fields.Many2one( + 'stock.picking.goods.appearance', + string="Appearance of goods", + default=False) + default_transport_reason_id = fields.Many2one( + 'stock.picking.transport.reason', + string="Reason of transport", + default=False) + default_transport_method_id = fields.Many2one( + 'stock.picking.transport.method', + string="Method of transport", + default=False) + + @api.onchange('partner_id') + def onchange_partner_id_shipping_info(self): + if self.partner_id: + values = { + 'default_transport_condition_id': + self.partner_id.default_transport_condition_id, + 'default_goods_appearance_id': + self.partner_id.default_goods_appearance_id, + 'default_transport_reason_id': + self.partner_id.default_transport_reason_id, + 'default_transport_method_id': + self.partner_id.default_transport_method_id, + } + + else: + values = { + 'default_transport_condition_id': False, + 'default_goods_appearance_id': False, + 'default_transport_reason_id': False, + 'default_transport_method_id': False, + } + + self.update(values) + + @api.multi + def _compute_delivery_notes(self): + for order in self: + delivery_notes = order.order_line.mapped('delivery_note_line_ids.' + 'delivery_note_id') + + order.delivery_note_ids = delivery_notes + order.delivery_note_count = len(delivery_notes) + + @api.multi + def _assign_delivery_notes_invoices(self, invoice_ids): + order_lines = self.mapped('order_line') \ + .filtered(lambda l: l.is_invoiced and l.delivery_note_line_ids) + + delivery_note_lines = order_lines.mapped('delivery_note_line_ids') \ + .filtered(lambda l: l.is_invoiceable) + delivery_notes = delivery_note_lines.mapped('delivery_note_id') + + ready_delivery_notes = delivery_notes \ + .filtered(lambda n: n.state != DOMAIN_DELIVERY_NOTE_STATES[0]) + + draft_delivery_notes = delivery_notes - ready_delivery_notes + draft_delivery_note_lines = \ + draft_delivery_notes.mapped('line_ids') & delivery_note_lines + + ready_delivery_note_lines = \ + delivery_note_lines - draft_delivery_note_lines + + # + # TODO: È necessario gestire il caso di fatturazione splittata + # di una stessa riga d'ordine associata ad una sola + # picking (e di conseguenza, ad un solo DdT)? + # Può essere, invece, un caso "borderline" + # da lasciar gestire all'operatore? + # Personalmente, non lo gestirei e delegherei + # all'operatore questa responsabilità... + # + + draft_delivery_note_lines.write({ + 'invoice_status': DOMAIN_INVOICE_STATUSES[0], + 'sale_line_id': None + }) + + ready_delivery_note_lines.write({ + 'invoice_status': DOMAIN_INVOICE_STATUSES[2] + }) + ready_delivery_notes.write({ + 'invoice_ids': [(4, invoice_id) for invoice_id in invoice_ids] + }) + + ready_delivery_notes._compute_invoice_status() + + @api.multi + def _generate_delivery_note_lines(self, invoice_ids): + invoices = self.env['account.invoice'].browse(invoice_ids) + invoices.update_delivery_note_lines() + + @api.multi + def action_invoice_create(self, grouped=False, final=False): + invoice_ids = super().action_invoice_create(grouped=grouped, + final=final) + + self._assign_delivery_notes_invoices(invoice_ids) + self._generate_delivery_note_lines(invoice_ids) + + return invoice_ids + + @api.multi + def goto_delivery_notes(self, **kwargs): + delivery_notes = self.mapped('delivery_note_ids') + action = self.env.ref('l10n_it_delivery_note.' + 'stock_delivery_note_action').read()[0] + action.update(kwargs) + + if len(delivery_notes) > 1: + action['domain'] = [('id', 'in', delivery_notes.ids)] + + elif len(delivery_notes) == 1: + action['views'] = [( + self.env.ref('l10n_it_delivery_note.' + 'stock_delivery_note_form_view').id, 'form')] + action['res_id'] = delivery_notes.id + + else: + action = {'type': 'ir.actions.act_window_close'} + + return action + + +class SaleOrderLine(models.Model): + _inherit = 'sale.order.line' + + delivery_note_line_ids = fields.One2many('stock.delivery.note.line', + 'sale_line_id', readonly=True) + delivery_picking_id = fields.Many2one('stock.picking', readonly=True, + copy=False) + + @property + def has_picking(self): + return self.move_ids or (self.is_delivery and self.delivery_picking_id) + + @property + def is_invoiceable(self): + return self.invoice_status == DOMAIN_INVOICE_STATUSES[1] and \ + self.qty_to_invoice != 0 + + @property + def is_invoiced(self): + return self.invoice_status != DOMAIN_INVOICE_STATUSES[1] and \ + self.qty_invoiced != 0 + + @property + def need_to_be_invoiced(self): + return self.product_uom_qty != (self.qty_to_invoice + self.qty_invoiced) + + def fix_qty_to_invoice(self, new_qty_to_invoice=0): + self.ensure_one() + + cache = { + 'invoice_status': self.invoice_status, + 'qty_to_invoice': self.qty_to_invoice + } + + self.write({ + 'invoice_status': 'to invoice' if new_qty_to_invoice else 'no', + 'qty_to_invoice': new_qty_to_invoice + }) + + return cache + + def is_pickings_related(self, picking_ids): + if self.is_delivery: + return self.delivery_picking_id in picking_ids + + return bool(self.move_ids & picking_ids.mapped('move_lines')) + + @api.multi + @api.returns('self') + def retrieve_pickings_lines(self, picking_ids): + return self.filtered(lambda l: l.has_picking) \ + .filtered(lambda l: l.is_pickings_related(picking_ids)) diff --git a/l10n_it_delivery_note/models/stock_delivery_note.py b/l10n_it_delivery_note/models/stock_delivery_note.py new file mode 100644 index 000000000000..eb97a63f0586 --- /dev/null +++ b/l10n_it_delivery_note/models/stock_delivery_note.py @@ -0,0 +1,712 @@ +# Copyright (c) 2019, Link IT Europe Srl +# @author: Matteo Bilotta + +import datetime + +from odoo import _, api, fields, models +from odoo.addons import decimal_precision as dp +from odoo.exceptions import UserError + +from ..mixins.picking_checker import DONE_PICKING_STATE, PICKING_TYPES + +DATE_FORMAT = '%d/%m/%Y' +DATETIME_FORMAT = '%d/%m/%Y %H:%M:%S' + +DELIVERY_NOTE_STATES = [ + ('draft', "Draft"), + ('confirm', "Validated"), + ('invoiced', "Invoiced"), + ('done', "Done"), + ('cancel', "Cancelled") +] +DOMAIN_DELIVERY_NOTE_STATES = [s[0] for s in DELIVERY_NOTE_STATES] + +LINE_DISPLAY_TYPES = [ + ('line_section', "Section"), + ('line_note', "Note") +] +DOMAIN_LINE_DISPLAY_TYPES = [t[0] for t in LINE_DISPLAY_TYPES] + +DRAFT_EDITABLE_STATE = {'draft': [('readonly', False)]} +DONE_READONLY_STATE = {'done': [('readonly', True)]} + +INVOICE_STATUSES = [ + ('no', "Nothing to invoice"), + ('to invoice', "To invoice"), + ('invoiced', "Fully invoiced") +] +DOMAIN_INVOICE_STATUSES = [s[0] for s in INVOICE_STATUSES] + + +class StockDeliveryNote(models.Model): + _name = 'stock.delivery.note' + _inherit = [ + 'mail.thread', + 'mail.activity.mixin', + 'stock.picking.checker.mixin', + 'shipping.information.updater.mixin' + ] + _description = "Delivery Note" + _order = 'date DESC, id DESC' + + def _default_company(self): + return self.env.user.company_id + + def _default_type(self): + return self.env['stock.delivery.note.type'].search([], limit=1) + + def _default_volume_uom(self): + return self.env.ref('uom.product_uom_litre', raise_if_not_found=False) + + def _domain_volume_uom(self): + uom_category_id = self.env.ref('uom.product_uom_categ_vol', + raise_if_not_found=False) + + return [('category_id', '=', uom_category_id.id)] + + def _default_weight_uom(self): + return self.env.ref('uom.product_uom_kgm', raise_if_not_found=False) + + def _domain_weight_uom(self): + uom_category_id = self.env.ref('uom.product_uom_categ_kgm', + raise_if_not_found=False) + + return [('category_id', '=', uom_category_id.id)] + + active = fields.Boolean(default=True) + name = fields.Char(string="Name", readonly=True, index=True, copy=False, + track_visibility='onchange') + partner_ref = fields.Char(string="Partner reference", + index=True, + copy=False, + states=DONE_READONLY_STATE, + track_visibility='onchange') + display_name = fields.Char(compute='_compute_display_name', store=True, + index=True, copy=False) + + state = fields.Selection(DELIVERY_NOTE_STATES, + string="State", + copy=False, + default=DOMAIN_DELIVERY_NOTE_STATES[0], + required=True, + track_visibility='onchange') + + partner_sender_id = fields.Many2one('res.partner', + string="Sender", + states=DRAFT_EDITABLE_STATE, + default=_default_company, + readonly=True, + required=True, + track_visibility='onchange') + + partner_id = fields.Many2one('res.partner', + string="Recipient", + states=DRAFT_EDITABLE_STATE, + readonly=True, + required=True, + index=True, + track_visibility='onchange') + partner_shipping_id = fields.Many2one('res.partner', + string="Shipping address", + states=DONE_READONLY_STATE, + required=True, + track_visibility='onchange') + + carrier_id = fields.Many2one('res.partner', + string="Carrier", + states=DONE_READONLY_STATE, + track_visibility='onchange') + delivery_method_id = fields.Many2one('delivery.carrier', + string="Delivery method", + states=DONE_READONLY_STATE, + track_visibility='onchange') + + date = fields.Date(string="Date", states=DRAFT_EDITABLE_STATE, + copy=False) + type_id = fields.Many2one('stock.delivery.note.type', + string="Type", + default=_default_type, + states=DRAFT_EDITABLE_STATE, + readonly=True, + required=True, + index=True) + + sequence_id = fields.Many2one('ir.sequence', readonly=True, copy=False) + type_code = fields.Selection(string="Type of Operation", + related='type_id.code', store=True) + packages = fields.Integer(string="Packages", states=DONE_READONLY_STATE) + volume = fields.Float(string="Volume", states=DONE_READONLY_STATE) + + volume_uom_id = fields.Many2one('uom.uom', + string="Volume UoM", + default=_default_volume_uom, + domain=_domain_volume_uom, + states=DONE_READONLY_STATE) + gross_weight = fields.Float(string="Gross weight", + states=DONE_READONLY_STATE) + gross_weight_uom_id = fields.Many2one('uom.uom', + string="Gross weight UoM", + default=_default_weight_uom, + domain=_domain_weight_uom, + states=DONE_READONLY_STATE) + net_weight = fields.Float(string="Net weight", + states=DONE_READONLY_STATE) + net_weight_uom_id = fields.Many2one('uom.uom', + string="Net weight UoM", + default=_default_weight_uom, + domain=_domain_weight_uom, + states=DONE_READONLY_STATE) + + transport_condition_id = fields.Many2one( + 'stock.picking.transport.condition', + string="Condition of transport", + states=DONE_READONLY_STATE) + goods_appearance_id = fields.Many2one('stock.picking.goods.appearance', + string="Appearance of goods", + states=DONE_READONLY_STATE) + transport_reason_id = fields.Many2one('stock.picking.transport.reason', + string="Reason of transport", + states=DONE_READONLY_STATE) + transport_method_id = fields.Many2one('stock.picking.transport.method', + string="Method of transport", + states=DONE_READONLY_STATE) + + transport_datetime = fields.Datetime(string="Transport date", + states=DONE_READONLY_STATE) + + line_ids = fields.One2many('stock.delivery.note.line', 'delivery_note_id', + string="Lines") + invoice_status = fields.Selection(INVOICE_STATUSES, + string="Invoice status", + compute='_compute_invoice_status', + default=DOMAIN_INVOICE_STATUSES[0], + readonly=True, + store=True, + copy=False) + + picking_ids = fields.One2many('stock.picking', 'delivery_note_id', + string="Pickings") + pickings_picker = fields.Many2many('stock.picking', + compute='_compute_get_pickings', + inverse='_inverse_set_pickings') + + picking_type = fields.Selection(PICKING_TYPES, + string="Picking type", + compute='_compute_picking_type', + store=True) + + sale_ids = fields.Many2many('sale.order', compute='_compute_sales') + sale_count = fields.Integer(compute='_compute_sales') + sales_transport_check = fields.Boolean(compute='_compute_sales', + default=True) + + invoice_ids = fields.Many2many('account.invoice', + 'stock_delivery_note_account_invoice_rel', + 'delivery_note_id', + 'invoice_id', + string="Invoices", + copy=False) + + print_prices = fields.Boolean(string="Show prices on printed DN", + related="type_id.print_prices", + store=True) + note = fields.Html(string="Internal note", + states=DONE_READONLY_STATE) + + can_change_number = fields.Boolean(compute='_compute_boolean_flags') + show_product_information = fields.Boolean(compute='_compute_boolean_flags') + company_id = fields.Many2one('res.company', required=True, + default=_default_company) + + @api.multi + @api.depends('name', 'partner_id', + 'partner_ref', 'partner_id.display_name') + def _compute_display_name(self): + for note in self: + if not note.name: + partner_name = note.partner_id.display_name + create_date = note.create_date.strftime(DATETIME_FORMAT) + name = "{} - {}".format(partner_name, create_date) + + else: + name = note.name + + if note.partner_ref and note.type_code == 'incoming': + name = "{} ({})".format(name, note.partner_ref) + + note.display_name = name + + @api.multi + @api.depends('state', 'line_ids', 'line_ids.invoice_status') + def _compute_invoice_status(self): + for note in self: + lines = note.line_ids.filtered(lambda l: l.sale_line_id) + + if all(line.invoice_status == DOMAIN_INVOICE_STATUSES[2] + for line in lines): + note.state = DOMAIN_DELIVERY_NOTE_STATES[2] + note.invoice_status = DOMAIN_INVOICE_STATUSES[2] + + elif any(line.invoice_status == DOMAIN_INVOICE_STATUSES[1] + for line in lines): + note.invoice_status = DOMAIN_INVOICE_STATUSES[1] + + else: + note.invoice_status = DOMAIN_INVOICE_STATUSES[0] + + @api.multi + def _compute_get_pickings(self): + for note in self: + note.pickings_picker = note.picking_ids + + @api.multi + def _inverse_set_pickings(self): + for note in self: + if note.pickings_picker: + self.check_compliance(note.pickings_picker) + + note.picking_ids = note.pickings_picker + + @api.multi + @api.depends('picking_ids') + def _compute_picking_type(self): + for note in self.filtered(lambda n: n.picking_ids): + picking_types = set(note.picking_ids.mapped('picking_type_code')) + picking_types = list(picking_types) + + if len(picking_types) != 1: + raise ValueError( + "You have just called this method on an " + "heterogeneous set of pickings.\n" + "All pickings should have the same " + "'picking_type_code' field value.") + + note.picking_type = picking_types[0] + + @api.multi + def _compute_sales(self): + for note in self: + sales = note.mapped('picking_ids.sale_id') + + note.sale_ids = sales + note.sale_count = len(sales) + + tc = sales.mapped('default_transport_condition_id') + ga = sales.mapped('default_goods_appearance_id') + tr = sales.mapped('default_transport_reason_id') + tm = sales.mapped('default_transport_method_id') + note.sales_transport_check = all([ + len(x) < 2 for x in [tc, ga, tr, tm] + ]) + + @api.multi + def _compute_boolean_flags(self): + can_change_number = \ + self.user_has_groups('l10n_it_delivery_note.can_change_number') + show_product_information = \ + self.user_has_groups('l10n_it_delivery_note_base.' + 'show_product_related_fields') + + for note in self: + note.can_change_number = \ + (note.state == 'draft' and can_change_number) + note.show_product_information = show_product_information + + @api.onchange('type_id') + def _onchange_type(self): + if self.type_id: + if self.name and self.type_id.sequence_id != self.sequence_id: + raise UserError(_("You cannot set this delivery note type due" + " of a different numerator configuration.")) + + if self._update_generic_shipping_information(self.type_id): + return { + 'warning': { + 'title': _("Warning!"), + 'message': "Some of the shipping configuration have " + "been overwritten with" + " the default ones of the selected delivery" + " note type.\n" + "Please, make sure to check this " + "information before continuing." + } + } + + @api.onchange('partner_id') + def _onchange_partner(self): + self.partner_shipping_id = self.partner_id + + if self.partner_id: + pickings_picker_domain = [ + ('delivery_note_id', '=', False), + ('state', '=', DONE_PICKING_STATE), + ('picking_type_code', '=', self.picking_type), + ('partner_id', '=', self.partner_id.id) + ] + + else: + pickings_picker_domain = [('id', '=', False)] + + return {'domain': {'pickings_picker': pickings_picker_domain}} + + @api.onchange('partner_shipping_id') + def _onchange_partner_shipping(self): + if self.partner_shipping_id: + changed = \ + self._update_partner_shipping_information(self.partner_shipping_id) + + if changed: + return { + 'warning': { + 'title': _("Warning!"), + 'message': "Some of the shipping configuration have " + "been overwritten with" + " the default ones of the selected " + "shipping partner address.\n" + "Please, make sure to check this " + "information before continuing." + } + } + + else: + self.delivery_method_id = False + + def check_compliance(self, pickings): + super().check_compliance(pickings) + + self._check_delivery_notes(self.pickings_picker - self.picking_ids) + + @api.multi + def ensure_annulability(self): + if self.mapped('invoice_ids'): + raise UserError(_("You cannot cancel this delivery note. " + "There is at least one invoice" + " related to this delivery note.")) + + @api.multi + def action_draft(self): + self.write({'state': DOMAIN_DELIVERY_NOTE_STATES[0]}) + self.line_ids.sync_invoice_status() + + @api.multi + def action_confirm(self): + for note in self: + sequence = note.type_id.sequence_id + + note.state = DOMAIN_DELIVERY_NOTE_STATES[1] + if not note.date: + note.date = datetime.date.today() + + if not note.name: + note.name = sequence.next_by_id() + note.sequence_id = sequence + + def _fix_quantities_to_invoice(self, lines): + cache = {} + + pickings_lines = lines.retrieve_pickings_lines(self.picking_ids) + other_lines = lines - pickings_lines + + for line in other_lines: + cache[line] = line.fix_qty_to_invoice() + + pickings_move_ids = self.mapped('picking_ids.move_lines') + for line in pickings_lines.filtered(lambda l: len(l.move_ids) > 1): + move_ids = line.move_ids & pickings_move_ids + qty_to_invoice = sum(move_ids.mapped('quantity_done')) + + if qty_to_invoice < (line.product_uom_qty - line.qty_to_invoice): + cache[line] = line.fix_qty_to_invoice(qty_to_invoice) + + return cache + + def action_invoice(self): + self.ensure_one() + + orders_lines = self.mapped('sale_ids.order_line') \ + .filtered(lambda l: l.product_id) + + downpayment_lines = orders_lines.filtered(lambda l: l.is_downpayment) + invoiceable_lines = orders_lines.filtered(lambda l: l.is_invoiceable) + + cache = \ + self._fix_quantities_to_invoice(invoiceable_lines - downpayment_lines) + + for downpayment in downpayment_lines: + order = downpayment.order_id + order_lines = order.order_line \ + .filtered(lambda l: l.product_id and not l.is_downpayment) + + if order_lines.filtered(lambda l: l.need_to_be_invoiced): + cache[downpayment] = downpayment.fix_qty_to_invoice() + + self.sale_ids \ + .filtered(lambda o: o.invoice_status == DOMAIN_INVOICE_STATUSES[1]) \ + .action_invoice_create(final=True) + + for line, vals in cache.items(): + line.write(vals) + + orders_lines._get_to_invoice_qty() + + @api.multi + def action_done(self): + self.write({'state': DOMAIN_DELIVERY_NOTE_STATES[3]}) + + @api.multi + def action_cancel(self): + self.ensure_annulability() + + self.write({'state': DOMAIN_DELIVERY_NOTE_STATES[4]}) + + @api.multi + def action_print(self): + return self.env.ref('l10n_it_delivery_note.' + 'delivery_note_report_action').report_action(self) + + def update_transport_datetime(self): + self.transport_datetime = datetime.datetime.now() + + def goto(self, **kwargs): + self.ensure_one() + + return { + 'type': 'ir.actions.act_window', + 'res_model': self._name, + 'res_id': self.id, + 'views': [(False, 'form')], + 'view_type': 'form', + 'view_mode': 'form', + 'target': 'current', + **kwargs + } + + @api.multi + def goto_sales(self, **kwargs): + sales = self.mapped('sale_ids') + action = self.env.ref('sale.action_orders').read()[0] + action.update(kwargs) + + if len(sales) > 1: + action['domain'] = [('id', 'in', sales.ids)] + + elif len(sales) == 1: + action['views'] = [ + (self.env.ref('sale.view_order_form').id, 'form')] + action['res_id'] = sales.id + + else: + action = {'type': 'ir.actions.act_window_close'} + + return action + + def _create_detail_lines(self, move_ids): + if not move_ids: + return + + moves = self.env['stock.move'].browse(move_ids) + lines_vals = \ + self.env['stock.delivery.note.line']._prepare_detail_lines(moves) + + self.write({'line_ids': [(0, False, vals) for vals in lines_vals]}) + + def _delete_detail_lines(self, move_ids): + if not move_ids: + return + + lines = self.env['stock.delivery.note.line'] \ + .search([('move_id', 'in', move_ids)]) + + self.write({'line_ids': [(2, line.id, False) for line in lines]}) + + @api.multi + def update_detail_lines(self): + for note in self: + lines_move_ids = note.mapped('line_ids.move_id').ids + pickings_move_ids = note.mapped('picking_ids.valid_move_ids').ids + + move_ids_to_create = [l for l in pickings_move_ids if + l not in lines_move_ids] + move_ids_to_delete = [l for l in lines_move_ids if + l not in pickings_move_ids] + + note._create_detail_lines(move_ids_to_create) + note._delete_detail_lines(move_ids_to_delete) + + @api.model + @api.returns('self') + def create(self, vals): + res = super().create(vals) + + if 'picking_ids' in vals: + res.update_detail_lines() + + return res + + @api.multi + def write(self, vals): + res = super().write(vals) + + if 'picking_ids' in vals: + self.update_detail_lines() + + return res + + @api.multi + def unlink(self): + self.ensure_annulability() + + return super().unlink() + + @api.model + def get_location_address(self, location_id): + location_address = "" + warehouse = self.env['stock.warehouse'] \ + .search([('lot_stock_id', '=', location_id)]) + + if warehouse and warehouse.partner_id: + partner = warehouse.partner_id + + location_address += "{}, ".format(partner.name) + if partner.street: + location_address += "{} - ".format(partner.street) + + location_address += "{} {}".format(partner.zip, partner.city) + if partner.state_id: + location_address += " ({})".format(partner.state_id.name) + + return location_address + + +class StockDeliveryNoteLine(models.Model): + _name = 'stock.delivery.note.line' + _description = "Delivery Note Line" + _order = 'sequence, id' + + def _default_currency(self): + return self.env.user.company_id.currency_id + + def _default_unit_uom(self): + return self.env.ref('uom.product_uom_unit', raise_if_not_found=False) + + delivery_note_id = fields.Many2one('stock.delivery.note', + string="Delivery Note", + required=True, + ondelete='cascade') + + sequence = fields.Integer(string="Sequence", required=True, default=10, + index=True) + name = fields.Text(string="Description", required=True) + display_type = fields.Selection(LINE_DISPLAY_TYPES, string="Line type", + default=False) + product_id = fields.Many2one('product.product', string="Product") + product_description = fields.Text(related='product_id.description_sale') + product_qty = fields.Float( + string="Quantity", + digits=dp.get_precision('Product Unit of Measure'), + default=1.0) + product_uom_id = fields.Many2one('uom.uom', string="UoM", + default=_default_unit_uom) + price_unit = fields.Monetary(string="Unit price", + currency_field='currency_id', + digits=dp.get_precision('Product Price')) + currency_id = fields.Many2one('res.currency', string="Currency", + required=True, default=_default_currency) + discount = fields.Float(string="Discount", + digits=dp.get_precision('Discount')) + tax_ids = fields.Many2many('account.tax', string="Taxes") + + move_id = fields.Many2one('stock.move', string="Warehouse movement", + readonly=True, copy=False) + sale_line_id = fields.Many2one('sale.order.line', + related='move_id.sale_line_id', store=True, + copy=False) + invoice_status = fields.Selection(INVOICE_STATUSES, + string="Invoice status", + required=True, + default=DOMAIN_INVOICE_STATUSES[0], + copy=False) + + _sql_constraints = [( + 'move_uniq', + 'unique(move_id)', + "You cannot assign the same warehouse movement to " + "different delivery notes!" + )] + + @property + def is_invoiceable(self): + return self.invoice_status == DOMAIN_INVOICE_STATUSES[1] + + @api.onchange('product_id') + def _onchange_product_id(self): + if self.product_id: + domain = [ + ('category_id', '=', self.product_id.uom_id.category_id.id)] + self.name = \ + self.product_id.get_product_multiline_description_sale() + + else: + domain = [] + + return {'domain': {'product_uom_id': domain}} + + @api.model + def _prepare_detail_lines(self, moves): + lines = [] + for move in moves: + line = { + 'move_id': move.id, + 'name': move.name, + 'product_id': move.product_id.id, + 'product_qty': move.product_uom_qty, + 'product_uom_id': move.product_uom.id + } + + if move.sale_line_id: + order_line = move.sale_line_id + order = order_line.order_id + + line['price_unit'] = order_line.price_unit + line['currency_id'] = order.currency_id.id + line['discount'] = order_line.discount + line['tax_ids'] = [(6, False, order_line.tax_id.ids)] + line['invoice_status'] = DOMAIN_INVOICE_STATUSES[1] + + lines.append(line) + + return lines + + @api.model + @api.returns('self') + def create(self, vals): + if vals.get('display_type'): + vals.update({ + 'product_id': False, + 'product_qty': 0.0, + 'product_uom_id': False, + 'price_unit': 0.0, + 'discount': 0.0, + 'tax_ids': [(5, False, False)] + }) + + return super().create(vals) + + @api.multi + def write(self, vals): + if 'display_type' in vals and \ + self.filtered(lambda l: l.display_type != vals['display_type']): + raise UserError(_( + "You cannot change the type of a delivery note line. " + "Instead you should delete the current line" + " and create a new line of the proper type." + )) + + return super().write(vals) + + @api.multi + def sync_invoice_status(self): + for line in self.filtered(lambda l: l.sale_line_id): + invoice_status = line.sale_line_id.invoice_status + line.invoice_status = DOMAIN_INVOICE_STATUSES[ + 1] if invoice_status == 'upselling' else invoice_status diff --git a/l10n_it_delivery_note/models/stock_picking.py b/l10n_it_delivery_note/models/stock_picking.py new file mode 100644 index 000000000000..f7b47a48bd66 --- /dev/null +++ b/l10n_it_delivery_note/models/stock_picking.py @@ -0,0 +1,343 @@ +# Copyright 2014-2019 Dinamiche Aziendali srl +# (http://www.dinamicheaziendali.it/) +# @author: Marco Calcagni +# @author: Gianmarco Conte +# Copyright (c) 2019, Link IT Europe Srl +# @author: Matteo Bilotta +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import _, api, fields, models +from odoo.exceptions import UserError + +from .stock_delivery_note import DOMAIN_DELIVERY_NOTE_STATES +from ..mixins.picking_checker import DOMAIN_PICKING_TYPES, DONE_PICKING_STATE + +CANCEL_MOVE_STATE = 'cancel' + + +class StockPicking(models.Model): + _name = 'stock.picking' + _inherit = ['stock.picking', 'shipping.information.updater.mixin'] + + delivery_note_id = fields.Many2one('stock.delivery.note', + string="Delivery Note", copy=False) + delivery_note_sequence_id = \ + fields.Many2one('ir.sequence', related='delivery_note_id.sequence_id') + delivery_note_state = fields.Selection(string="DN State", + related='delivery_note_id.state') + delivery_note_partner_ref = fields.Char(related='delivery_note_id.partner_ref') + delivery_note_partner_shipping_id = \ + fields.Many2one('res.partner', + related='delivery_note_id.partner_shipping_id') + + delivery_note_carrier_id = fields.Many2one('res.partner', + string="DN Carrier", + related='delivery_note_id.carrier_id') + delivery_method_id = \ + fields.Many2one('delivery.carrier', + related='delivery_note_id.delivery_method_id') + + delivery_note_type_id = fields.Many2one('stock.delivery.note.type', + related='delivery_note_id.type_id') + delivery_note_type_code = fields.Selection(related='delivery_note_type_id.code') + delivery_note_date = fields.Date(string="DN Date", related='delivery_note_id.date') + delivery_note_note = fields.Html(related='delivery_note_id.note') + + transport_condition_id = \ + fields.Many2one('stock.picking.transport.condition', + related='delivery_note_id.transport_condition_id') + goods_appearance_id = \ + fields.Many2one('stock.picking.goods.appearance', + related='delivery_note_id.goods_appearance_id') + transport_reason_id = \ + fields.Many2one('stock.picking.transport.reason', + related='delivery_note_id.transport_reason_id') + transport_method_id = \ + fields.Many2one('stock.picking.transport.method', + related='delivery_note_id.transport_method_id') + + transport_datetime = fields.Datetime(related='delivery_note_id.transport_datetime') + + packages = fields.Integer(string="DN Packages", related='delivery_note_id.packages') + delivery_note_volume = fields.Float(string="DN Volume", + related='delivery_note_id.volume') + delivery_note_volume_uom_id = \ + fields.Many2one('uom.uom', related='delivery_note_id.volume_uom_id') + gross_weight = fields.Float(related='delivery_note_id.gross_weight') + gross_weight_uom_id = \ + fields.Many2one('uom.uom', + related='delivery_note_id.gross_weight_uom_id') + net_weight = fields.Float(related='delivery_note_id.net_weight') + net_weight_uom_id = \ + fields.Many2one('uom.uom', + related='delivery_note_id.net_weight_uom_id') + + valid_move_ids = fields.One2many('stock.move', + 'picking_id', + domain=[('state', '!=', CANCEL_MOVE_STATE)]) + picking_type_code = fields.Selection(string="DN Operation Type", + related='picking_type_id.code') + + use_delivery_note = fields.Boolean(compute='_compute_boolean_flags') + use_advanced_behaviour = fields.Boolean(compute='_compute_boolean_flags') + delivery_note_exists = fields.Boolean(compute='_compute_boolean_flags') + delivery_note_draft = fields.Boolean(compute='_compute_boolean_flags') + delivery_note_readonly = fields.Boolean(compute='_compute_boolean_flags') + delivery_note_visible = fields.Boolean(compute='_compute_boolean_flags') + can_be_invoiced = fields.Boolean(compute='_compute_boolean_flags') + + @property + def _delivery_note_fields(self): + from collections import OrderedDict + + fields = OrderedDict({ + key: field + for key, field in self._fields.items() + if field.related and field.related[0] == 'delivery_note_id' + }) + + setattr(type(self), '_delivery_note_fields', fields) + + return fields + + @api.multi + def _compute_boolean_flags(self): + from_delivery_note = self.env.context.get('from_delivery_note') + use_advanced_behaviour = self.user_has_groups('l10n_it_delivery_note.' + 'use_advanced_delivery_notes') + + for picking in self: + picking.use_delivery_note = \ + not from_delivery_note and picking.state == DONE_PICKING_STATE + + picking.delivery_note_visible = use_advanced_behaviour + picking.use_advanced_behaviour = use_advanced_behaviour + + picking.delivery_note_draft = False + picking.delivery_note_readonly = True + + if picking.use_delivery_note and picking.delivery_note_id: + picking.delivery_note_exists = True + picking.delivery_note_draft = \ + (picking.delivery_note_id.state == + DOMAIN_DELIVERY_NOTE_STATES[0]) + picking.delivery_note_readonly = \ + (picking.delivery_note_id.state == + DOMAIN_DELIVERY_NOTE_STATES[3]) + picking.can_be_invoiced = \ + bool(picking.delivery_note_id.sale_ids) + + @api.onchange('delivery_note_type_id') + def _onchange_delivery_note_type(self): + if self.delivery_note_type_id: + if self.delivery_note_id.name \ + and self.delivery_note_type_id.sequence_id != \ + self.delivery_note_sequence_id: + raise UserError(_("You cannot set this delivery note type due" + " of a different numerator configuration.")) + + if self._update_generic_shipping_information(self.delivery_note_type_id): + return { + 'warning': { + 'title': _("Warning!"), + 'message': "Some of the shipping configuration have " + "been overwritten with" + " the default ones of the selected " + "delivery note type.\n" + "Please, make sure to check this " + "information before continuing." + } + } + + @api.onchange('delivery_note_partner_shipping_id') + def _onchange_delivery_note_partner_shipping(self): + if self.delivery_note_partner_shipping_id: + changed = self._update_partner_shipping_information( + self.delivery_note_partner_shipping_id) + + if changed: + return { + 'warning': { + 'title': _("Warning!"), + 'message': "Some of the shipping configuration have " + "been overwritten with" + " the default ones of the selected shipping" + " partner address.\n" + "Please, make sure to check this " + "information before continuing." + } + } + + else: + self.delivery_method_id = False + + def _add_delivery_cost_to_so(self): + self.ensure_one() + + super(StockPicking, self.with_context(default_delivery_picking_id=self.id)) \ + ._add_delivery_cost_to_so() + + def action_delivery_note_create(self): + self.ensure_one() + + return { + 'name': _("Create a new delivery note"), + 'type': 'ir.actions.act_window', + 'res_model': 'stock.delivery.note.create.wizard', + 'view_type': 'form', + 'view_mode': 'form', + 'target': 'new', + 'context': {'active_ids': self.ids} + } + + def action_delivery_note_select(self): + self.ensure_one() + + return { + 'name': _("Select an existing delivery note"), + 'type': 'ir.actions.act_window', + 'res_model': 'stock.delivery.note.select.wizard', + 'view_type': 'form', + 'view_mode': 'form', + 'target': 'new', + 'context': {'active_ids': self.ids} + } + + def action_delivery_note_draft(self): + self.ensure_one() + + return self.delivery_note_id.action_draft() + + def action_delivery_note_confirm(self): + self.ensure_one() + + return self.delivery_note_id.action_confirm() + + def action_delivery_note_invoice(self): + self.ensure_one() + + return self.delivery_note_id.action_invoice() + + def action_delivery_note_done(self): + self.ensure_one() + + return self.delivery_note_id.action_done() + + def action_delivery_note_cancel(self): + self.ensure_one() + + return self.delivery_note_id.action_cancel() + + def action_delivery_note_print(self): + self.ensure_one() + + return self.delivery_note_id.action_print() + + @api.multi + def action_done(self): + res = super().action_done() + codes = self.mapped('picking_type_code') + + if all(code != DOMAIN_PICKING_TYPES[0] for code in codes) and \ + not self.user_has_groups('l10n_it_delivery_note.' + 'use_advanced_delivery_notes'): + + partners = self.get_partners() + delivery_note = self.env['stock.delivery.note'].create({ + 'partner_sender_id': partners[0].id, + 'partner_id': partners[1].id, + 'partner_shipping_id': partners[1].id + }) + + self.write({'delivery_note_id': delivery_note.id}) + + return res + + def delivery_note_update_transport_datetime(self): + self.delivery_note_id.update_transport_datetime() + + @api.multi + @api.returns('res.partner') + def get_partners(self): + partner_id = self.mapped('partner_id') + + if len(partner_id) != 1 and self.location_dest_id.usage == 'customer': + raise ValueError( + "You have just called this method on an heterogeneous set " + "of pickings.\n" + "All pickings should have the same 'partner_id' field value.") + + src_location_id = self.mapped('location_id') + + if len(src_location_id) != 1: + raise ValueError( + "You have just called this method on an heterogeneous set " + "of pickings.\n" + "All pickings should have the same 'location_id' field value.") + + dest_location_id = self.mapped('location_dest_id') + + if len(dest_location_id) != 1: + raise ValueError( + "You have just called this method on an heterogeneous " + "set of pickings.\n" + "All pickings should have the same 'location_dest_id' " + "field value.") + + src_warehouse_id = src_location_id.get_warehouse() + dest_warehouse_id = dest_location_id.get_warehouse() + + src_partner_id = src_warehouse_id.partner_id + dest_partner_id = dest_warehouse_id.partner_id + + if not src_partner_id: + src_partner_id = partner_id + + if not dest_partner_id: + raise ValueError( + "Fields 'src_partner_id' and 'dest_partner_id' " + "cannot be both unset.") + + elif not dest_partner_id: + dest_partner_id = partner_id + + return (src_partner_id, dest_partner_id) + + def goto(self, **kwargs): + self.ensure_one() + + return { + 'type': 'ir.actions.act_window', + 'res_model': self._name, + 'res_id': self.id, + 'views': [(False, 'form')], + 'view_type': 'form', + 'view_mode': 'form', + 'target': 'current', + **kwargs + } + + def goto_delivery_note(self, **kwargs): + return self.delivery_note_id.goto(**kwargs) + + def update_delivery_note_fields(self, vals): + note_fields = self._delivery_note_fields + + if any(key in note_fields for key in vals.keys()): + delivery_note_vals = {note_fields[key].related[1]: value for + key, value in vals.items() if + key in note_fields} + + self.mapped('delivery_note_id').write(delivery_note_vals) + + @api.multi + def write(self, vals): + res = super().write(vals) + + if self.mapped('delivery_note_id'): + self.update_delivery_note_fields(vals) + + if 'delivery_note_id' in vals: + self.mapped('delivery_note_id').update_detail_lines() + + return res diff --git a/l10n_it_delivery_note/readme/CONFIGURE.rst b/l10n_it_delivery_note/readme/CONFIGURE.rst new file mode 100644 index 000000000000..b5a314532cde --- /dev/null +++ b/l10n_it_delivery_note/readme/CONFIGURE.rst @@ -0,0 +1,18 @@ +To configure this module, go to: + +1. *Inventory → Configuration → Settings - Delivery Notes* + + Checking 'Use Advanced DN Features' allows you to manage more picking on one delivery note. + +2. *Inventory → Configuration → Warehouse Management → Delivery Note Types* + + In delivery note type you can specify if the product price have to be printed in the delivery note report/slip. + + - *Inventory → Configuration → Delivery Notes → Conditions of Transport* + - *Inventory → Configuration → Delivery Notes → Appearances of Goods* + - *Inventory → Configuration → Delivery Notes → Reasons of Transport* + - *Inventory → Configuration → Delivery Notes → Methods of Transport* + +3. *Settings → User & Companies → Users* + + In the user profile settings, "Show product information in DN lines" allows showing prices in the form. diff --git a/l10n_it_delivery_note/readme/CONTRIBUTORS.rst b/l10n_it_delivery_note/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000000..efb25ead1c1c --- /dev/null +++ b/l10n_it_delivery_note/readme/CONTRIBUTORS.rst @@ -0,0 +1,8 @@ +* Riccardo Bellanova +* Matteo Bilotta +* Giuseppe Borruso +* Marco Calcagni +* Marco Colombo +* Gianmarco Conte +* Letizia Freda +* Andrea Piovesana diff --git a/l10n_it_delivery_note/readme/DESCRIPTION.rst b/l10n_it_delivery_note/readme/DESCRIPTION.rst new file mode 100644 index 000000000000..9e731d4787a6 --- /dev/null +++ b/l10n_it_delivery_note/readme/DESCRIPTION.rst @@ -0,0 +1,31 @@ +**English** + +This module manage the Italian DDT (Delivery note). + +From a picking is possible to generate a Delivery Note and group more picking in one delivery note. It's also possible to invoice from the delivery note form. + +This module is alternative to :code:`l10n_it_ddt`, it follows the Odoo way to process sale orders, pickings and invoices. + +You can't have both :code:`l10n_it_ddt` and :code:`l10n_it_delivery_note` installed together. + +There are two available settings: + +- Base (default): one picking, one DN. +- Advanced: more picking in one DN. + + +**Italiano** + +Questo modulo consente di gestire i DDT. + +Da un prelievo è possibile generare un DDT e raggruppare più prelievi in un DDT. È anche possibile fatturare dalla scheda del DDT. + +Questo modulo è un alternativa al modulo :code:`l10n_it_ddt`, segue la modalità Odoo di gestire ordini di vendita, prelievi e fatture. + +Non è possibile avere installati contemporaneamente :code:`l10n_it_ddt` e :code:`l10n_it_delivery_note`. + +Ci sono due impostazioni possibili. + +- Base (predefinita): un prelievo, un DDT. +- Avanzata: più prelievi in un DDT. + diff --git a/l10n_it_delivery_note/readme/USAGE.rst b/l10n_it_delivery_note/readme/USAGE.rst new file mode 100644 index 000000000000..2e8b35aab01f --- /dev/null +++ b/l10n_it_delivery_note/readme/USAGE.rst @@ -0,0 +1,63 @@ +Funzionalità base +~~~~~~~~~~~~~~~~~ + +Quando un prelievo viene validato compare una scheda DDT. + +Nella scheda fare clic su "Crea nuovo", si apre un procedura guidata dove scegliere il tipo di DDT, quindi confermare. Immettere i dati richiesti e poi fare clic su "Valida" per numerare il DDT. + +Una volta validato, è possibile emettere fattura direttamente dal DDT se il DDT stesso è di tipo consegna a cliente (In uscita) e si hanno i permessi sull'utente. + +È possibile annullare il DDT, reimpostarlo a bozza e poi modificarlo. Se il DDT è fatturato il numero e la data non sono modificabili. + +Per i trasferimenti tra magazzini creare un prelievo di tipo interno con le relative ubicazioni. Validare il prelievo visualizza la scheda DDT. + +È possibile anche avere DDT in ingresso, ovvero dopo la validazione del prelievo selezionare la scheda per indicare il numero del DDT fornitore e la data. + +Funzionalità avanzata +~~~~~~~~~~~~~~~~~~~~~ + +Vengono attivate varie funzionalità aggiuntive: + +- più prelievi per un DDT +- selezione multipla di prelievi e generazione dei DDT +- aggiunta righe nota e righe sezione descrittive. +- lista dei DDT. + +Il report DDT stampa in righe aggiuntive i lotti/seriali e le scadenze del prodotto. + +Il prezzo può essere indicato anche nel report DDT se nel tipo DDT è indicata la stampa prezzi. +La visibilità dei prezzi si trova nei permessi dell'utente. + +Le fatture generate dai DDT contengono i riferimenti al DDT stesso nelle righe nota. + + +Migrazione dei dati da *l10n_it_ddt* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Il modulo presenta una funzione di migrazione dei dati dal modulo OCA *l10n_it_ddt* da eseguire manualmente. +Al momento, non è ancora presente un menù oppure una voce da interfaccia che permetta di eseguire questa operazione; bensì, è stato definito un comando da CLI da eseguire all’avvio di Odoo. +Di seguito, una piccola lista di passi da seguire per portare a termine la migrazione: + +1. Eseguire un back-up del database. + + Questa procedura di migrazione dei dati è stata sì sviluppata e testata, MA solamente per un numero limitato di casi. + NON è consigliata in alcun modo come funzionalità production-ready. + +2. Installare il modulo *l10n_it_delivery_note* SENZA prima disinstallare il modulo OCA *l10n_it_ddt*. + + N.B.: NON iniziare ad usare il modulo *l10n_it_delivery_note* senza aver prima migrato i dati. + Potrebbero verificarsi, in prima battuta, problemi legati alla numerazione dei documenti creati. + Inoltre, la procedura di migrazione stessa è progettata affinché verifichi che non siano presenti documenti di *l10n_it_delivery_note*; qualora ne rilevi alcuni, si interromperà non eseguendo alcuna migrazione. + +3. Terminata l’installazione del modulo, terminare in sicurezza il processo di Odoo. + +4. Lanciare Odoo, nella maniera in cui si è soliti fare, aggiungendo alcuni parametri al comando d’avvio: + + `./odoo-bin migrate_ddt_data --database [...]` + +5. Una volta terminata l’esecuzione della procedura, verificare che tutti i documenti siano stati migrati con successo e nel modo atteso. + +6. Verificata l’esattezza dei dati migrati, disinstallare il modulo *l10n_it_ddt*. + +È possibile iniziare ad utilizzare *l10n_it_delivery_note*. + diff --git a/l10n_it_delivery_note/report/report_delivery_note.xml b/l10n_it_delivery_note/report/report_delivery_note.xml new file mode 100644 index 000000000000..748c5cb7d079 --- /dev/null +++ b/l10n_it_delivery_note/report/report_delivery_note.xml @@ -0,0 +1,334 @@ + + + + + + + + + + + + + diff --git a/l10n_it_delivery_note/security/ir.model.access.csv b/l10n_it_delivery_note/security/ir.model.access.csv new file mode 100644 index 000000000000..3a078b54ebfa --- /dev/null +++ b/l10n_it_delivery_note/security/ir.model.access.csv @@ -0,0 +1,15 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_stock_picking_goods_appearance_manager,stock.picking.goods.appearance manager,l10n_it_delivery_note_base.model_stock_picking_goods_appearance,stock.group_stock_manager,1,1,1,1 +access_stock_picking_goods_appearance_user,stock.picking.goods.appearance user,l10n_it_delivery_note_base.model_stock_picking_goods_appearance,base.group_user,1,0,0,0 +access_stock_picking_transport_condition_manager,stock.picking.transport.condition manager,l10n_it_delivery_note_base.model_stock_picking_transport_condition,stock.group_stock_manager,1,1,1,1 +access_stock_picking_transport_condition_user,stock.picking.transport.condition user,l10n_it_delivery_note_base.model_stock_picking_transport_condition,base.group_user,1,0,0,0 +access_stock_picking_transport_reason_manager,stock.picking.transport.reason manager,l10n_it_delivery_note_base.model_stock_picking_transport_reason,stock.group_stock_manager,1,1,1,1 +access_stock_picking_transport_reason_user,stock.picking.transport.reason user,l10n_it_delivery_note_base.model_stock_picking_transport_reason,base.group_user,1,0,0,0 +access_stock_picking_transport_method_manager,stock.picking.transport.method manager,l10n_it_delivery_note_base.model_stock_picking_transport_method,stock.group_stock_manager,1,1,1,1 +access_stock_picking_transport_method_user,stock.picking.transport.method user,l10n_it_delivery_note_base.model_stock_picking_transport_method,base.group_user,1,0,0, +access_stock_delivery_note_user,access_stock_delivery_note user,model_stock_delivery_note,stock.group_stock_user,1,1,1,1 +access_stock_delivery_note_manager,access_stock_delivery_note manager,model_stock_delivery_note,stock.group_stock_manager,1,1,1,1 +access_stock_delivery_note_line_user,access_stock_delivery_note_line user,model_stock_delivery_note_line,stock.group_stock_user,1,0,0,0 +access_stock_delivery_note_line_manager,access_stock_delivery_note_line manager,model_stock_delivery_note_line,stock.group_stock_manager,1,1,1,1 +access_stock_delivery_note_type_user,access_stock_delivery_note_type user,l10n_it_delivery_note_base.model_stock_delivery_note_type,stock.group_stock_user,1,0,0,0 +access_stock_delivery_note_type_manager,access_stock_delivery_note_type manager,l10n_it_delivery_note_base.model_stock_delivery_note_type,stock.group_stock_manager,1,1,1,1 diff --git a/l10n_it_delivery_note/security/ir_rule.xml b/l10n_it_delivery_note/security/ir_rule.xml new file mode 100644 index 000000000000..837a68443e5e --- /dev/null +++ b/l10n_it_delivery_note/security/ir_rule.xml @@ -0,0 +1,18 @@ + + + + + + + + Delivery note type multi-company + + + ['|', ('company_id' , '=', False), ('company_id', 'child_of', [user.company_id.id])] + + + + diff --git a/l10n_it_delivery_note/security/res_groups.xml b/l10n_it_delivery_note/security/res_groups.xml new file mode 100644 index 000000000000..1546b46845e5 --- /dev/null +++ b/l10n_it_delivery_note/security/res_groups.xml @@ -0,0 +1,20 @@ + + + + + + + + Use Advanced DN Features + + + + + Allow to change delivery note number + + + + diff --git a/l10n_it_delivery_note/security/res_users.xml b/l10n_it_delivery_note/security/res_users.xml new file mode 100644 index 000000000000..7ebdb41ec48f --- /dev/null +++ b/l10n_it_delivery_note/security/res_users.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + diff --git a/l10n_it_delivery_note/static/description/icon.jpg b/l10n_it_delivery_note/static/description/icon.jpg new file mode 100644 index 0000000000000000000000000000000000000000..76e120ceb5b82aedc87547a15b5edeed9f4611fa GIT binary patch literal 3386 zcmb7_cT`i^7RGO=f+&O%Bs2+CK#(XfG_lYjASDEy5M~e*0vZWTno%rtG*szI3xp<0 zuSyXD0tN_3Rg@wq0@9@B#ZjDB{&{omT6gWc_P)RGyXV}q5B&}O9l&E^U~B+@KmY(@ zTmXFpI18|`u(GkTu(7eSv9q)7=l=Ky#g&;+zIgJ1v? z7{m+)(OUqK?>1S#+x<1znHhHXftVOs6CMD>%*4dPzMqqYh5fGz5YzWGm|ajpg_rNN zCGyW$el=?kuUo`8YVUgiNw^I@=5gt>7yDpO`ygjLGgWOJgR>?U87wG6gcT+ ziH(s{0)qf15EBavD+}{aE8lg%ynGT?{3^#Ev!1rRwFp1+Clw|sSc6*oXVYffn1!0qM5tZ@e|qj%S;PLn9jRq)y|I9DSy9jY5t!=!(!X z6ln;Xthioyp?p^NmE<4BntA5Q4#;mW$$Ytqv>V48xYcoWTJKav8y2H(NzFahbPYm% zfc~gyyWKUiz<#seXRAq#C6;_=HfPl#68ob>?E8CS%$6ey``+-H|A49dEV-^d*06Z} zfFZ8#fAmz|E&FV}_%AtCwCg=Wvo}B0*THM43w6155l+F+Sa+=qc?^bAsUKuw)#R5j zwT8RR0B{(!H%t5dH{)_io`bVjv7Y(Y+!C?HAMY*JRhf4Z z)o?QBOf^Mx_4*b^h5a<*gdq<;H%dB8yCXW1vt}|o@vsG45`inqtF8W0LUIq~c1&z^ zpQ+z-K)VhA*q~d;*&Y8_*@D0E z+d=~!m|EV=3L{ork-28AXo~IJQKJJcS;3=fm58Alx5eQx8G^J-@bL{{#q&ZkQD4v2ul!I#kTp3o|^udhdZ(JJ5M#uo(7hLWGI?-=ib*yN?65h z#8N9?-H|i>E-3?7PFZH+9JD6^_r@Irasl>E`oDyyCLOP(B z=A-3Q2`_uNS^nfYDTmDkV79NN`RZ*$O1hpodY5Q8fv!rr4EdKf3!efJoB2IZ@Ao65 z&&a>9MDoL7N+v~~R6$&rc?(WU3tacPYXTu*|D>zj<;v%5ul=yj<2mvvvI%{hc$zV>(#i+dM#S8as^j0JW3K=^@q}Ol6_k`90qa|pM z-`ros_>n_$O!fCaSy^YvjVg}}IO&}qQ>zYB^25FD(32X;QCgPY?I#S}k-F%XDXDCc zHM1*i7ddwFCXn5O1(@D{yL3!9XpLL>_A2zxSH%b8A2_CnJku#{6?IqkOs$r*6bmPl zeHzJP`J0ai?&kDYQ**NnfRC+q?DO)ho=k>5`YQ*>dr`8mHo3mAs*N z&1kBkPv;^jN?nWSFi=3D#ds$BJ$a}C%dJqSPh4@< zbCqT7F&nNc!j#$HdE@D^Qkkmgx+>Dn*tJ6E&V8vN6rNpw?Q5?)AhGokQS)-{-QzJY zI$#&F@aSjm>eXUS(LsyV&>NcvKana;FM|%m!_9p|-_VcI95h;g*V`gH|5a#sW5^K;3zx!i=Zu^(E1c{0a**S; zuXEE}sqL%T0(jSvN9KIn+fmEAQUTVv8`o)H+!S~f*F0j$WKxnElnq*nE{&Rh{d_9M zRlqsj4~aY!UW=ZZLQ}9IXV!k3C6>pRFIyxo>qNWpoy?}-m&vIS)13opha;1gz1w=l zCdO2T6(*ff7hJFOYF!q}5E2W*hK8r#*N}N}!kec}kr!^1jn%mCI32A&npa2Cb!FD? zdm}elbzvsRnI*u{BP3^xl=k5PFY>TEzv|d`u z|B_Vl`!%P4w)E9TWw>c?qF+1#tNZB;uS}2}?Nrs7oTy~gfbkYLOG+{wfGhRDd0rSg z%O!FXYE5Fu_Vkg!CunJpFm>G>Z|(&Z}N`?K|rm=lbz#qWbEt zln@spEEOVST<WoO2FJWAaORQD#K=*^f*D*BAh{ zM}U&@&A&+iAbzf8Biq1$<{9@P-6EkJJ?UnN>?{Ry%~uRRaF%M1P9$mw(}AZ&4Y%To zy6|2F^`qmkmEiTa*$R`LjYa^A%c;L;(3?P2!@qIu&z)G}>%d(vq>L{o_a4$MW)9#z1*=X%(ZT}YO?gN9!sA^SR-h9m9dt`%grNsk4TXGNh oSCig*0GONINP6xnS(acpA{2DcLGE-)hrlTo`FFo6xamXx0udbq-v9sr literal 0 HcmV?d00001 diff --git a/l10n_it_delivery_note/static/description/icon.png b/l10n_it_delivery_note/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 zcmW++2RxMjAAjx~&dlBk9S+%}OXg)AGE&Cb*&}d0jUxM@u(PQx^-s)697TX`ehR4?GS^qbkof1cslKgkU)h65qZ9Oc=ml_0temigYLJfnz{IDzUf>bGs4N!v3=Z3jMq&A#7%rM5eQ#dc?k~! zVpnB`o+K7|Al`Q_U;eD$B zfJtP*jH`siUq~{KE)`jP2|#TUEFGRryE2`i0**z#*^6~AI|YzIWy$Cu#CSLW3q=GA z6`?GZymC;dCPk~rBS%eCb`5OLr;RUZ;D`}um=H)BfVIq%7VhiMr)_#G0N#zrNH|__ zc+blN2UAB0=617@>_u;MPHN;P;N#YoE=)R#i$k_`UAA>WWCcEVMh~L_ zj--gtp&|K1#58Yz*AHCTMziU1Jzt_jG0I@qAOHsk$2}yTmVkBp_eHuY$A9)>P6o~I z%aQ?!(GqeQ-Y+b0I(m9pwgi(IIZZzsbMv+9w{PFtd_<_(LA~0H(xz{=FhLB@(1&qHA5EJw1>>=%q2f&^X>IQ{!GJ4e9U z&KlB)z(84HmNgm2hg2C0>WM{E(DdPr+EeU_N@57;PC2&DmGFW_9kP&%?X4}+xWi)( z;)z%wI5>D4a*5XwD)P--sPkoY(a~WBw;E~AW`Yue4kFa^LM3X`8x|}ZUeMnqr}>kH zG%WWW>3ml$Yez?i%)2pbKPI7?5o?hydokgQyZsNEr{a|mLdt;X2TX(#B1j35xPnPW z*bMSSOauW>o;*=kO8ojw91VX!qoOQb)zHJ!odWB}d+*K?#sY_jqPdg{Sm2HdYzdEx zOGVPhVRTGPtv0o}RfVP;Nd(|CB)I;*t&QO8h zFfekr30S!-LHmV_Su-W+rEwYXJ^;6&3|L$mMC8*bQptyOo9;>Qb9Q9`ySe3%V$A*9 zeKEe+b0{#KWGp$F+tga)0RtI)nhMa-K@JS}2krK~n8vJ=Ngm?R!9G<~RyuU0d?nz# z-5EK$o(!F?hmX*2Yt6+coY`6jGbb7tF#6nHA zuKk=GGJ;ZwON1iAfG$E#Y7MnZVmrY|j0eVI(DN_MNFJmyZ|;w4tf@=CCDZ#5N_0K= z$;R~bbk?}TpfDjfB&aiQ$VA}s?P}xPERJG{kxk5~R`iRS(SK5d+Xs9swCozZISbnS zk!)I0>t=A<-^z(cmSFz3=jZ23u13X><0b)P)^1T_))Kr`e!-pb#q&J*Q`p+B6la%C zuVl&0duN<;uOsB3%T9Fp8t{ED108<+W(nOZd?gDnfNBC3>M8WE61$So|P zVvqH0SNtDTcsUdzaMDpT=Ty0pDHHNL@Z0w$Y`XO z2M-_r1S+GaH%pz#Uy0*w$Vdl=X=rQXEzO}d6J^R6zjM1u&c9vYLvLp?W7w(?np9x1 zE_0JSAJCPB%i7p*Wvg)pn5T`8k3-uR?*NT|J`eS#_#54p>!p(mLDvmc-3o0mX*mp_ zN*AeS<>#^-{S%W<*mz^!X$w_2dHWpcJ6^j64qFBft-o}o_Vx80o0>}Du;>kLts;$8 zC`7q$QI(dKYG`Wa8#wl@V4jVWBRGQ@1dr-hstpQL)Tl+aqVpGpbSfN>5i&QMXfiZ> zaA?T1VGe?rpQ@;+pkrVdd{klI&jVS@I5_iz!=UMpTsa~mBga?1r}aRBm1WS;TT*s0f0lY=JBl66Upy)-k4J}lh=P^8(SXk~0xW=T9v*B|gzIhN z>qsO7dFd~mgxAy4V?&)=5ieYq?zi?ZEoj)&2o)RLy=@hbCRcfT5jigwtQGE{L*8<@Yd{zg;CsL5mvzfDY}P-wos_6PfprFVaeqNE%h zKZhLtcQld;ZD+>=nqN~>GvROfueSzJD&BE*}XfU|H&(FssBqY=hPCt`d zH?@s2>I(|;fcW&YM6#V#!kUIP8$Nkdh0A(bEVj``-AAyYgwY~jB zT|I7Bf@%;7aL7Wf4dZ%VqF$eiaC38OV6oy3Z#TER2G+fOCd9Iaoy6aLYbPTN{XRPz z;U!V|vBf%H!}52L2gH_+j;`bTcQRXB+y9onc^wLm5wi3-Be}U>k_u>2Eg$=k!(l@I zcCg+flakT2Nej3i0yn+g+}%NYb?ta;R?(g5SnwsQ49U8Wng8d|{B+lyRcEDvR3+`O{zfmrmvFrL6acVP%yG98X zo&+VBg@px@i)%o?dG(`T;n*$S5*rnyiR#=wW}}GsAcfyQpE|>a{=$Hjg=-*_K;UtD z#z-)AXwSRY?OPefw^iI+ z)AXz#PfEjlwTes|_{sB?4(O@fg0AJ^g8gP}ex9Ucf*@_^J(s_5jJV}c)s$`Myn|Kd z$6>}#q^n{4vN@+Os$m7KV+`}c%4)4pv@06af4-x5#wj!KKb%caK{A&Y#Rfs z-po?Dcb1({W=6FKIUirH&(yg=*6aLCekcKwyfK^JN5{wcA3nhO(o}SK#!CINhI`-I z1)6&n7O&ZmyFMuNwvEic#IiOAwNkR=u5it{B9n2sAJV5pNhar=j5`*N!Na;c7g!l$ z3aYBqUkqqTJ=Re-;)s!EOeij=7SQZ3Hq}ZRds%IM*PtM$wV z@;rlc*NRK7i3y5BETSKuumEN`Xu_8GP1Ri=OKQ$@I^ko8>H6)4rjiG5{VBM>B|%`&&s^)jS|-_95&yc=GqjNo{zFkw%%HHhS~e=s zD#sfS+-?*t|J!+ozP6KvtOl!R)@@-z24}`9{QaVLD^9VCSR2b`b!KC#o;Ki<+wXB6 zx3&O0LOWcg4&rv4QG0)4yb}7BFSEg~=IR5#ZRj8kg}dS7_V&^%#Do==#`u zpy6{ox?jWuR(;pg+f@mT>#HGWHAJRRDDDv~@(IDw&R>9643kK#HN`!1vBJHnC+RM&yIh8{gG2q zA%e*U3|N0XSRa~oX-3EAneep)@{h2vvd3Xvy$7og(sayr@95+e6~Xvi1tUqnIxoIH zVWo*OwYElb#uyW{Imam6f2rGbjR!Y3`#gPqkv57dB6K^wRGxc9B(t|aYDGS=m$&S!NmCtrMMaUg(c zc2qC=2Z`EEFMW-me5B)24AqF*bV5Dr-M5ig(l-WPS%CgaPzs6p_gnCIvTJ=Y<6!gT zVt@AfYCzjjsMEGi=rDQHo0yc;HqoRNnNFeWZgcm?f;cp(6CNylj36DoL(?TS7eU#+ z7&mfr#y))+CJOXQKUMZ7QIdS9@#-}7y2K1{8)cCt0~-X0O!O?Qx#E4Og+;A2SjalQ zs7r?qn0H044=sDN$SRG$arw~n=+T_DNdSrarmu)V6@|?1-ZB#hRn`uilTGPJ@fqEy zGt(f0B+^JDP&f=r{#Y_wi#AVDf-y!RIXU^0jXsFpf>=Ji*TeqSY!H~AMbJdCGLhC) zn7Rx+sXw6uYj;WRYrLd^5IZq@6JI1C^YkgnedZEYy<&4(z%Q$5yv#Boo{AH8n$a zhb4Y3PWdr269&?V%uI$xMcUrMzl=;w<_nm*qr=c3Rl@i5wWB;e-`t7D&c-mcQl7x! zZWB`UGcw=Y2=}~wzrfLx=uet<;m3~=8I~ZRuzvMQUQdr+yTV|ATf1Uuomr__nDf=X zZ3WYJtHp_ri(}SQAPjv+Y+0=fH4krOP@S&=zZ-t1jW1o@}z;xk8 z(Nz1co&El^HK^NrhVHa-_;&88vTU>_J33=%{if;BEY*J#1n59=07jrGQ#IP>@u#3A z;!q+E1Rj3ZJ+!4bq9F8PXJ@yMgZL;>&gYA0%_Kbi8?S=XGM~dnQZQ!yBSgcZhY96H zrWnU;k)qy`rX&&xlDyA%(a1Hhi5CWkmg(`Gb%m(HKi-7Z!LKGRP_B8@`7&hdDy5n= z`OIxqxiVfX@OX1p(mQu>0Ai*v_cTMiw4qRt3~NBvr9oBy0)r>w3p~V0SCm=An6@3n)>@z!|o-$HvDK z|3D2ZMJkLE5loMKl6R^ez@Zz%S$&mbeoqH5`Bb){Ei21q&VP)hWS2tjShfFtGE+$z zzCR$P#uktu+#!w)cX!lWN1XU%K-r=s{|j?)Akf@q#3b#{6cZCuJ~gCxuMXRmI$nGtnH+-h z+GEi!*X=AP<|fG`1>MBdTb?28JYc=fGvAi2I<$B(rs$;eoJCyR6_bc~p!XR@O-+sD z=eH`-ye})I5ic1eL~TDmtfJ|8`0VJ*Yr=hNCd)G1p2MMz4C3^Mj?7;!w|Ly%JqmuW zlIEW^Ft%z?*|fpXda>Jr^1noFZEwFgVV%|*XhH@acv8rdGxeEX{M$(vG{Zw+x(ei@ zmfXb22}8-?Fi`vo-YVrTH*C?a8%M=Hv9MqVH7H^J$KsD?>!SFZ;ZsvnHr_gn=7acz z#W?0eCdVhVMWN12VV^$>WlQ?f;P^{(&pYTops|btm6aj>_Uz+hqpGwB)vWp0Cf5y< zft8-je~nn?W11plq}N)4A{l8I7$!ks_x$PXW-2XaRFswX_BnF{R#6YIwMhAgd5F9X zGmwdadS6(a^fjHtXg8=l?Rc0Sm%hk6E9!5cLVloEy4eh(=FwgP`)~I^5~pBEWo+F6 zSf2ncyMurJN91#cJTy_u8Y}@%!bq1RkGC~-bV@SXRd4F{R-*V`bS+6;W5vZ(&+I<9$;-V|eNfLa5n-6% z2(}&uGRF;p92eS*sE*oR$@pexaqr*meB)VhmIg@h{uzkk$9~qh#cHhw#>O%)b@+(| z^IQgqzuj~Sk(J;swEM-3TrJAPCq9k^^^`q{IItKBRXYe}e0Tdr=Huf7da3$l4PdpwWDop%^}n;dD#K4s#DYA8SHZ z&1!riV4W4R7R#C))JH1~axJ)RYnM$$lIR%6fIVA@zV{XVyx}C+a-Dt8Y9M)^KU0+H zR4IUb2CJ{Hg>CuaXtD50jB(_Tcx=Z$^WYu2u5kubqmwp%drJ6 z?Fo40g!Qd<-l=TQxqHEOuPX0;^z7iX?Ke^a%XT<13TA^5`4Xcw6D@Ur&VT&CUe0d} z1GjOVF1^L@>O)l@?bD~$wzgf(nxX1OGD8fEV?TdJcZc2KoUe|oP1#=$$7ee|xbY)A zDZq+cuTpc(fFdj^=!;{k03C69lMQ(|>uhRfRu%+!k&YOi-3|1QKB z z?n?eq1XP>p-IM$Z^C;2L3itnbJZAip*Zo0aw2bs8@(s^~*8T9go!%dHcAz2lM;`yp zD=7&xjFV$S&5uDaiScyD?B-i1ze`+CoRtz`Wn+Zl&#s4&}MO{@N!ufrzjG$B79)Y2d3tBk&)TxUTw@QS0TEL_?njX|@vq?Uz(nBFK5Pq7*xj#u*R&i|?7+6# z+|r_n#SW&LXhtheZdah{ZVoqwyT{D>MC3nkFF#N)xLi{p7J1jXlmVeb;cP5?e(=f# zuT7fvjSbjS781v?7{)-X3*?>tq?)Yd)~|1{BDS(pqC zC}~H#WXlkUW*H5CDOo<)#x7%RY)A;ShGhI5s*#cRDA8YgqG(HeKDx+#(ZQ?386dv! zlXCO)w91~Vw4AmOcATuV653fa9R$fyK8ul%rG z-wfS zihugoZyr38Im?Zuh6@RcF~t1anQu7>#lPpb#}4cOA!EM11`%f*07RqOVkmX{p~KJ9 z^zP;K#|)$`^Rb{rnHGH{~>1(fawV0*Z#)}M`m8-?ZJV<+e}s9wE# z)l&az?w^5{)`S(%MRzxdNqrs1n*-=jS^_jqE*5XDrA0+VE`5^*p3CuM<&dZEeCjoz zR;uu_H9ZPZV|fQq`Cyw4nscrVwi!fE6ciMmX$!_hN7uF;jjKG)d2@aC4ropY)8etW=xJvni)8eHi`H$%#zn^WJ5NLc-rqk|u&&4Z6fD_m&JfSI1Bvb?b<*n&sfl0^t z=HnmRl`XrFvMKB%9}>PaA`m-fK6a0(8=qPkWS5bb4=v?XcWi&hRY?O5HdulRi4?fN zlsJ*N-0Qw+Yic@s0(2uy%F@ib;GjXt01Fmx5XbRo6+n|pP(&nodMoap^z{~q ziEeaUT@Mxe3vJSfI6?uLND(CNr=#^W<1b}jzW58bIfyWTDle$mmS(|x-0|2UlX+9k zQ^EX7Nw}?EzVoBfT(-LT|=9N@^hcn-_p&sqG z&*oVs2JSU+N4ZD`FhCAWaS;>|wH2G*Id|?pa#@>tyxX`+4HyIArWDvVrX)2WAOQff z0qyHu&-S@i^MS-+j--!pr4fPBj~_8({~e1bfcl0wI1kaoN>mJL6KUPQm5N7lB(ui1 zE-o%kq)&djzWJ}ob<-GfDlkB;F31j-VHKvQUGQ3sp`CwyGJk_i!y^sD0fqC@$9|jO zOqN!r!8-p==F@ZVP=U$qSpY(gQ0)59P1&t@y?5rvg<}E+GB}26NYPp4f2YFQrQtot5mn3wu_qprZ=>Ig-$ zbW26Ws~IgY>}^5w`vTB(G`PTZaDiGBo5o(tp)qli|NeV( z@H_=R8V39rt5J5YB2Ky?4eJJ#b`_iBe2ot~6%7mLt5t8Vwi^Jy7|jWXqa3amOIoRb zOr}WVFP--DsS`1WpN%~)t3R!arKF^Q$e12KEqU36AWwnCBICpH4XCsfnyrHr>$I$4 z!DpKX$OKLWarN7nv@!uIA+~RNO)l$$w}p(;b>mx8pwYvu;dD_unryX_NhT8*Tj>BTrTTL&!?O+%Rv;b?B??gSzdp?6Uug9{ zd@V08Z$BdI?fpoCS$)t4mg4rT8Q_I}h`0d-vYZ^|dOB*Q^S|xqTV*vIg?@fVFSmMpaw0qtTRbx} z({Pg?#{2`sc9)M5N$*N|4;^t$+QP?#mov zGVC@I*lBVrOU-%2y!7%)fAKjpEFsgQc4{amtiHb95KQEwvf<(3T<9-Zm$xIew#P22 zc2Ix|App^>v6(3L_MCU0d3W##AB0M~3D00EWoKZqsJYT(#@w$Y_H7G22M~ApVFTRHMI_3be)Lkn#0F*V8Pq zc}`Cjy$bE;FJ6H7p=0y#R>`}-m4(0F>%@P|?7fx{=R^uFdISRnZ2W_xQhD{YuR3t< z{6yxu=4~JkeA;|(J6_nv#>Nvs&FuLA&PW^he@t(UwFFE8)|a!R{`E`K`i^ZnyE4$k z;(749Ix|oi$c3QbEJ3b~D_kQsPz~fIUKym($a_7dJ?o+40*OLl^{=&oq$<#Q(yyrp z{J-FAniyAw9tPbe&IhQ|a`DqFTVQGQ&Gq3!C2==4x{6EJwiPZ8zub-iXoUtkJiG{} zPaR&}_fn8_z~(=;5lD-aPWD3z8PZS@AaUiomF!G8I}Mf>e~0g#BelA-5#`cj;O5>N Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 diff --git a/l10n_it_delivery_note/static/description/index.html b/l10n_it_delivery_note/static/description/index.html new file mode 100644 index 000000000000..68fbc191917a --- /dev/null +++ b/l10n_it_delivery_note/static/description/index.html @@ -0,0 +1,530 @@ + + + + + + +ITA - Documento di trasporto + + + +
+

ITA - Documento di trasporto

+ + +

Beta License: AGPL-3 OCA/l10n-italy Translate me on Weblate Try me on Runbot

+

English

+

This module manage the Italian DDT (Delivery note).

+

From a picking is possible to generate a Delivery Note and group more picking in one delivery note. It’s also possible to invoice from the delivery note form.

+

This module is alternative to l10n_it_ddt, it follows the Odoo way to process sale orders, pickings and invoices.

+

You can’t have both l10n_it_ddt and l10n_it_delivery_note installed together.

+

There are two available settings:

+
    +
  • Base (default): one picking, one DN.
  • +
  • Advanced: more picking in one DN.
  • +
+

Italiano

+

Questo modulo consente di gestire i DDT.

+

Da un prelievo è possibile generare un DDT e raggruppare più prelievi in un DDT. È anche possibile fatturare dalla scheda del DDT.

+

Questo modulo è un alternativa al modulo l10n_it_ddt, segue la modalità Odoo di gestire ordini di vendita, prelievi e fatture.

+

Non è possibile avere installati contemporaneamente l10n_it_ddt e l10n_it_delivery_note.

+

Ci sono due impostazioni possibili.

+
    +
  • Base (predefinita): un prelievo, un DDT.
  • +
  • Avanzata: più prelievi in un DDT.
  • +
+

Table of contents

+ +
+

Configuration

+

To configure this module, go to:

+
    +
  1. Inventory → Configuration → Settings - Delivery Notes

    +

    Checking ‘Use Advanced DN Features’ allows you to manage more picking on one delivery note.

    +
  2. +
  3. Inventory → Configuration → Warehouse Management → Delivery Note Types

    +

    In delivery note type you can specify if the product price have to be printed in the delivery note report/slip.

    +
      +
    • Inventory → Configuration → Delivery Notes → Conditions of Transport
    • +
    • Inventory → Configuration → Delivery Notes → Appearances of Goods
    • +
    • Inventory → Configuration → Delivery Notes → Reasons of Transport
    • +
    • Inventory → Configuration → Delivery Notes → Methods of Transport
    • +
    +
  4. +
  5. Settings → User & Companies → Users

    +

    In the user profile settings, “Show product information in DN lines” allows showing prices in the form.

    +
  6. +
+
+
+

Usage

+
+

Funzionalità base

+

Quando un prelievo viene validato compare una scheda DDT.

+

Nella scheda fare clic su “Crea nuovo”, si apre un procedura guidata dove scegliere il tipo di DDT, quindi confermare. Immettere i dati richiesti e poi fare clic su “Valida” per numerare il DDT.

+

Una volta validato, è possibile emettere fattura direttamente dal DDT se il DDT stesso è di tipo consegna a cliente (In uscita) e si hanno i permessi sull’utente.

+

È possibile annullare il DDT, reimpostarlo a bozza e poi modificarlo. Se il DDT è fatturato il numero e la data non sono modificabili.

+

Per i trasferimenti tra magazzini creare un prelievo di tipo interno con le relative ubicazioni. Validare il prelievo visualizza la scheda DDT.

+

È possibile anche avere DDT in ingresso, ovvero dopo la validazione del prelievo selezionare la scheda per indicare il numero del DDT fornitore e la data.

+
+
+

Funzionalità avanzata

+

Vengono attivate varie funzionalità aggiuntive:

+
    +
  • più prelievi per un DDT
  • +
  • selezione multipla di prelievi e generazione dei DDT
  • +
  • aggiunta righe nota e righe sezione descrittive.
  • +
  • lista dei DDT.
  • +
+

Il report DDT stampa in righe aggiuntive i lotti/seriali e le scadenze del prodotto.

+

Il prezzo può essere indicato anche nel report DDT se nel tipo DDT è indicata la stampa prezzi. +La visibilità dei prezzi si trova nei permessi dell’utente.

+

Le fatture generate dai DDT contengono i riferimenti al DDT stesso nelle righe nota.

+
+
+

Migrazione dei dati da l10n_it_ddt

+

Il modulo presenta una funzione di migrazione dei dati dal modulo OCA l10n_it_ddt da eseguire manualmente. +Al momento, non è ancora presente un menù oppure una voce da interfaccia che permetta di eseguire questa operazione; bensì, è stato definito un comando da CLI da eseguire all’avvio di Odoo. +Di seguito, una piccola lista di passi da seguire per portare a termine la migrazione:

+
    +
  1. Eseguire un back-up del database.

    +

    Questa procedura di migrazione dei dati è stata sì sviluppata e testata, MA solamente per un numero limitato di casi. +NON è consigliata in alcun modo come funzionalità production-ready.

    +
  2. +
  3. Installare il modulo l10n_it_delivery_note SENZA prima disinstallare il modulo OCA l10n_it_ddt.

    +

    N.B.: NON iniziare ad usare il modulo l10n_it_delivery_note senza aver prima migrato i dati. +Potrebbero verificarsi, in prima battuta, problemi legati alla numerazione dei documenti creati. +Inoltre, la procedura di migrazione stessa è progettata affinché verifichi che non siano presenti documenti di l10n_it_delivery_note; qualora ne rilevi alcuni, si interromperà non eseguendo alcuna migrazione.

    +
  4. +
  5. Terminata l’installazione del modulo, terminare in sicurezza il processo di Odoo.

    +
  6. +
  7. Lanciare Odoo, nella maniera in cui si è soliti fare, aggiungendo alcuni parametri al comando d’avvio:

    +

    ./odoo-bin migrate_ddt_data –database <nome_database> […]

    +
  8. +
  9. Una volta terminata l’esecuzione della procedura, verificare che tutti i documenti siano stati migrati con successo e nel modo atteso.

    +
  10. +
  11. Verificata l’esattezza dei dati migrati, disinstallare il modulo l10n_it_ddt.

    +
  12. +
+

È possibile iniziare ad utilizzare l10n_it_delivery_note.

+
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Marco Calcagni
  • +
  • Gianmarco Conte
  • +
  • Link IT Europe Srl
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

Current maintainers:

+

As400it Byloth

+

This module is part of the OCA/l10n-italy project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/l10n_it_delivery_note/static/src/scss/stock_delivery_note.scss b/l10n_it_delivery_note/static/src/scss/stock_delivery_note.scss new file mode 100644 index 000000000000..51b714d28bf2 --- /dev/null +++ b/l10n_it_delivery_note/static/src/scss/stock_delivery_note.scss @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2019, Link IT Europe Srl + * @author: Matteo Bilotta + */ + +.o_form_view .o_notebook > .tab-content > .tab-pane +{ + & > .no-margin-page-content + { + margin-bottom: -46px; + margin-left: -16px; + margin-right: -16px; + margin-top: -16px; + + min-height: 83px; + + & > .header + { + border-bottom: 1px solid #ced4da; + border-top: 1px solid #ced4da; + display: flex; + margin-top: -17px; + min-height: 34px; + padding-left: 16px; + + & > div > .btn, + & > div > div > .btn + { + margin: 4px 3px 4px 0px; + min-height: 25px; + padding-bottom: 2px; + padding-top: 2px; + } + + & > .statusbar_status + { + align-content: space-around; + align-items: center; + align-self: stretch; + display: flex; + flex-flow: row-reverse wrap-reverse; + margin-bottom: 0px; + margin-left: auto; + overflow: hidden; + + & > .arrow_button + { + background-color: #FFFFFF; + border-left: 1px solid #DEE2E6; + border-radius: 0; + border-width: 0 0 0; + color: #ADB5BD; + cursor: default; + font-size: 11px; + font-weight: bold; + margin: 0px; + min-height: 33px; + opacity: 1.0; + padding-left: 22px; + pointer-events: none; + position: relative; + transition: all 0.1s ease 0s; + + &:not(:first-child):before, + &:not(:first-child):after + { + border-bottom: 17px solid transparent; + border-left: 11px solid white; + border-right: none; + border-top: 16px solid transparent; + bottom: auto; + content: " "; + display: block; + left: auto; + position: absolute; + right: -10px; + transition: border 0.2s ease 0s; + top: 0; + } + &:not(:first-child):before + { + border-left-color: #DEE2E6; + right: -11px; + } + + &.first_arrow + { + padding-left: 15px; + border-left: 1px solid #CED4DA; + } + + &.active + { + background-color: #E9ECEF; + color: #7C7BAD; + + &:after + { + border-left-color: #E9ECEF; + } + } + } + } + } + & > .content + { + box-shadow: inset 0px 5px 10px -4px rgba(0, 0, 0, 0.1); + padding: 16px; + + & > :first-child + { + margin-top: 0; + + &.o_field_x2many.o_field_x2many_list tr > :first-child, + &.o_field_x2many.o_field_x2many_list tr > :first-child .o_input + { + padding-left: 16px; + } + } + } + } +} + +.btn, +.o_icon_button +{ + &.fa + { + font-family: FontAwesome, Roboto, sans-serif; + } + + & > .fa:not(:last-child):before + { + margin-right: 0.5em; + } +} + +table.o_list_view tr.o_data_row > td.o_list_button +{ + padding-left: 16px !important; + width: 1px; + + & > button.o_icon_button > .fa:before + { + margin: 0px; + } +} diff --git a/l10n_it_delivery_note/tests/__init__.py b/l10n_it_delivery_note/tests/__init__.py new file mode 100644 index 000000000000..e1f46a858e91 --- /dev/null +++ b/l10n_it_delivery_note/tests/__init__.py @@ -0,0 +1 @@ +from . import test_stock_delivery_note_invoicing diff --git a/l10n_it_delivery_note/tests/test_stock_delivery_note_invoicing.py b/l10n_it_delivery_note/tests/test_stock_delivery_note_invoicing.py new file mode 100644 index 000000000000..a8e48313d920 --- /dev/null +++ b/l10n_it_delivery_note/tests/test_stock_delivery_note_invoicing.py @@ -0,0 +1,1300 @@ +from datetime import datetime, timedelta +from odoo.tests.common import TransactionCase + +DOWNPAYMENT_METHODS = ['fixed', 'percentage'] + + +class StockDeliveryNoteInvoicingTest(TransactionCase): + at_install = False + post_install = True + + sender = None + recipient = None + + desk_combination_line = None + customizable_desk_line = None + right_corner_desk_line = None + large_cabinet_line = None + storage_box_line = None + large_desk_line = None + + def create_partner(self, name, **kwargs): + return self.env['res.partner'].create({'name': name, **kwargs}) + + def create_sales_order(self, lines, **kwargs): + vals = {'partner_id': self.recipient.id} + + if lines: + vals['order_line'] = lines + + vals.update(kwargs) + + return self.env['sale.order'].create(vals) + + def prepare_sales_order_line(self, product, quantity=1.0, price=None, + **kwargs): + vals = { + 'product_id': product.id, + 'product_uom_qty': quantity + } + + if price: + vals['price_unit'] = price + + vals.update(kwargs) + + return 0, False, vals + + def add_downpayment_line(self, sales_order, method, amount, **kwargs): + if method not in DOWNPAYMENT_METHODS: + raise ValueError("Downpayment method must be 'fixed' or 'percentage'.") + + return self.env['sale.advance.payment.inv'] \ + .with_context(active_ids=sales_order.ids) \ + .create({ + 'advance_payment_method': method, + 'amount': amount, + **kwargs + }).create_invoices() + + def create_delivery_note(self, **kwargs): + vals = { + 'partner_sender_id': self.sender.id, + 'partner_id': self.recipient.id, + 'partner_shipping_id': self.recipient.id + } + + vals.update(kwargs) + + return self.env['stock.delivery.note'].create(vals) + + def setUp(self): + super().setUp() + + self.env.user.write({ + 'groups_id': [(4, self.env.ref('l10n_it_delivery_note.' + 'use_advanced_delivery_notes').id)] + }) + + self.sender = self.env.ref('base.main_partner') + self.recipient = self.create_partner("Mario Rossi") + + try: + self.desk_combination_line = \ + self.prepare_sales_order_line(self.env.ref('product.' + 'product_product_3'), 1) + self.customizable_desk_line = \ + self.prepare_sales_order_line(self.env.ref('product.' + 'product_product_4'), 3) + self.right_corner_desk_line = \ + self.prepare_sales_order_line(self.env.ref('product.' + 'product_product_5'), 2) + self.large_cabinet_line = \ + self.prepare_sales_order_line(self.env.ref('product.' + 'product_product_6'), 11) + self.storage_box_line = \ + self.prepare_sales_order_line(self.env.ref('product.' + 'product_product_7'), 5) + self.large_desk_line = \ + self.prepare_sales_order_line(self.env.ref('product.' + 'product_product_8'), 1) + + except ValueError as exc: + raise RuntimeError("It seems you're not using a database with" + " demonstration data loaded for this tests.") \ + from exc + + # ⇒ "Ordine singolo: fatturazione completa" + def test_complete_invoicing_single_so(self): + # + # SO ┐ ┌ DdT + # └ Picking ┘ + # + + sales_order = self.create_sales_order([ + self.desk_combination_line, + self.right_corner_desk_line, + self.large_cabinet_line, + self.large_desk_line + ]) + self.assertEqual(len(sales_order.order_line), 4) + + sales_order.action_confirm() + self.add_downpayment_line(sales_order, 'percentage', 10) + self.assertEqual(len(sales_order.order_line), 5) + self.assertEqual(sales_order.invoice_status, 'no') + + downpayment_order_line = sales_order.order_line[4] + self.assertEqual(downpayment_order_line.invoice_status, 'to invoice') + self.assertEqual(downpayment_order_line.qty_to_invoice, -1) + self.assertEqual(downpayment_order_line.qty_invoiced, 1) + + downpayment_invoice = sales_order.invoice_ids + self.assertEqual(len(downpayment_invoice), 1) + + downpayment_invoice_line = downpayment_invoice.invoice_line_ids + self.assertEqual(len(downpayment_invoice_line), 1) + self.assertEqual(downpayment_invoice_line.quantity, 1) + + picking = sales_order.picking_ids + self.assertEqual(len(picking), 1) + self.assertEqual(len(picking.move_lines), 4) + + picking.move_lines[0].quantity_done = 1 + picking.move_lines[1].quantity_done = 2 + picking.move_lines[2].quantity_done = 11 + picking.move_lines[3].quantity_done = 1 + + result = picking.button_validate() + self.assertIsNone(result) + + delivery_note = self.create_delivery_note() + delivery_note.transport_datetime = \ + datetime.now() + timedelta(days=1, hours=3) + delivery_note.picking_ids = picking + delivery_note.action_confirm() + self.assertEqual(len(delivery_note.line_ids), 4) + self.assertEqual(delivery_note.state, 'confirm') + self.assertEqual(delivery_note.invoice_status, 'to invoice') + + delivery_note.action_invoice() + self.assertEqual(len(delivery_note.line_ids), 4) + self.assertEqual(delivery_note.state, 'invoiced') + self.assertEqual(delivery_note.invoice_status, 'invoiced') + + self.assertEqual(len(sales_order.order_line), 5) + self.assertEqual(sales_order.invoice_status, 'invoiced') + + invoices = sales_order.invoice_ids + self.assertEqual(len(invoices), 2) + + final_invoice = invoices[0] + self.assertEqual(len(final_invoice.invoice_line_ids), 6) + self.assertEqual(final_invoice.delivery_note_ids, delivery_note) + + self.assertEqual(delivery_note.invoice_ids, final_invoice) + + # + # Linea 1 + # + order_line = sales_order.order_line[0] + self.assertEqual(order_line.invoice_status, 'invoiced') + self.assertEqual(order_line.qty_to_invoice, 0) + self.assertEqual(order_line.qty_invoiced, 1) + + move = order_line.move_ids + self.assertEqual(len(move), 1) + self.assertEqual(move.quantity_done, 1) + + delivery_note_line = delivery_note.line_ids[0] + self.assertEqual(delivery_note_line.invoice_status, 'invoiced') + self.assertEqual(delivery_note_line.sale_line_id, order_line) + self.assertEqual(delivery_note_line.product_qty, 1) + + invoice_line = final_invoice.invoice_line_ids[0] + self.assertEqual(invoice_line.sale_line_ids, order_line) + self.assertEqual(invoice_line.quantity, 1) + + # + # Linea 2 + # + order_line = sales_order.order_line[1] + self.assertEqual(order_line.invoice_status, 'invoiced') + self.assertEqual(order_line.qty_to_invoice, 0) + self.assertEqual(order_line.qty_invoiced, 2) + + move = order_line.move_ids + self.assertEqual(len(move), 1) + self.assertEqual(move.quantity_done, 2) + + delivery_note_line = delivery_note.line_ids[1] + self.assertEqual(delivery_note_line.invoice_status, 'invoiced') + self.assertEqual(delivery_note_line.sale_line_id, order_line) + self.assertEqual(delivery_note_line.product_qty, 2) + + invoice_line = final_invoice.invoice_line_ids[1] + self.assertEqual(invoice_line.sale_line_ids, order_line) + self.assertEqual(invoice_line.quantity, 2) + + # + # Linea 3 + # + order_line = sales_order.order_line[2] + self.assertEqual(order_line.invoice_status, 'invoiced') + self.assertEqual(order_line.qty_to_invoice, 0) + self.assertEqual(order_line.qty_invoiced, 11) + + move = order_line.move_ids + self.assertEqual(len(move), 1) + self.assertEqual(move.quantity_done, 11) + + delivery_note_line = delivery_note.line_ids[2] + self.assertEqual(delivery_note_line.invoice_status, 'invoiced') + self.assertEqual(delivery_note_line.sale_line_id, order_line) + self.assertEqual(delivery_note_line.product_qty, 11) + + invoice_line = final_invoice.invoice_line_ids[2] + self.assertEqual(invoice_line.sale_line_ids, order_line) + self.assertEqual(invoice_line.quantity, 11) + + # + # Linea 4 + # + order_line = sales_order.order_line[3] + self.assertEqual(order_line.invoice_status, 'invoiced') + self.assertEqual(order_line.qty_to_invoice, 0) + self.assertEqual(order_line.qty_invoiced, 1) + + move = order_line.move_ids + self.assertEqual(len(move), 1) + self.assertEqual(move.quantity_done, 1) + + delivery_note_line = delivery_note.line_ids[3] + self.assertEqual(delivery_note_line.invoice_status, 'invoiced') + self.assertEqual(delivery_note_line.sale_line_id, order_line) + self.assertEqual(delivery_note_line.product_qty, 1) + + invoice_line = final_invoice.invoice_line_ids[3] + self.assertEqual(invoice_line.sale_line_ids, order_line) + self.assertEqual(invoice_line.quantity, 1) + + # + # Linea 5 (Downpayment) + # + order_line = sales_order.order_line[4] + self.assertEqual(order_line.invoice_status, 'invoiced') + self.assertEqual(order_line.qty_to_invoice, 0) + self.assertEqual(order_line.qty_invoiced, 0) + + move = order_line.move_ids + self.assertEqual(len(move), 0) + + delivery_note_line = delivery_note.line_ids \ + .filtered(lambda l: l.sale_line_id == order_line) + + self.assertEqual(len(delivery_note_line), 0) + + invoice_line = final_invoice.invoice_line_ids[4] + self.assertEqual(invoice_line.sale_line_ids, order_line) + self.assertEqual(invoice_line.quantity, -1) + + # + # Linea 6 (DdT in fattura) + # + invoice_line = final_invoice.invoice_line_ids[5] + self.assertEqual(invoice_line.display_type, 'line_note') + self.assertEqual(invoice_line.quantity, 0) + self.assertEqual(invoice_line.delivery_note_id, delivery_note) + + # ⇒ "Ordine singolo: fatturazione parziale" + def test_partial_invoicing_single_so(self): + # + # SO ┐ ┌ DdT + # ├ Picking ┘ + # │ + # └ Picking ┐ + # └ DdT + # + + StockPicking = self.env['stock.picking'] + StockBackorderConfirmationWizard = self.env[ + 'stock.backorder.confirmation'] + + sales_order = self.create_sales_order([ + self.customizable_desk_line, + self.right_corner_desk_line, + self.large_cabinet_line, + self.storage_box_line + ]) + self.assertEqual(len(sales_order.order_line), 4) + + sales_order.action_confirm() + self.add_downpayment_line(sales_order, 'percentage', 10) + self.assertEqual(len(sales_order.order_line), 5) + self.assertEqual(sales_order.invoice_status, 'no') + + downpayment_order_line = sales_order.order_line[4] + self.assertEqual(downpayment_order_line.invoice_status, 'to invoice') + self.assertEqual(downpayment_order_line.qty_to_invoice, -1) + self.assertEqual(downpayment_order_line.qty_invoiced, 1) + + downpayment_invoice = sales_order.invoice_ids + self.assertEqual(len(downpayment_invoice), 1) + + downpayment_invoice_line = downpayment_invoice.invoice_line_ids + self.assertEqual(len(downpayment_invoice_line), 1) + self.assertEqual(downpayment_invoice_line.quantity, 1) + + picking = sales_order.picking_ids + self.assertEqual(len(picking), 1) + self.assertEqual(len(picking.move_lines), 4) + + picking.move_lines[0].quantity_done = 2 # 3 + picking.move_lines[1].quantity_done = 2 + picking.move_lines[2].quantity_done = 6 # 11 + picking.move_lines[3].quantity_done = 3 # 5 + + wizard = StockBackorderConfirmationWizard.create({ + 'pick_ids': [(4, picking.id)] + }) + wizard.process() + + first_delivery_note = self.create_delivery_note() + first_delivery_note.transport_datetime = \ + datetime.now() + timedelta(days=1, hours=3) + first_delivery_note.picking_ids = picking + first_delivery_note.action_confirm() + self.assertEqual(len(first_delivery_note.line_ids), 4) + self.assertEqual(first_delivery_note.state, 'confirm') + self.assertEqual(first_delivery_note.invoice_status, 'to invoice') + + sales_order.action_invoice_create(final=False) + self.assertEqual(len(sales_order.order_line), 5) + self.assertEqual(sales_order.invoice_status, 'no') + + invoices = sales_order.invoice_ids + self.assertEqual(len(invoices), 2) + + partial_invoice = invoices[0] + self.assertEqual(len(partial_invoice.invoice_line_ids), 5) + self.assertEqual(partial_invoice.delivery_note_ids, + first_delivery_note) + + self.assertEqual(len(first_delivery_note.line_ids), 4) + self.assertEqual(first_delivery_note.state, 'invoiced') + self.assertEqual(first_delivery_note.invoice_status, 'invoiced') + self.assertEqual(first_delivery_note.invoice_ids, partial_invoice) + + # + # = = - = = - = = - = = + # + + backorder = StockPicking.search([('backorder_id', '=', picking.id)]) + self.assertEqual(len(backorder), 1) + self.assertEqual(len(backorder.move_lines), 3) + + backorder.move_lines[0].quantity_done = 1 + backorder.move_lines[1].quantity_done = 5 + backorder.move_lines[2].quantity_done = 2 + + result = backorder.button_validate() + self.assertIsNone(result) + + second_delivery_note = self.create_delivery_note() + second_delivery_note.transport_datetime = \ + datetime.now() + timedelta(days=1, hours=3) + second_delivery_note.picking_ids = backorder + second_delivery_note.action_confirm() + self.assertEqual(len(second_delivery_note.line_ids), 3) + self.assertEqual(second_delivery_note.state, 'confirm') + self.assertEqual(second_delivery_note.invoice_status, 'to invoice') + + # + # Linea 1 + # + order_line = sales_order.order_line[0] + self.assertEqual(order_line.invoice_status, 'to invoice') + self.assertEqual(order_line.qty_to_invoice, 1) + self.assertEqual(order_line.qty_invoiced, 2) + + moves = order_line.move_ids + self.assertEqual(len(moves), 2) + self.assertEqual(moves[0].quantity_done, 2) + + delivery_note_line = first_delivery_note.line_ids[0] + self.assertEqual(delivery_note_line.invoice_status, 'invoiced') + self.assertEqual(delivery_note_line.sale_line_id, order_line) + self.assertEqual(delivery_note_line.product_qty, 2) + + invoice_line = partial_invoice.invoice_line_ids[0] + self.assertEqual(invoice_line.sale_line_ids, order_line) + self.assertEqual(invoice_line.quantity, 2) + + # + # Linea 2 + # + order_line = sales_order.order_line[1] + self.assertEqual(order_line.invoice_status, 'invoiced') + self.assertEqual(order_line.qty_to_invoice, 0) + self.assertEqual(order_line.qty_invoiced, 2) + + move = order_line.move_ids + self.assertEqual(len(move), 1) + self.assertEqual(move.quantity_done, 2) + + delivery_note_line = first_delivery_note.line_ids[1] + self.assertEqual(delivery_note_line.invoice_status, 'invoiced') + self.assertEqual(delivery_note_line.sale_line_id, order_line) + self.assertEqual(delivery_note_line.product_qty, 2) + + invoice_line = partial_invoice.invoice_line_ids[1] + self.assertEqual(invoice_line.sale_line_ids, order_line) + self.assertEqual(invoice_line.quantity, 2) + + # + # Linea 3 + # + order_line = sales_order.order_line[2] + self.assertEqual(order_line.invoice_status, 'to invoice') + self.assertEqual(order_line.qty_to_invoice, 5) + self.assertEqual(order_line.qty_invoiced, 6) + + moves = order_line.move_ids + self.assertEqual(len(moves), 2) + self.assertEqual(moves[0].quantity_done, 6) + + delivery_note_line = first_delivery_note.line_ids[2] + self.assertEqual(delivery_note_line.invoice_status, 'invoiced') + self.assertEqual(delivery_note_line.sale_line_id, order_line) + self.assertEqual(delivery_note_line.product_qty, 6) + + invoice_line = partial_invoice.invoice_line_ids[2] + self.assertEqual(invoice_line.sale_line_ids, order_line) + self.assertEqual(invoice_line.quantity, 6) + + # + # Linea 4 + # + order_line = sales_order.order_line[3] + self.assertEqual(order_line.invoice_status, 'to invoice') + self.assertEqual(order_line.qty_to_invoice, 2) + self.assertEqual(order_line.qty_invoiced, 3) + + moves = order_line.move_ids + self.assertEqual(len(moves), 2) + self.assertEqual(moves[0].quantity_done, 3) + + delivery_note_line = first_delivery_note.line_ids[3] + self.assertEqual(delivery_note_line.invoice_status, 'invoiced') + self.assertEqual(delivery_note_line.sale_line_id, order_line) + self.assertEqual(delivery_note_line.product_qty, 3) + + invoice_line = partial_invoice.invoice_line_ids[3] + self.assertEqual(invoice_line.sale_line_ids, order_line) + self.assertEqual(invoice_line.quantity, 3) + + # + # Linea 5 (DdT in fattura) + # + invoice_line = partial_invoice.invoice_line_ids[4] + self.assertEqual(invoice_line.display_type, 'line_note') + self.assertEqual(invoice_line.quantity, 0) + self.assertEqual(invoice_line.delivery_note_id, first_delivery_note) + + # + # = = - = = - = = - = = + # + + second_delivery_note.action_invoice() + self.assertEqual(len(second_delivery_note.line_ids), 3) + self.assertEqual(second_delivery_note.state, 'invoiced') + self.assertEqual(second_delivery_note.invoice_status, 'invoiced') + + self.assertEqual(len(sales_order.order_line), 5) + self.assertEqual(sales_order.invoice_status, 'invoiced') + + invoices = sales_order.invoice_ids + self.assertEqual(len(invoices), 3) + + final_invoice = invoices[0] + self.assertEqual(len(final_invoice.invoice_line_ids), 5) + self.assertEqual(final_invoice.delivery_note_ids, second_delivery_note) + + self.assertEqual(second_delivery_note.invoice_ids, final_invoice) + + # + # Linea ordine 1 + # Linea fattura 1 + # + order_line = sales_order.order_line[0] + self.assertEqual(order_line.invoice_status, 'invoiced') + self.assertEqual(order_line.qty_to_invoice, 0) + self.assertEqual(order_line.qty_invoiced, 3) + + moves = order_line.move_ids + self.assertEqual(len(moves), 2) + self.assertEqual(moves[1].quantity_done, 1) + + delivery_note_line = second_delivery_note.line_ids[0] + self.assertEqual(delivery_note_line.invoice_status, 'invoiced') + self.assertEqual(delivery_note_line.sale_line_id, order_line) + self.assertEqual(delivery_note_line.product_qty, 1) + + invoice_line = final_invoice.invoice_line_ids[0] + self.assertEqual(invoice_line.sale_line_ids, order_line) + self.assertEqual(invoice_line.quantity, 1) + + # + # Linea ordine 3 + # Linea fattura 2 + # + order_line = sales_order.order_line[2] + self.assertEqual(order_line.invoice_status, 'invoiced') + self.assertEqual(order_line.qty_to_invoice, 0) + self.assertEqual(order_line.qty_invoiced, 11) + + moves = order_line.move_ids + self.assertEqual(len(moves), 2) + self.assertEqual(moves[1].quantity_done, 5) + + delivery_note_line = second_delivery_note.line_ids[1] + self.assertEqual(delivery_note_line.invoice_status, 'invoiced') + self.assertEqual(delivery_note_line.sale_line_id, order_line) + self.assertEqual(delivery_note_line.product_qty, 5) + + invoice_line = final_invoice.invoice_line_ids[1] + self.assertEqual(invoice_line.sale_line_ids, order_line) + self.assertEqual(invoice_line.quantity, 5) + + # + # Linea ordine 4 + # Linea fattura 3 + # + order_line = sales_order.order_line[3] + self.assertEqual(order_line.invoice_status, 'invoiced') + self.assertEqual(order_line.qty_to_invoice, 0) + self.assertEqual(order_line.qty_invoiced, 5) + + moves = order_line.move_ids + self.assertEqual(len(moves), 2) + self.assertEqual(moves[1].quantity_done, 2) + + delivery_note_line = second_delivery_note.line_ids[2] + self.assertEqual(delivery_note_line.invoice_status, 'invoiced') + self.assertEqual(delivery_note_line.sale_line_id, order_line) + self.assertEqual(delivery_note_line.product_qty, 2) + + invoice_line = final_invoice.invoice_line_ids[2] + self.assertEqual(invoice_line.sale_line_ids, order_line) + self.assertEqual(invoice_line.quantity, 2) + + # + # Linea ordine 5 (Downpayment) + # Linea fattura 4 + # + order_line = sales_order.order_line[4] + self.assertEqual(order_line.invoice_status, 'invoiced') + self.assertEqual(order_line.qty_to_invoice, 0) + self.assertEqual(order_line.qty_invoiced, 0) + + move = order_line.move_ids + self.assertEqual(len(move), 0) + + delivery_notes = first_delivery_note | second_delivery_note + delivery_note_line = delivery_notes.mapped('line_ids') \ + .filtered(lambda l: l.sale_line_id == order_line) + + self.assertEqual(len(delivery_note_line), 0) + + invoice_line = final_invoice.invoice_line_ids[3] + self.assertEqual(invoice_line.sale_line_ids, order_line) + self.assertEqual(invoice_line.quantity, -1) + + # + # Linea fattura 5 (DdT in fattura) + # + invoice_line = final_invoice.invoice_line_ids[4] + self.assertEqual(invoice_line.display_type, 'line_note') + self.assertEqual(invoice_line.quantity, 0) + self.assertEqual(invoice_line.delivery_note_id, second_delivery_note) + + # ⇒ "Ordini multipli: fatturazione completa" + def test_complete_invoicing_multiple_so(self): + # + # SO ┐ + # └ Picking ┐ + # ├ DdT + # ┌ Picking ┘ + # SO ┘ + # + + first_sales_order = self.create_sales_order([ + self.desk_combination_line, + self.customizable_desk_line, + self.right_corner_desk_line + ]) + self.assertEqual(len(first_sales_order.order_line), 3) + + first_sales_order.action_confirm() + self.add_downpayment_line(first_sales_order, 'percentage', 10) + self.assertEqual(len(first_sales_order.order_line), 4) + self.assertEqual(first_sales_order.invoice_status, 'no') + + downpayment_order_line = first_sales_order.order_line[3] + self.assertEqual(downpayment_order_line.invoice_status, 'to invoice') + self.assertEqual(downpayment_order_line.qty_to_invoice, -1) + self.assertEqual(downpayment_order_line.qty_invoiced, 1) + + downpayment_invoice = first_sales_order.invoice_ids + self.assertEqual(len(downpayment_invoice), 1) + + downpayment_invoice_line = downpayment_invoice.invoice_line_ids + self.assertEqual(len(downpayment_invoice_line), 1) + self.assertEqual(downpayment_invoice_line.quantity, 1) + + first_picking = first_sales_order.picking_ids + self.assertEqual(len(first_picking), 1) + self.assertEqual(len(first_picking.move_lines), 3) + + first_picking.move_lines[0].quantity_done = 1 + first_picking.move_lines[1].quantity_done = 3 + first_picking.move_lines[2].quantity_done = 2 + + result = first_picking.button_validate() + self.assertIsNone(result) + + # + # = = - = = - = = - = = + # + + second_sales_order = self.create_sales_order([ + self.large_cabinet_line, + self.storage_box_line, + self.large_desk_line + ]) + self.assertEqual(len(second_sales_order.order_line), 3) + + second_sales_order.action_confirm() + self.assertEqual(second_sales_order.invoice_status, 'no') + + second_picking = second_sales_order.picking_ids + self.assertEqual(len(second_picking), 1) + self.assertEqual(len(second_picking.move_lines), 3) + + second_picking.move_lines[0].quantity_done = 11 + second_picking.move_lines[1].quantity_done = 5 + second_picking.move_lines[2].quantity_done = 1 + + result = second_picking.button_validate() + self.assertIsNone(result) + + # + # = = - = = - = = - = = + # + + pickings = first_picking | second_picking + delivery_note = self.create_delivery_note() + delivery_note.transport_datetime = \ + datetime.now() + timedelta(days=1, hours=3) + delivery_note.picking_ids = pickings + delivery_note.action_confirm() + self.assertEqual(len(delivery_note.line_ids), 6) + self.assertEqual(delivery_note.state, 'confirm') + self.assertEqual(delivery_note.invoice_status, 'to invoice') + + delivery_note.action_invoice() + self.assertEqual(len(delivery_note.line_ids), 6) + self.assertEqual(delivery_note.state, 'invoiced') + self.assertEqual(delivery_note.invoice_status, 'invoiced') + + self.assertEqual(len(first_sales_order.order_line), 4) + self.assertEqual(first_sales_order.invoice_status, 'invoiced') + + self.assertEqual(len(second_sales_order.order_line), 3) + self.assertEqual(second_sales_order.invoice_status, 'invoiced') + + sales_orders = first_sales_order | second_sales_order + + invoices = sales_orders.mapped('invoice_ids') + self.assertEqual(len(invoices), 2) + + final_invoice = invoices[0] + self.assertEqual(len(final_invoice.invoice_line_ids), 8) + self.assertEqual(final_invoice.delivery_note_ids, delivery_note) + + self.assertEqual(delivery_note.invoice_ids, final_invoice) + + # + # Ordine 1 - Linea 1 + # Linea fattura 1 + # + order_line = first_sales_order.order_line[0] + self.assertEqual(order_line.invoice_status, 'invoiced') + self.assertEqual(order_line.qty_to_invoice, 0) + self.assertEqual(order_line.qty_invoiced, 1) + + move = order_line.move_ids + self.assertEqual(len(move), 1) + self.assertEqual(move.quantity_done, 1) + + delivery_note_line = delivery_note.line_ids[0] + self.assertEqual(delivery_note_line.invoice_status, 'invoiced') + self.assertEqual(delivery_note_line.sale_line_id, order_line) + self.assertEqual(delivery_note_line.product_qty, 1) + + invoice_line = final_invoice.invoice_line_ids[0] + self.assertEqual(invoice_line.sale_line_ids, order_line) + self.assertEqual(invoice_line.quantity, 1) + + # + # Ordine 1 - Linea 2 + # Linea fattura 2 + # + order_line = first_sales_order.order_line[1] + self.assertEqual(order_line.invoice_status, 'invoiced') + self.assertEqual(order_line.qty_to_invoice, 0) + self.assertEqual(order_line.qty_invoiced, 3) + + move = order_line.move_ids + self.assertEqual(len(move), 1) + self.assertEqual(move.quantity_done, 3) + + delivery_note_line = delivery_note.line_ids[1] + self.assertEqual(delivery_note_line.invoice_status, 'invoiced') + self.assertEqual(delivery_note_line.sale_line_id, order_line) + self.assertEqual(delivery_note_line.product_qty, 3) + + invoice_line = final_invoice.invoice_line_ids[1] + self.assertEqual(invoice_line.sale_line_ids, order_line) + self.assertEqual(invoice_line.quantity, 3) + + # + # Ordine 1 - Linea 3 + # Linea fattura 3 + # + order_line = first_sales_order.order_line[2] + self.assertEqual(order_line.invoice_status, 'invoiced') + self.assertEqual(order_line.qty_to_invoice, 0) + self.assertEqual(order_line.qty_invoiced, 2) + + move = order_line.move_ids + self.assertEqual(len(move), 1) + self.assertEqual(move.quantity_done, 2) + + delivery_note_line = delivery_note.line_ids[2] + self.assertEqual(delivery_note_line.invoice_status, 'invoiced') + self.assertEqual(delivery_note_line.sale_line_id, order_line) + self.assertEqual(delivery_note_line.product_qty, 2) + + invoice_line = final_invoice.invoice_line_ids[2] + self.assertEqual(invoice_line.sale_line_ids, order_line) + self.assertEqual(invoice_line.quantity, 2) + + # + # Ordine 1 - Linea 4 (Downpayment) + # Linea fattura 4 + # + order_line = first_sales_order.order_line[3] + self.assertEqual(order_line.invoice_status, 'invoiced') + self.assertEqual(order_line.qty_to_invoice, 0) + self.assertEqual(order_line.qty_invoiced, 0) + + move = order_line.move_ids + self.assertEqual(len(move), 0) + + delivery_note_line = delivery_note.line_ids \ + .filtered(lambda l: l.sale_line_id == order_line) + + self.assertEqual(len(delivery_note_line), 0) + + invoice_line = final_invoice.invoice_line_ids[3] + self.assertEqual(invoice_line.sale_line_ids, order_line) + self.assertEqual(invoice_line.quantity, -1) + + # + # Ordine 2 - Linea 1 + # Linea fattura 5 + # + order_line = second_sales_order.order_line[0] + self.assertEqual(order_line.invoice_status, 'invoiced') + self.assertEqual(order_line.qty_to_invoice, 0) + self.assertEqual(order_line.qty_invoiced, 11) + + move = order_line.move_ids + self.assertEqual(len(move), 1) + self.assertEqual(move.quantity_done, 11) + + delivery_note_line = delivery_note.line_ids[3] + self.assertEqual(delivery_note_line.invoice_status, 'invoiced') + self.assertEqual(delivery_note_line.sale_line_id, order_line) + self.assertEqual(delivery_note_line.product_qty, 11) + + invoice_line = final_invoice.invoice_line_ids[4] + self.assertEqual(invoice_line.sale_line_ids, order_line) + self.assertEqual(invoice_line.quantity, 11) + + # + # Ordine 2 - Linea 2 + # Linea fattura 6 + # + order_line = second_sales_order.order_line[1] + self.assertEqual(order_line.invoice_status, 'invoiced') + self.assertEqual(order_line.qty_to_invoice, 0) + self.assertEqual(order_line.qty_invoiced, 5) + + move = order_line.move_ids + self.assertEqual(len(move), 1) + self.assertEqual(move.quantity_done, 5) + + delivery_note_line = delivery_note.line_ids[4] + self.assertEqual(delivery_note_line.invoice_status, 'invoiced') + self.assertEqual(delivery_note_line.sale_line_id, order_line) + self.assertEqual(delivery_note_line.product_qty, 5) + + invoice_line = final_invoice.invoice_line_ids[5] + self.assertEqual(invoice_line.sale_line_ids, order_line) + self.assertEqual(invoice_line.quantity, 5) + + # + # Ordine 2 - Linea 3 + # Linea fattura 7 + # + order_line = second_sales_order.order_line[2] + self.assertEqual(order_line.invoice_status, 'invoiced') + self.assertEqual(order_line.qty_to_invoice, 0) + self.assertEqual(order_line.qty_invoiced, 1) + + move = order_line.move_ids + self.assertEqual(len(move), 1) + self.assertEqual(move.quantity_done, 1) + + delivery_note_line = delivery_note.line_ids[5] + self.assertEqual(delivery_note_line.invoice_status, 'invoiced') + self.assertEqual(delivery_note_line.sale_line_id, order_line) + self.assertEqual(delivery_note_line.product_qty, 1) + + invoice_line = final_invoice.invoice_line_ids[6] + self.assertEqual(invoice_line.sale_line_ids, order_line) + self.assertEqual(invoice_line.quantity, 1) + + # + # Linea fattura 8 (DdT in fattura) + # + invoice_line = final_invoice.invoice_line_ids[7] + self.assertEqual(invoice_line.display_type, 'line_note') + self.assertEqual(invoice_line.quantity, 0) + self.assertEqual(invoice_line.delivery_note_id, delivery_note) + + # ⇒ "Ordini multipli: fatturazione parziale" + def test_partial_invoicing_multiple_so(self): + # + # ┌ Picking ──────┐ + # SO ┤ ├ DdT + # │ ┌ Picking ┘ + # │ SO ┤ + # │ └ Picking ┐ + # │ ├ DdT + # └ Picking ──────┘ + # + + StockPicking = self.env['stock.picking'] + StockBackorderConfirmationWizard = self.env[ + 'stock.backorder.confirmation'] + + first_sales_order = self.create_sales_order([ + self.desk_combination_line, + self.right_corner_desk_line, + self.large_desk_line + ]) + self.assertEqual(len(first_sales_order.order_line), 3) + + first_sales_order.action_confirm() + self.add_downpayment_line(first_sales_order, 'percentage', 10) + self.assertEqual(len(first_sales_order.order_line), 4) + self.assertEqual(first_sales_order.invoice_status, 'no') + + downpayment_order_line = first_sales_order.order_line[3] + self.assertEqual(downpayment_order_line.invoice_status, 'to invoice') + self.assertEqual(downpayment_order_line.qty_to_invoice, -1) + self.assertEqual(downpayment_order_line.qty_invoiced, 1) + + downpayment_invoice = first_sales_order.invoice_ids + self.assertEqual(len(downpayment_invoice), 1) + + downpayment_invoice_line = downpayment_invoice.invoice_line_ids + self.assertEqual(len(downpayment_invoice_line), 1) + self.assertEqual(downpayment_invoice_line.quantity, 1) + + first_picking = first_sales_order.picking_ids + self.assertEqual(len(first_picking), 1) + self.assertEqual(len(first_picking.move_lines), 3) + + first_picking.move_lines[0].quantity_done = 1 + first_picking.move_lines[1].quantity_done = 1 # 2 + first_picking.move_lines[2].quantity_done = 1 + + wizard = StockBackorderConfirmationWizard.create({ + 'pick_ids': [(4, first_picking.id)] + }) + wizard.process() + + # + # = = - = = - = = - = = + # + + second_sales_order = self.create_sales_order([ + self.customizable_desk_line, + self.large_cabinet_line, + self.storage_box_line + ]) + self.assertEqual(len(second_sales_order.order_line), 3) + + second_sales_order.action_confirm() + self.assertEqual(second_sales_order.invoice_status, 'no') + + second_picking = second_sales_order.picking_ids + self.assertEqual(len(second_picking), 1) + self.assertEqual(len(second_picking.move_lines), 3) + + second_picking.move_lines[0].quantity_done = 3 + second_picking.move_lines[1].quantity_done = 3 # 11 + second_picking.move_lines[2].quantity_done = 3 # 5 + + wizard = StockBackorderConfirmationWizard.create({ + 'pick_ids': [(4, second_picking.id)] + }) + wizard.process() + + # + # = = - = = - = = - = = + # + + pickings = first_picking | second_picking + first_delivery_note = self.create_delivery_note() + first_delivery_note.transport_datetime = \ + datetime.now() + timedelta(days=1, hours=3) + first_delivery_note.picking_ids = pickings + first_delivery_note.action_confirm() + self.assertEqual(len(first_delivery_note.line_ids), 6) + self.assertEqual(first_delivery_note.state, 'confirm') + self.assertEqual(first_delivery_note.invoice_status, 'to invoice') + + first_sales_order.action_invoice_create(final=False) + self.assertEqual(len(first_sales_order.order_line), 4) + self.assertEqual(first_sales_order.invoice_status, 'no') + + second_sales_order.action_invoice_create(final=False) + self.assertEqual(len(second_sales_order.order_line), 3) + self.assertEqual(second_sales_order.invoice_status, 'no') + + sales_orders = first_sales_order | second_sales_order + + invoices = sales_orders.mapped('invoice_ids') + self.assertEqual(len(invoices), 3) + + first_partial_invoice = invoices[0] + self.assertEqual(len(first_partial_invoice.invoice_line_ids), 4) + self.assertEqual(first_partial_invoice.delivery_note_ids, + first_delivery_note) + + second_partial_invoice = invoices[2] + self.assertEqual(len(second_partial_invoice.invoice_line_ids), 4) + self.assertEqual(second_partial_invoice.delivery_note_ids, + first_delivery_note) + + self.assertEqual(len(first_delivery_note.line_ids), 6) + # + # TODO: self.assertEqual(first_delivery_note.state, 'invoiced')? + # + self.assertEqual(len(first_delivery_note.invoice_ids), 2) + self.assertEqual(first_delivery_note.invoice_ids[1], + first_partial_invoice) + self.assertEqual(first_delivery_note.invoice_ids[0], + second_partial_invoice) + + # + # = = - = = - = = - = = + # + + first_backorder = \ + StockPicking.search([('backorder_id', '=', first_picking.id)]) + self.assertEqual(len(first_backorder), 1) + self.assertEqual(len(first_backorder.move_lines), 1) + + first_backorder.move_lines[0].quantity_done = 1 + + result = first_backorder.button_validate() + self.assertIsNone(result) + + # + # = = - = = - = = - = = + # + + second_backorder = \ + StockPicking.search([('backorder_id', '=', second_picking.id)]) + self.assertEqual(len(second_backorder), 1) + self.assertEqual(len(second_backorder.move_lines), 2) + + second_backorder.move_lines[0].quantity_done = 8 + second_backorder.move_lines[1].quantity_done = 2 + + result = second_backorder.button_validate() + self.assertIsNone(result) + + backorders = first_backorder | second_backorder + second_delivery_note = self.create_delivery_note() + second_delivery_note.transport_datetime = \ + datetime.now() + timedelta(days=1, hours=3) + second_delivery_note.picking_ids = backorders + second_delivery_note.action_confirm() + self.assertEqual(len(second_delivery_note.line_ids), 3) + self.assertEqual(second_delivery_note.state, 'confirm') + self.assertEqual(second_delivery_note.invoice_status, 'to invoice') + + # + # Ordine 1 - Linea 1 + # Fattura 1 - Linea 1 + # + order_line = first_sales_order.order_line[0] + self.assertEqual(order_line.invoice_status, 'invoiced') + self.assertEqual(order_line.qty_to_invoice, 0) + self.assertEqual(order_line.qty_invoiced, 1) + + move = order_line.move_ids + self.assertEqual(len(move), 1) + self.assertEqual(move.quantity_done, 1) + + delivery_note_line = first_delivery_note.line_ids[0] + self.assertEqual(delivery_note_line.invoice_status, 'invoiced') + self.assertEqual(delivery_note_line.sale_line_id, order_line) + self.assertEqual(delivery_note_line.product_qty, 1) + + invoice_line = first_partial_invoice.invoice_line_ids[0] + self.assertEqual(invoice_line.sale_line_ids, order_line) + self.assertEqual(invoice_line.quantity, 1) + + # + # Ordine 1 - Linea 2 + # Fattura 1 - Linea 2 + # + order_line = first_sales_order.order_line[1] + self.assertEqual(order_line.invoice_status, 'to invoice') + self.assertEqual(order_line.qty_to_invoice, 1) + self.assertEqual(order_line.qty_invoiced, 1) + + moves = order_line.move_ids + self.assertEqual(len(moves), 2) + self.assertEqual(moves[0].quantity_done, 1) + + delivery_note_line = first_delivery_note.line_ids[1] + self.assertEqual(delivery_note_line.invoice_status, 'invoiced') + self.assertEqual(delivery_note_line.sale_line_id, order_line) + self.assertEqual(delivery_note_line.product_qty, 1) + + invoice_line = first_partial_invoice.invoice_line_ids[1] + self.assertEqual(invoice_line.sale_line_ids, order_line) + self.assertEqual(invoice_line.quantity, 1) + + # + # Ordine 1 - Linea 3 + # Fattura 1 - Linea 3 + # + order_line = first_sales_order.order_line[2] + self.assertEqual(order_line.invoice_status, 'invoiced') + self.assertEqual(order_line.qty_to_invoice, 0) + self.assertEqual(order_line.qty_invoiced, 1) + + move = order_line.move_ids + self.assertEqual(len(move), 1) + self.assertEqual(move.quantity_done, 1) + + delivery_note_line = first_delivery_note.line_ids[2] + self.assertEqual(delivery_note_line.invoice_status, 'invoiced') + self.assertEqual(delivery_note_line.sale_line_id, order_line) + self.assertEqual(delivery_note_line.product_qty, 1) + + invoice_line = first_partial_invoice.invoice_line_ids[2] + self.assertEqual(invoice_line.sale_line_ids, order_line) + self.assertEqual(invoice_line.quantity, 1) + + # + # Fattura 1 - Linea 4 (DdT in fattura) + # + invoice_line = first_partial_invoice.invoice_line_ids[3] + self.assertEqual(invoice_line.display_type, 'line_note') + self.assertEqual(invoice_line.quantity, 0) + self.assertEqual(invoice_line.delivery_note_id, first_delivery_note) + + # + # Ordine 2 - Linea 1 + # Fattura 2 - Linea 1 + # + order_line = second_sales_order.order_line[0] + self.assertEqual(order_line.invoice_status, 'invoiced') + self.assertEqual(order_line.qty_to_invoice, 0) + self.assertEqual(order_line.qty_invoiced, 3) + + move = order_line.move_ids + self.assertEqual(len(move), 1) + self.assertEqual(move.quantity_done, 3) + + delivery_note_line = first_delivery_note.line_ids[3] + self.assertEqual(delivery_note_line.invoice_status, 'invoiced') + self.assertEqual(delivery_note_line.sale_line_id, order_line) + self.assertEqual(delivery_note_line.product_qty, 3) + + invoice_line = second_partial_invoice.invoice_line_ids[0] + self.assertEqual(invoice_line.sale_line_ids, order_line) + self.assertEqual(invoice_line.quantity, 3) + + # + # Ordine 2 - Linea 2 + # Fattura 2 - Linea 2 + # + order_line = second_sales_order.order_line[1] + self.assertEqual(order_line.invoice_status, 'to invoice') + self.assertEqual(order_line.qty_to_invoice, 8) + self.assertEqual(order_line.qty_invoiced, 3) + + moves = order_line.move_ids + self.assertEqual(len(moves), 2) + self.assertEqual(moves[0].quantity_done, 3) + + delivery_note_line = first_delivery_note.line_ids[4] + self.assertEqual(delivery_note_line.invoice_status, 'invoiced') + self.assertEqual(delivery_note_line.sale_line_id, order_line) + self.assertEqual(delivery_note_line.product_qty, 3) + + invoice_line = second_partial_invoice.invoice_line_ids[1] + self.assertEqual(invoice_line.sale_line_ids, order_line) + self.assertEqual(invoice_line.quantity, 3) + + # + # Ordine 2 - Linea 3 + # Fattura 2 - Linea 3 + # + order_line = second_sales_order.order_line[2] + self.assertEqual(order_line.invoice_status, 'to invoice') + self.assertEqual(order_line.qty_to_invoice, 2) + self.assertEqual(order_line.qty_invoiced, 3) + + moves = order_line.move_ids + self.assertEqual(len(moves), 2) + self.assertEqual(moves[0].quantity_done, 3) + + delivery_note_line = first_delivery_note.line_ids[5] + self.assertEqual(delivery_note_line.invoice_status, 'invoiced') + self.assertEqual(delivery_note_line.sale_line_id, order_line) + self.assertEqual(delivery_note_line.product_qty, 3) + + invoice_line = second_partial_invoice.invoice_line_ids[2] + self.assertEqual(invoice_line.sale_line_ids, order_line) + self.assertEqual(invoice_line.quantity, 3) + + # + # Fattura 2 - Linea 4 (DdT in fattura) + # + invoice_line = second_partial_invoice.invoice_line_ids[3] + self.assertEqual(invoice_line.display_type, 'line_note') + self.assertEqual(invoice_line.quantity, 0) + self.assertEqual(invoice_line.delivery_note_id, first_delivery_note) + + # + # = = - = = - = = - = = + # + + second_delivery_note.action_invoice() + self.assertEqual(len(second_delivery_note.line_ids), 3) + self.assertEqual(second_delivery_note.state, 'invoiced') + self.assertEqual(second_delivery_note.invoice_status, 'invoiced') + + self.assertEqual(len(first_sales_order.order_line), 4) + self.assertEqual(first_sales_order.invoice_status, 'invoiced') + + self.assertEqual(len(second_sales_order.order_line), 3) + self.assertEqual(second_sales_order.invoice_status, 'invoiced') + + invoices = sales_orders.mapped('invoice_ids') + self.assertEqual(len(invoices), 4) + + final_invoice = invoices[1] + self.assertEqual(len(final_invoice.invoice_line_ids), 5) + self.assertEqual(final_invoice.delivery_note_ids, second_delivery_note) + + self.assertEqual(second_delivery_note.invoice_ids, final_invoice) + + # + # Ordine 1 - Linea 2 + # Fattura 3 - Linea 1 + # + order_line = first_sales_order.order_line[1] + self.assertEqual(order_line.invoice_status, 'invoiced') + self.assertEqual(order_line.qty_to_invoice, 0) + self.assertEqual(order_line.qty_invoiced, 2) + + moves = order_line.move_ids + self.assertEqual(len(moves), 2) + self.assertEqual(moves[1].quantity_done, 1) + + delivery_note_line = second_delivery_note.line_ids[0] + self.assertEqual(delivery_note_line.invoice_status, 'invoiced') + self.assertEqual(delivery_note_line.sale_line_id, order_line) + self.assertEqual(delivery_note_line.product_qty, 1) + + invoice_line = final_invoice.invoice_line_ids[0] + self.assertEqual(invoice_line.sale_line_ids, order_line) + self.assertEqual(invoice_line.quantity, 1) + + # + # Ordine 1 - Linea 4 (Downpayment) + # Fattura 3 - Linea 2 + # + order_line = first_sales_order.order_line[3] + self.assertEqual(order_line.invoice_status, 'invoiced') + self.assertEqual(order_line.qty_to_invoice, 0) + self.assertEqual(order_line.qty_invoiced, 0) + + move = order_line.move_ids + self.assertEqual(len(move), 0) + + delivery_notes = first_delivery_note | second_delivery_note + delivery_note_line = delivery_notes.mapped('line_ids') \ + .filtered(lambda l: l.sale_line_id == order_line) + + self.assertEqual(len(delivery_note_line), 0) + + invoice_line = final_invoice.invoice_line_ids[1] + self.assertEqual(invoice_line.sale_line_ids, order_line) + self.assertEqual(invoice_line.quantity, -1) + + # + # Ordine 2 - Linea 2 + # Fattura 3 - Linea 3 + # + order_line = second_sales_order.order_line[1] + self.assertEqual(order_line.invoice_status, 'invoiced') + self.assertEqual(order_line.qty_to_invoice, 0) + self.assertEqual(order_line.qty_invoiced, 11) + + moves = order_line.move_ids + self.assertEqual(len(moves), 2) + self.assertEqual(moves[1].quantity_done, 8) + + delivery_note_line = second_delivery_note.line_ids[1] + self.assertEqual(delivery_note_line.invoice_status, 'invoiced') + self.assertEqual(delivery_note_line.sale_line_id, order_line) + self.assertEqual(delivery_note_line.product_qty, 8) + + invoice_line = final_invoice.invoice_line_ids[2] + self.assertEqual(invoice_line.sale_line_ids, order_line) + self.assertEqual(invoice_line.quantity, 8) + + # + # Ordine 2 - Linea 3 + # Fattura 3 - Linea 4 + # + order_line = second_sales_order.order_line[2] + self.assertEqual(order_line.invoice_status, 'invoiced') + self.assertEqual(order_line.qty_to_invoice, 0) + self.assertEqual(order_line.qty_invoiced, 5) + + moves = order_line.move_ids + self.assertEqual(len(moves), 2) + self.assertEqual(moves[1].quantity_done, 2) + + delivery_note_line = second_delivery_note.line_ids[2] + self.assertEqual(delivery_note_line.invoice_status, 'invoiced') + self.assertEqual(delivery_note_line.sale_line_id, order_line) + self.assertEqual(delivery_note_line.product_qty, 2) + + invoice_line = final_invoice.invoice_line_ids[3] + self.assertEqual(invoice_line.sale_line_ids, order_line) + self.assertEqual(invoice_line.quantity, 2) + + # + # Fattura 3 - Linea 5 (DdT in fattura) + # + invoice_line = final_invoice.invoice_line_ids[4] + self.assertEqual(invoice_line.display_type, 'line_note') + self.assertEqual(invoice_line.quantity, 0) + self.assertEqual(invoice_line.delivery_note_id, second_delivery_note) diff --git a/l10n_it_delivery_note/views/account_invoice.xml b/l10n_it_delivery_note/views/account_invoice.xml new file mode 100644 index 000000000000..e4300022cdbc --- /dev/null +++ b/l10n_it_delivery_note/views/account_invoice.xml @@ -0,0 +1,28 @@ + + + + + + + + account.invoice.form + account.invoice + + + + + + + + + diff --git a/l10n_it_delivery_note/views/assets.xml b/l10n_it_delivery_note/views/assets.xml new file mode 100644 index 000000000000..95937968c3cc --- /dev/null +++ b/l10n_it_delivery_note/views/assets.xml @@ -0,0 +1,18 @@ + + + + + + + + + diff --git a/l10n_it_delivery_note/views/res_config_settings.xml b/l10n_it_delivery_note/views/res_config_settings.xml new file mode 100644 index 000000000000..5a8015b4ca7d --- /dev/null +++ b/l10n_it_delivery_note/views/res_config_settings.xml @@ -0,0 +1,53 @@ + + + + + + + + res.config.settings.form + res.config.settings + + + +

Delivery Notes

+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ +
diff --git a/l10n_it_delivery_note/views/res_partner.xml b/l10n_it_delivery_note/views/res_partner.xml new file mode 100644 index 000000000000..98048560f769 --- /dev/null +++ b/l10n_it_delivery_note/views/res_partner.xml @@ -0,0 +1,26 @@ + + + + + + + + res.partner.form + res.partner + + + + + + + + + + + + + + diff --git a/l10n_it_delivery_note/views/sale_order.xml b/l10n_it_delivery_note/views/sale_order.xml new file mode 100644 index 000000000000..1e1bc65c277b --- /dev/null +++ b/l10n_it_delivery_note/views/sale_order.xml @@ -0,0 +1,24 @@ + + + + + + + + sale.order.form + sale.order + + + + + + + + + + + + diff --git a/l10n_it_delivery_note/views/stock_delivery_note.xml b/l10n_it_delivery_note/views/stock_delivery_note.xml new file mode 100644 index 000000000000..b6dfc32388ee --- /dev/null +++ b/l10n_it_delivery_note/views/stock_delivery_note.xml @@ -0,0 +1,419 @@ + + + + + + + + stock.delivery.note.form + stock.delivery.note + form + +
+ + + + + + + +
+
+ +
+ + +
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + + + + + + + + +
+
+ + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + +
+
+ + + stock.picking.tree + stock.picking + + + +