Repository: ursais/osi-addons (language: python)

Issue:
[FIX] Github Actions

agreement_helpdesk
- [x] Add a many2one field "Service Profile" (serviceprofile_id) on helpdesk.ticket
- [x] Add a group by Service Profile in the search view
- [x] Filter the list of service profiles based on the selected agreement



Discussion / hints:

Fix patch:
diff --git a/.eslintrc b/.eslintrc
deleted file mode 100644
index 28a0808b3..000000000
--- a/.eslintrc
+++ /dev/null
@@ -1,291 +0,0 @@
-{
-  "globals": {
-    "$": false,
-    "_": false,
-    "fuzzy": false,
-    "jQuery": false,
-    "moment": false,
-    "odoo": false,
-    "openerp": false,
-    "self": false
-  },
-  "env": {
-    "browser": true
-  },
-  "rules": {
-    "no-alert": "warn",
-    "no-array-constructor": "warn",
-    "no-bitwise": "off",
-    "no-caller": "warn",
-    "no-case-declarations": "warn",
-    "no-catch-shadow": "warn",
-    "no-class-assign": "warn",
-    "no-cond-assign": "warn",
-    "no-confusing-arrow": "warn",
-    "no-console": "off",
-    "no-const-assign": "warn",
-    "no-constant-condition": "warn",
-    "no-continue": "off",
-    "no-control-regex": "warn",
-    "no-debugger": "warn",
-    "no-delete-var": "warn",
-    "no-div-regex": "warn",
-    "no-dupe-args": "warn",
-    "no-dupe-class-members": "warn",
-    "no-dupe-keys": "warn",
-    "no-duplicate-case": "warn",
-    "no-duplicate-imports": "warn",
-    "no-else-return": "warn",
-    "no-empty": "warn",
-    "no-empty-character-class": "warn",
-    "no-empty-function": "warn",
-    "no-empty-pattern": "warn",
-    "no-eq-null": "warn",
-    "no-eval": "warn",
-    "no-ex-assign": "warn",
-    "no-extend-native": "warn",
-    "no-extra-bind": "warn",
-    "no-extra-boolean-cast": "warn",
-    "no-extra-label": "warn",
-    "no-extra-parens": "warn",
-    "no-extra-semi": "warn",
-    "no-fallthrough": "warn",
-    "no-floating-decimal": "warn",
-    "no-func-assign": "warn",
-    "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-invalid-this": "off",
-    "no-irregular-whitespace": "warn",
-    "no-iterator": "warn",
-    "no-label-var": "warn",
-    "no-labels": "warn",
-    "no-lone-blocks": "warn",
-    "no-lonely-if": "warn",
-    "no-loop-func": "off",
-    "no-magic-numbers": "off",
-    "no-mixed-operators": "warn",
-    "no-mixed-requires": "warn",
-    "no-mixed-spaces-and-tabs": "warn",
-    "no-multi-spaces": "warn",
-    "no-multi-str": "warn",
-    "no-multiple-empty-lines": "warn",
-    "no-native-reassign": "warn",
-    "no-negated-condition": "warn",
-    "no-negated-in-lhs": "warn",
-    "no-nested-ternary": "off",
-    "no-new": "warn",
-    "no-new-func": "warn",
-    "no-new-object": "warn",
-    "no-new-require": "warn",
-    "no-new-symbol": "warn",
-    "no-new-wrappers": "warn",
-    "no-obj-calls": "warn",
-    "no-octal": "warn",
-    "no-octal-escape": "warn",
-    "no-param-reassign": "warn",
-    "no-path-concat": "warn",
-    "no-plusplus": "off",
-    "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": "warn",
-    "no-script-url": "warn",
-    "no-self-assign": "warn",
-    "no-self-compare": "warn",
-    "no-sequences": "warn",
-    "no-shadow": "warn",
-    "no-shadow-restricted-names": "warn",
-    "no-whitespace-before-property": "warn",
-    "no-spaced-func": "warn",
-    "no-sparse-arrays": "warn",
-    "no-sync": "warn",
-    "no-tabs": "warn",
-    "no-ternary": "off",
-    "no-trailing-spaces": "warn",
-    "no-this-before-super": "warn",
-    "no-throw-literal": "warn",
-    "no-undef": "warn",
-    "no-undef-init": "warn",
-    "no-undefined": "off",
-    "no-unexpected-multiline": "warn",
-    "no-underscore-dangle": "off",
-    "no-unmodified-loop-condition": "warn",
-    "no-unneeded-ternary": "warn",
-    "no-unreachable": "warn",
-    "no-unsafe-finally": "warn",
-    "no-unused-expressions": "warn",
-    "no-unused-labels": "warn",
-    "no-unused-vars": "warn",
-    "no-use-before-define": "warn",
-    "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-var": "off",
-    "no-warning-comments": "off",
-    "no-with": "warn",
-    "array-bracket-spacing": "off",
-    "array-callback-return": "warn",
-    "arrow-body-style": "warn",
-    "arrow-parens": "warn",
-    "arrow-spacing": "off",
-    "accessor-pairs": "warn",
-    "block-scoped-var": "off",
-    "block-spacing": ["warn", "always"],
-    "brace-style": "warn",
-    "callback-return": "warn",
-    "camelcase": "off",
-    "capitalized-comments": ["warn", "always", {
-      "ignoreConsecutiveComments": true,
-      "ignoreInlineComments": true
-    }],
-    "comma-dangle": ["warn", "always-multiline"],
-    "comma-spacing": ["warn", {
-      "before": false,
-      "after": true
-    }],
-    "comma-style": "warn",
-    "complexity": [
-      "warn",
-      15
-    ],
-    "computed-property-spacing": "off",
-    "consistent-return": "off",
-    "consistent-this": "off",
-    "constructor-super": "warn",
-    "curly": "warn",
-    "default-case": "off",
-    "dot-location": ["warn", "property"],
-    "dot-notation": "warn",
-    "eol-last": "warn",
-    "eqeqeq": "warn",
-    "func-names": "off",
-    "func-style": "off",
-    "generator-star-spacing": "off",
-    "global-require": "warn",
-    "guard-for-in": "off",
-    "handle-callback-err": "warn",
-    "id-blacklist": "warn",
-    "id-length": "off",
-    "id-match": "warn",
-    "indent": "warn",
-    "init-declarations": "warn",
-    "jsx-quotes": "warn",
-    "key-spacing": "off",
-    "keyword-spacing": "warn",
-    "linebreak-style": [
-      "warn",
-      "unix"
-    ],
-    "lines-around-comment": "warn",
-    "max-depth": "warn",
-    "max-len": ["warn", {
-      "code": 88,
-      "ignorePattern": "odoo\\.define\\(",
-      "tabWidth": 4
-    }],
-    "max-lines": "off",
-    "max-nested-callbacks": "warn",
-    "max-params": "off",
-    "max-statements": "off",
-    "max-statements-per-line": "warn",
-    "multiline-ternary": "off",
-    "new-cap": "off",
-    "new-parens": "warn",
-    "newline-after-var": "off",
-    "newline-before-return": "off",
-    "newline-per-chained-call": "off",
-    "object-curly-newline": ["warn", { "consistent": true }],
-    "object-curly-spacing": ["warn", "never"],
-    "object-property-newline": ["warn", {
-      "allowAllPropertiesOnSameLine": true
-    }],
-    "object-shorthand": "off",
-    "one-var": "off",
-    "one-var-declaration-per-line": "off",
-    "operator-assignment": "warn",
-    "operator-linebreak": "warn",
-    "padded-blocks": "off",
-    "prefer-arrow-callback": "off",
-    "prefer-const": "warn",
-    "prefer-reflect": "off",
-    "prefer-rest-params": "off",
-    "prefer-spread": "off",
-    "prefer-template": "off",
-    "quote-props": "off",
-    "quotes": "off",
-    "radix": "warn",
-    "require-yield": "warn",
-    "rest-spread-spacing": "off",
-    "semi": [
-      "warn",
-      "always"
-    ],
-    "semi-spacing": "warn",
-    "sort-imports": "warn",
-    "sort-vars": "off",
-    "space-before-blocks": "warn",
-    "space-before-function-paren": "warn",
-    "space-in-parens": "off",
-    "space-infix-ops": "off",
-    "space-unary-ops": "off",
-    "spaced-comment": ["warn", "always"],
-    "strict": ["warn", "function"],
-    "template-curly-spacing": "off",
-    "unicode-bom": "warn",
-    "use-isnan": "warn",
-    "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",
-    "vars-on-top": "off",
-    "wrap-iife": "warn",
-    "wrap-regex": "warn",
-    "yield-star-spacing": "off",
-    "yoda": "warn"
-  },
-  "parserOptions": {
-      "ecmaVersion": 2017
-  }
-}
diff --git a/.eslintrc.yml b/.eslintrc.yml
new file mode 100644
index 000000000..b1b456989
--- /dev/null
+++ b/.eslintrc.yml
@@ -0,0 +1,180 @@
+env:
+    browser: true
+
+# See https://github.com/OCA/odoo-community.org/issues/37#issuecomment-470686449
+parserOptions:
+    ecmaVersion: 2017
+
+# Globals available in Odoo that shouldn't produce errorings
+globals:
+    _: readonly
+    $: readonly
+    fuzzy: readonly
+    jQuery: readonly
+    moment: readonly
+    odoo: readonly
+    openerp: readonly
+    Promise: 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/.flake8 b/.flake8
index 638a9cd89..6bb5147f5 100644
--- a/.flake8
+++ b/.flake8
@@ -1,6 +1,6 @@
 [flake8]
 max-line-length = 88
-max-complexity = 16
+max-complexity = 19
 # B = bugbear
 # B9 = bugbear opinionated (incl line length)
 select = C,E,F,W,B,B9
diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml
new file mode 100644
index 000000000..30e3cdabb
--- /dev/null
+++ b/.github/workflows/pre-commit.yml
@@ -0,0 +1,15 @@
+name: pre-commit
+
+on:
+    pull_request:
+    push:
+
+jobs:
+    pre-commit:
+        runs-on: ubuntu-latest
+        steps:
+            - uses: actions/checkout@v2
+            - uses: actions/setup-python@v2
+              with:
+                  python-version: "3.9"
+            - uses: pre-commit/action@v2.0.0
diff --git a/.gitignore b/.gitignore
index d22ce9c49..a3faef8f8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -73,4 +73,4 @@ docs/_build/
 *.swp
 
 # OCA rules
-!static/lib/
\ No newline at end of file
+!static/lib/
diff --git a/.isort.cfg b/.isort.cfg
index 2c20bbfb1..5751c40dd 100644
--- a/.isort.cfg
+++ b/.isort.cfg
@@ -9,4 +9,4 @@ line_length=88
 known_odoo=odoo
 known_odoo_addons=odoo.addons
 sections=FUTURE,STDLIB,THIRDPARTY,ODOO,ODOO_ADDONS,FIRSTPARTY,LOCALFOLDER
-known_third_party=anthem,helper,locust,locustodoorpc,pkg_resources,psycopg2,pytest,selenium,setuptools,tasks
+known_third_party=
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 876d1e98e..536a6f81f 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,68 +1,135 @@
-exclude: "^setup/|/static/lib/|/static/src/lib/"
+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$|
+    # 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$|
+    # You don't usually want a bot to modify your legal texts
+    (LICENSE.*|COPYING.*)
 default_language_version:
-  python: python3
+    python: python3
+    node: "14.13.0"
 repos:
-- repo: https://github.com/psf/black
-  rev: 19.3b0
-  hooks:
-  - id: black
-- repo: https://github.com/pre-commit/pre-commit-hooks
-  rev: v2.3.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: flake8
-    name: flake8 except __init__.py
-    exclude: /__init__\.py$
-    additional_dependencies: ["flake8-bugbear==19.8.0"]
-  - id: flake8
-    name: flake8 only __init__.py
-    args: ["--extend-ignore=F401"]  # ignore unused imports in __init__.py
-    files: /__init__\.py$
-    additional_dependencies: ["flake8-bugbear==19.8.0"]
-  - id: fix-encoding-pragma
-    args: ["--remove"]
-  - id: check-case-conflict
-  - id: check-docstring-first
-  - id: check-executables-have-shebangs
-  - id: check-merge-conflict
-  - id: check-symlinks
-  - id: check-xml
-  - id: mixed-line-ending
-    args: ["--fix=lf"]
-- repo: https://github.com/pre-commit/mirrors-pylint
-  rev: v2.3.1
-  hooks:
-  - id: pylint
-    name: pylint with optional checks
-    args: ["--rcfile=.pylintrc", "--exit-zero"]
-    verbose: true
-    additional_dependencies: ["pylint-odoo==3.0.3"]
-  - id: pylint
-    name: pylint with mandatory checks
-    args: ["--rcfile=.pylintrc-mandatory"]
-    additional_dependencies: ["pylint-odoo==3.0.3"]
-- repo: https://github.com/asottile/pyupgrade
-  rev: v1.24.0
-  hooks:
-  - id: pyupgrade
-- repo: https://github.com/asottile/seed-isort-config
-  rev: v1.9.3
-  hooks:
-  - id: seed-isort-config
-- repo: https://github.com/pre-commit/mirrors-isort
-  rev: v4.3.21
-  hooks:
-  - id: isort
-    name: isort except __init__.py
-    exclude: /__init__\.py$
-- repo: https://github.com/pre-commit/mirrors-eslint
-  rev: v6.5.1
-  hooks:
-  - id: eslint
-    verbose: true
+    - 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$"
+    - repo: https://github.com/oca/maintainer-tools
+      rev: ab1d7f6
+      hooks:
+          # update the NOT INSTALLABLE ADDONS section above
+          - id: oca-update-pre-commit-excluded-addons
+          - id: oca-fix-manifest-website
+            args: ["https://github.com/ursais/osi-addons"]
+    - repo: https://github.com/myint/autoflake
+      rev: v1.4
+      hooks:
+          - id: autoflake
+            args: ["-i", "--ignore-init-module-imports"]
+    - repo: https://github.com/psf/black
+      rev: 21.10b0
+      hooks:
+          - id: black
+    - repo: https://github.com/pre-commit/mirrors-prettier
+      rev: v2.1.2
+      hooks:
+          - id: prettier
+            name: prettier + plugin-xml
+            additional_dependencies:
+                - "prettier@2.1.2"
+                - "@prettier/plugin-xml@0.12.0"
+            args:
+                - --plugin=@prettier/plugin-xml
+    - repo: https://github.com/pre-commit/mirrors-eslint
+      rev: v7.8.1
+      hooks:
+          - id: eslint
+            verbose: true
+            args:
+                - --color
+                - --fix
+    - repo: https://github.com/pre-commit/pre-commit-hooks
+      rev: v3.2.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/asottile/pyupgrade
+      rev: v2.7.2
+      hooks:
+          - id: pyupgrade
+    - repo: https://github.com/PyCQA/isort
+      rev: 5.5.1
+      hooks:
+          - id: isort
+            name: isort except __init__.py
+            args:
+                - --settings=.
+            exclude: /__init__\.py$
+    - repo: https://github.com/acsone/setuptools-odoo
+      rev: 3.0.3
+      hooks:
+          - id: setuptools-odoo-make-default
+          - id: setuptools-odoo-get-requirements
+            args:
+                - --output
+                - requirements.txt
+                - --header
+                - "# generated from manifests external_dependencies"
+    - repo: https://gitlab.com/PyCQA/flake8
+      rev: 3.8.3
+      hooks:
+          - id: flake8
+            name: flake8 except __init__.py
+            exclude: /__init__\.py$
+            additional_dependencies: ["flake8-bugbear==20.1.4"]
+          - id: flake8
+            name: flake8 only __init__.py
+            args: ["--extend-ignore=F401"] # ignore unused imports in __init__.py
+            files: /__init__\.py$
+            additional_dependencies: ["flake8-bugbear==20.1.4"]
+    - repo: https://github.com/PyCQA/pylint
+      rev: pylint-2.5.3
+      hooks:
+          - id: pylint
+            name: pylint with optional checks
+            args:
+                - --rcfile=.pylintrc
+                - --exit-zero
+            verbose: true
+            additional_dependencies: &pylint_deps
+                - pylint-odoo==3.5.0
+          - id: pylint
+            name: pylint with mandatory checks
+            args:
+                - --rcfile=.pylintrc-mandatory
+            additional_dependencies: *pylint_deps
diff --git a/.travis.yml b/.travis.yml
index 9191da025..ba0c1a1af 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,48 +1,51 @@
 language: python
 cache:
-    - $HOME/.cache/pip
-    - $HOME/.cache/pre-commit
+    directories:
+        - $HOME/.cache/pip
+        - $HOME/.cache/pre-commit
 
 python:
-  - "3.6"
+    - "3.6"
 
 addons:
-  postgresql: "9.6"
-  apt:
-    packages:
-      - expect-dev  # provides unbuffer utility
+    postgresql: "9.6"
+    apt:
+        packages:
+            - expect-dev # provides unbuffer utility
 
 stages:
-  - linting
-  - test
+    - linting
+    - test
 
 jobs:
-  include:
-    - stage: linting
-      name: "pre-commit"
-      python: "3.6"  # Black requires python >= 3.6
-      install: pip install pre-commit
-      script: pre-commit run --all --show-diff-on-failure --verbose --color always
-      after_success:
-      before_install:
-    - stage: test
-      env:
-        - TESTS="1" ODOO_REPO="odoo/odoo" MAKEPOT="1"
-    - stage: test
-      env:
-        - TESTS="1" ODOO_REPO="OCA/OCB"
-
+    include:
+        - stage: linting
+          name: "pre-commit"
+          python: "3.6" # Black requires python >= 3.6
+          install: pip install pre-commit
+          script: pre-commit run --all --show-diff-on-failure --verbose --color always
+          after_success:
+          before_install:
+        - stage: test
+          env:
+              - TESTS=1 ODOO_REPO="odoo/odoo" MAKEPOT="1"
+        - stage: test
+          env:
+              - TESTS=1 ODOO_REPO="OCA/OCB"
 env:
-  global:
-  - VERSION="14.0" TESTS="0" LINT_CHECK="0" MAKEPOT="0"
+    global:
+        - VERSION="14.0" TESTS="0" LINT_CHECK="0" MAKEPOT="0"
+        - MQT_DEP=PIP
+        - EXCLUDE="documents_helpdesk"
 
 install:
-  - git clone --depth=1 https://github.com/ursais/maintainer-quality-tools.git ${HOME}/maintainer-quality-tools
-  - export PATH=${HOME}/maintainer-quality-tools/travis:${PATH}
-  - travis_install_nightly
+    - git clone --depth=1 https://github.com/ursais/maintainer-quality-tools.git
+      ${HOME}/maintainer-quality-tools
+    - export PATH=${HOME}/maintainer-quality-tools/travis:${PATH}
+    - travis_install_nightly
 
 script:
-  - travis_run_tests
+    - travis_run_tests
 
 after_success:
-  - travis_after_tests_success
+    - travis_after_tests_success
diff --git a/README.md b/README.md
index a5b034264..fa192d489 100644
--- a/README.md
+++ b/README.md
@@ -8,4 +8,3 @@ Odoo modules from Open Source Integrators.
 
 
 [//]: # (end addons)
-
diff --git a/account_bank_statement_extend/README.rst b/account_bank_statement_extend/README.rst
new file mode 100644
index 000000000..63ff64664
--- /dev/null
+++ b/account_bank_statement_extend/README.rst
@@ -0,0 +1,77 @@
+=============================
+Account Bank Statement Extend
+=============================
+
+.. |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-LGPL--3-blue.png
+    :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+    :alt: License: LGPL-3
+.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fosi--addons-lightgray.png?logo=github
+    :target: https://github.com/OCA/osi-addons/tree/14.0/account_bank_statement_extend
+    :alt: OCA/osi-addons
+
+|badge1| |badge2| |badge3|
+
+**Table of contents**
+
+.. contents::
+   :local:
+
+To use this module, you need to:
+
+* Go to Accounting Dashboard
+* Bank journal Open
+* View Bank Statement and From tree View select multiple statement and print report.
+* In Statement Get Report with source Account from main Move.
+
+
+Bug Tracker
+===========
+
+Bugs are tracked on `GitHub Issues <https://github.com/OCA/osi-addons/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 <https://github.com/OCA/osi-addons/issues/new?body=module:%20account_bank_statement_extend%0Aversion:%2014.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
+
+Do not contact contributors directly about support or help with technical issues.
+
+Credits
+=======
+
+* Balaji Kannan <bkannan@opensourceintegrators.com>
+* Hardik Suthar <hsuthar@opensourceintegrators.com>
+
+
+Contributors
+------------
+
+* Open Source Integrators <contact@opensourceintegrators.com>
+* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
+
+Authors
+~~~~~~~
+
+* Open Source Integrators
+
+
+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.
+
+Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
+
+This module is part of the `OCA/osi-addons <https://github.com/OCA/osi-addons/tree/14.0/account_bank_statement_extend>`_ project on GitHub.
+
+You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
+
diff --git a/account_bank_statement_extend/__init__.py b/account_bank_statement_extend/__init__.py
new file mode 100644
index 000000000..9dcd0caa0
--- /dev/null
+++ b/account_bank_statement_extend/__init__.py
@@ -0,0 +1,5 @@
+# Copyright (C) 2019 - 2021, Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from . import report
+from . import wizard
diff --git a/account_bank_statement_extend/__manifest__.py b/account_bank_statement_extend/__manifest__.py
new file mode 100644
index 000000000..989fd852d
--- /dev/null
+++ b/account_bank_statement_extend/__manifest__.py
@@ -0,0 +1,24 @@
+# Copyright (C) 2019 - 2021, Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+{
+    "name": "OSI Account Bank Statement Report Extend",
+    "version": "14.0.1.0.0",
+    "license": "AGPL-3",
+    "author": "Open Source Integrators",
+    "category": "account",
+    "maintainers": "Open Source Integrators",
+    "summary": """OSI Account Bank Statement Report
+                Extend Get More Details in Statement Report""",
+    "website": "https://github.com/ursais/osi-addons",
+    "depends": [
+        "account",
+    ],
+    "data": [
+        "security/ir.model.access.csv",
+        "report/account_bank_statement.xml",
+        "report/bank_statement_lines_report.xml",
+        "wizard/parser_report_bank_statement.xml",
+    ],
+    "installable": True,
+}
diff --git a/account_bank_statement_extend/report/__init__.py b/account_bank_statement_extend/report/__init__.py
new file mode 100644
index 000000000..fb97c5916
--- /dev/null
+++ b/account_bank_statement_extend/report/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (C) 2019 - 2021, Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from . import account_bank_statement
diff --git a/account_bank_statement_extend/report/account_bank_statement.py b/account_bank_statement_extend/report/account_bank_statement.py
new file mode 100644
index 000000000..ba87e8b81
--- /dev/null
+++ b/account_bank_statement_extend/report/account_bank_statement.py
@@ -0,0 +1,107 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import models
+from odoo.tools.misc import format_date
+
+
+class AccountBankStatement(models.Model):
+    _inherit = "account.bank.statement"
+
+    def get_statement_entries(self):
+        rl = []
+        for stmt_line in self.line_ids:
+            reconcile_ids = stmt_line.move_id.line_ids.full_reconcile_id
+            if not stmt_line.move_id.line_ids.full_reconcile_id:
+                rl.append(
+                    {
+                        "date": format_date(self.env, stmt_line.date),
+                        "account_id": "      ",
+                        "partner_id": stmt_line.partner_id.name,
+                        "partner_bank_id": stmt_line.partner_bank_id,
+                        "statement_id": stmt_line.name,
+                        "move_id": "      ",
+                        "ref": stmt_line.payment_ref,
+                        "note": stmt_line.narration,
+                        "matching_number": "      ",
+                        "amount": stmt_line.amount,
+                        "debit": stmt_line.amount > 0 and abs(stmt_line.amount) or 0.0,
+                        "credit": stmt_line.amount < 0 and abs(stmt_line.amount) or 0.0,
+                    }
+                )
+                continue
+            else:
+                suspense_line = self.env["account.move.line"].search(
+                    [
+                        ("full_reconcile_id", "=", reconcile_ids.id),
+                        ("id", "not in", stmt_line.move_id.line_ids.ids),
+                    ]
+                )
+                payment_line = suspense_line.move_id.line_ids.filtered(
+                    lambda l: l.id != suspense_line.id
+                    and l.account_id.internal_type in ("receivable", "payable")
+                )
+
+                for payment in payment_line:
+                    rl.append(
+                        {
+                            "date": format_date(self.env, stmt_line.date),
+                            "account_id": payment.account_id.code,
+                            "partner_id": payment.partner_id.name,
+                            "partner_bank_id": "      ",
+                            "statement_id": stmt_line.name,
+                            "move_id": payment.move_id.name,
+                            "ref": payment.ref,
+                            "note": "      ",
+                            "matching_number": payment.full_reconcile_id.name,
+                            "amount": stmt_line.amount,
+                            "debit": stmt_line.amount > 0
+                            and abs(stmt_line.amount)
+                            or payment.debit,
+                            "credit": stmt_line.amount < 0
+                            and abs(stmt_line.amount)
+                            or payment.credit,
+                        }
+                    )
+
+                outstanding_line = suspense_line.move_id.line_ids.filtered(
+                    lambda l: l.id not in (suspense_line + payment_line).ids
+                    and l.account_id.internal_type not in ("receivable", "payable")
+                )
+                reconcile_ids = outstanding_line.full_reconcile_id
+
+                if len(reconcile_ids) and len(outstanding_line):
+                    partner_line = self.env["account.move.line"].search(
+                        [
+                            ("full_reconcile_id", "=", reconcile_ids.id),
+                            ("id", "not in", outstanding_line.ids),
+                        ]
+                    )
+                    payment_line = partner_line.move_id.line_ids.filtered(
+                        lambda l: l.id != partner_line.id
+                        and l.account_id.internal_type in ("receivable", "payable")
+                    )
+
+                    for payment in payment_line:
+                        rl.append(
+                            {
+                                "date": format_date(self.env, stmt_line.date),
+                                "account_id": payment.account_id.code,
+                                "partner_id": payment.partner_id.name,
+                                "partner_bank_id": "      ",
+                                "statement_id": stmt_line.name,
+                                "move_id": payment.move_id.name,
+                                "ref": payment.ref,
+                                "note": "      ",
+                                "matching_number": payment.full_reconcile_id.name,
+                                "amount": stmt_line.amount,
+                                "debit": stmt_line.amount > 0
+                                and abs(stmt_line.amount)
+                                or payment.debit,
+                                "credit": stmt_line.amount < 0
+                                and abs(stmt_line.amount)
+                                or payment.credit,
+                            }
+                        )
+
+        return rl
diff --git a/account_bank_statement_extend/report/account_bank_statement.xml b/account_bank_statement_extend/report/account_bank_statement.xml
new file mode 100644
index 000000000..f19543851
--- /dev/null
+++ b/account_bank_statement_extend/report/account_bank_statement.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<odoo>
+    <template
+        id="report_statement_inherit"
+        inherit_id="account.report_statement"
+    >
+        <xpath
+            expr="//div[hasclass('page')]/table[2]/tbody/tr/td/table"
+            position="inside"
+        >
+
+        <tr t-foreach="o.get_base_reconcile_entries()" t-as="datas">
+            <td class="p-0 w-25">
+                <span
+                        class="d-block font-weight-bold"
+                        t-esc="datas.get('date')"
+                    />
+            </td>
+            <td class="p-0">
+                <span
+                        class="d-block font-weight-bold"
+                        t-if="datas.get('partner_id')"
+                        t-esc="datas.get('partner_id')"
+                    />
+                <span
+                        class="d-block"
+                        t-if="datas.get('matching_number')"
+                        t-esc="datas.get('matching_number')"
+                    />
+                <span
+                        class="d-block"
+                        t-if="datas.get('account_id')"
+                        t-esc="datas.get('account_id')"
+                    />
+                <span
+                        class="d-block"
+                        t-if="datas.get('move_id')"
+                        t-esc="datas.get('move_id')"
+                    />
+                <span
+                        class="d-block"
+                        t-if="datas.get('ref')"
+                        t-esc="datas.get('ref')"
+                    />
+            </td>
+            <td class="text-right p-0">
+                <t t-if="datas.get('credit')!=0.0">
+                    <span
+                            class="d-block font-weight-bold"
+                            t-esc="datas.get('credit')"
+                            t-options='{"widget": "monetary", "display_currency": o.currency_id}'
+                        />
+                </t>
+                <t t-else="">
+                    <span
+                            class="d-block font-weight-bold"
+                            t-esc="datas.get('debit')"
+                            t-options='{"widget": "monetary", "display_currency": o.currency_id}'
+                        />
+                </t>
+            </td>
+        </tr>
+        </xpath>
+    </template>
+</odoo>
diff --git a/account_bank_statement_extend/report/bank_statement_lines_report.xml b/account_bank_statement_extend/report/bank_statement_lines_report.xml
new file mode 100644
index 000000000..9b46b0161
--- /dev/null
+++ b/account_bank_statement_extend/report/bank_statement_lines_report.xml
@@ -0,0 +1,181 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<odoo>
+
+    <template id="bank_statement_line_report_template">
+        <t t-call="web.html_container">
+            <t t-foreach="docs" t-as="o">
+                <t t-call="web.external_layout">
+                    <div class="page">
+                        <head>
+                        </head>
+                        <style>
+                                thead,tr,td {border: 1px solid black;},
+                                th {color: #0c0c0c;}
+                        </style>
+                        <h2>Bank Statement Report</h2>
+                        <h6>From :- <span t-esc="o.date_from" />
+                        </h6>
+                        <h6>To :- <span t-esc="o.date_to" />
+                        </h6>
+                        <h6>Report Generated Date : <span
+                                t-esc="o.create_date.date()"
+                            />
+                        </h6>
+                        <h6>Report Generated By : <span
+                                t-esc="o.user_id.name"
+                            />
+                        </h6>
+
+                        <!-- <table class="table table-lg m-0 table-borderless border border-right-0 border-left-0 border-info">
+                                <tbody>
+                                    <tr>
+                                        <td > -->
+                                            <table
+                            class="table table-borderless m-0"
+                        >
+                                                <tr>
+                                                    <td>
+                                                        <strong
+                                    >Starting Balance</strong>
+                                                        <br />
+                                                    </td>
+                                                    <td>
+                                                        <strong>
+                                                            <span
+                                            t-esc="o.get_starting_balance()"
+                                        />
+                                                        </strong>
+                                                    </td>
+                                                </tr>
+                                                <tr>
+                                                    <td>
+                                                        <strong
+                                    >Ending Balance</strong>
+                                                    </td>
+                                                    <td>
+                                                        <strong>
+                                                            <span
+                                            t-esc="o.get_ending_balance()"
+                                        />
+                                                        </strong>
+                                                    </td>
+                                                </tr>
+                                                <tr>
+                                                    <td>
+                                                        <strong
+                                    >Transection Amount</strong>
+                                                    </td>
+                                                    <td>
+                                                        <strong>
+                                                            <span
+                                            t-esc="o.get_total_transection_amt()"
+                                        />
+                                                        </strong>
+                                                    </td>
+                                                </tr>
+                                            </table>
+                                        <!-- </td>
+                                    </tr>
+                                </tbody>
+                            </table> -->
+
+
+                        <table
+                            class="table"
+                            style="border: 1px solid black;margin-top: 50px;border-top:1px solid black;"
+                        >
+                            <thead>
+                                <tr style="border: 1px solid black;">
+                                    <th
+                                        style="color: #0c0c0c;"
+                                    >Serial Number</th>
+                                    <th style="color: #0c0c0c;">Date</th>
+                                    <th style="color: #0c0c0c;">Account</th>
+                                    <th style="color: #0c0c0c;">Partner</th>
+                                    <th style="color: #0c0c0c;">Statement</th>
+                                    <th style="color: #0c0c0c;">Entry</th>
+                                    <th style="color: #0c0c0c;">Reference</th>
+                                    <th
+                                        style="color: #0c0c0c;"
+                                    >Matching Number</th>
+                                    <th style="color: #0c0c0c;">Debit</th>
+                                    <th style="color: #0c0c0c;">Credit</th>
+                                </tr>
+                            </thead>
+                            <tbody>
+                                <tr t-foreach="docs" t-as="o">
+                                    <t t-set="i" t-value="1" />
+                                    <tr
+                                        t-foreach="o.get_bank_statement_report_data()"
+                                        t-as="datas"
+                                    >
+                                        <tr t-foreach="datas" t-as="line">
+                                            <td>
+                                                <span t-esc="i" />
+                                            </td>
+                                            <td>
+                                                <span
+                                                    t-esc="line.get('date')"
+                                                />
+                                            </td>
+                                            <td>
+                                                <span
+                                                    t-esc="line.get('account_id')"
+                                                />
+                                            </td>
+                                            <td>
+                                                <span
+                                                    t-esc="line.get('partner_id')"
+                                                />
+                                            </td>
+                                            <td><span
+                                                    t-esc="line.get('statement_id')"
+                                                /></td>
+                                            <td>
+                                                <span
+                                                    t-esc="line.get('move_id')"
+                                                />
+                                            </td>
+                                            <td>
+                                                <span t-esc="line.get('ref')" />
+                                            </td>
+                                            <td>
+                                               <span
+                                                    t-esc="line.get('matching_number')"
+                                                />
+                                            </td>
+                                            <td>
+                                                 <span
+                                                    t-esc="line.get('debit')"
+                                                />
+                                            </td>
+                                            <td>
+                                                <span
+                                                    t-esc="line.get('credit')"
+                                                />
+                                            </td>
+                                            <t t-set="i" t-value="i+1" />
+                                        </tr>
+                                        </tr>
+                                </tr>
+                            </tbody>
+                        </table>
+                    </div>
+                </t>
+            </t>
+        </t>
+    </template>
+
+    <record id="action_bank_statement_wiz_report" model="ir.actions.report">
+        <field name="name">Bank Statement Lines</field>
+        <field name="model">report.bank.statement</field>
+        <field name="report_type">qweb-pdf</field>
+        <field
+            name="report_name"
+        >account_bank_statement_extend.bank_statement_line_report_template</field>
+        <field
+            name="report_file"
+        >account_bank_statement_extend.bank_statement_line_report_template</field>
+    </record>
+
+</odoo>
diff --git a/account_bank_statement_extend/security/ir.model.access.csv b/account_bank_statement_extend/security/ir.model.access.csv
new file mode 100644
index 000000000..9c2246918
--- /dev/null
+++ b/account_bank_statement_extend/security/ir.model.access.csv
@@ -0,0 +1,2 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_report_bank_statement,report.bank.statement,model_report_bank_statement,base.group_user,1,1,1,1
diff --git a/account_bank_statement_extend/wizard/__init__.py b/account_bank_statement_extend/wizard/__init__.py
new file mode 100644
index 000000000..c560b221d
--- /dev/null
+++ b/account_bank_statement_extend/wizard/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (C) 2019 - 2021, Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from . import parser_report_bank_statement
diff --git a/account_bank_statement_extend/wizard/parser_report_bank_statement.py b/account_bank_statement_extend/wizard/parser_report_bank_statement.py
new file mode 100644
index 000000000..72d4e78bb
--- /dev/null
+++ b/account_bank_statement_extend/wizard/parser_report_bank_statement.py
@@ -0,0 +1,171 @@
+# Copyright (C) 2019 - TODAY, Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from odoo import fields, models
+
+
+class BankStatementReport(models.TransientModel):
+    _name = "report.bank.statement"
+
+    def _get_user_id(self):
+        return self.env.uid
+
+    date_from = fields.Date(string="From Date")
+    date_to = fields.Date(string="To Date")
+    user_id = fields.Many2one("res.users", default=_get_user_id)
+
+    def get_bank_statement_report(self):
+
+        return self.env.ref(
+            "account_bank_statement_extend.action_bank_statement_wiz_report"
+        ).report_action(self)
+
+    def get_starting_balance(self):
+        bank_state_ids = self.env["account.bank.statement.line"].search([])
+        starting_balance = 0.0
+        for b_state in bank_state_ids:
+            if b_state.date < self.date_from:
+                starting_balance += b_state.amount
+        return starting_balance
+
+    def get_total_transection_amt(self):
+        bank_state_ids = self.env["account.bank.statement.line"].search([])
+        total_transection = 0.0
+        for b_state in bank_state_ids:
+            if b_state.date >= self.date_from and b_state.date <= self.date_to:
+                total_transection += b_state.amount
+        return total_transection
+
+    def get_ending_balance(self):
+        bank_state_ids = self.env["account.bank.statement.line"].search([])
+        ending_balance = 0.0
+        for b_state in bank_state_ids:
+            if b_state.date <= self.date_to:
+                ending_balance += b_state.amount
+        return ending_balance
+
+    def get_bank_statement_dict(self, line, account_type, lines, b_state):
+        if line.id not in lines and account_type in ["payable", "receivable"]:
+            return {
+                "date": line.date,
+                "account_id": line.account_id.name,
+                "partner_id": line.partner_id.name,
+                "statement_id": b_state.statement_id.name,
+                "move_id": line.move_id.name,
+                "ref": line.ref,
+                "matching_number": line.full_reconcile_id.name,
+                "debit": line.debit,
+                "credit": line.credit,
+            }
+        return None
+
+    def get_bank_state_dict_rec(self, line_rec, lines_ids_journal, rl, b_state):
+        for aml in line_rec:
+            if aml.account_id.user_type_id.type in [
+                "payable",
+                "receivable",
+            ] and aml.move_id.move_type in [
+                "in_invoice",
+                "out_invoice",
+            ]:
+                bank_state_dict = self.get_bank_statement_dict(
+                    aml,
+                    aml.account_id.user_type_id.type,
+                    lines_ids_journal,
+                    b_state,
+                )
+                if bank_state_dict:
+                    rl.append(bank_state_dict)
+                    lines_ids_journal.append(aml.id)
+            else:
+                lines = aml.move_id.line_ids._reconciled_lines()
+                line_rec = self.env["account.move.line"].browse(lines)
+                for line_move in line_rec:
+                    if line_move.account_id.user_type_id.type in [
+                        "payable",
+                        "receivable",
+                    ] and line_move.move_id.move_type in [
+                        "in_invoice",
+                        "out_invoice",
+                    ]:
+                        bank_state_dict = self.get_bank_statement_dict(
+                            line_move,
+                            line_move.account_id.user_type_id.type,
+                            lines_ids_journal,
+                            b_state,
+                        )
+                        if bank_state_dict:
+                            rl.append(bank_state_dict)
+                            lines_ids_journal.append(line_move.id)
+
+    def get_bank_statement_report_data(self):
+        bank_state_ids = self.env["account.bank.statement.line"].search(
+            [("date", ">=", self.date_from), ("date", "<=", self.date_to)]
+        )
+        rec_lines_dict = {}
+        b_line_dict = []
+        lines_ids_journal = []
+        for b_state in bank_state_ids:
+            rl = []
+            rec_lines_dict = {
+                "date": b_state.date,
+                "account_id": None,
+                "partner_id": b_state.partner_id.name,
+                "statement_id": b_state.statement_id.name,
+                "move_id": b_state.move_id.name,
+                "ref": b_state.ref,
+                "matching_number": None,
+            }
+            if b_state.amount >= 0.0:
+                rec_lines_dict.update({"debit": b_state.amount, "credit": 0.0})
+            else:
+                rec_lines_dict.update({"debit": 0.0, "credit": b_state.amount})
+            rl.append(rec_lines_dict)
+            for move_line in b_state.move_id.line_ids:
+                if b_state.amount < 0.0:
+                    if move_line.full_reconcile_id:
+                        move_line = self.env["account.move.line"].search(
+                            [
+                                (
+                                    "full_reconcile_id",
+                                    "=",
+                                    move_line.full_reconcile_id.id,
+                                ),
+                                ("debit", "=", 0.0),
+                            ]
+                        )
+                        for _move in move_line:
+                            move_line = self.env["account.move.line"].browse(
+                                move_line._reconciled_lines()
+                            )
+                            for line in move_line:
+                                lines = line.move_id.line_ids._reconciled_lines()
+                                line_rec = self.env["account.move.line"].browse(lines)
+                                self.get_bank_state_dict_rec(
+                                    line_rec, lines_ids_journal, rl, b_state
+                                )
+                else:
+                    if move_line.full_reconcile_id:
+                        move_line = self.env["account.move.line"].search(
+                            [
+                                (
+                                    "full_reconcile_id",
+                                    "=",
+                                    move_line.full_reconcile_id.id,
+                                ),
+                                ("debit", "!=", 0.0),
+                            ]
+                        )
+                        for _move in move_line:
+                            move_line = self.env["account.move.line"].browse(
+                                move_line._reconciled_lines()
+                            )
+                            for line in move_line:
+                                lines = line.move_id.line_ids._reconciled_lines()
+                                line_rec = self.env["account.move.line"].browse(lines)
+                                self.get_bank_state_dict_rec(
+                                    line_rec, lines_ids_journal, rl, b_state
+                                )
+
+            b_line_dict.append(rl)
+        return b_line_dict
diff --git a/account_bank_statement_extend/wizard/parser_report_bank_statement.xml b/account_bank_statement_extend/wizard/parser_report_bank_statement.xml
new file mode 100644
index 000000000..ffb1d31af
--- /dev/null
+++ b/account_bank_statement_extend/wizard/parser_report_bank_statement.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<odoo>
+
+    <!--From to To Date CS Production Report -->
+    <record model="ir.ui.view" id="view_bank_statement_report_wizard">
+        <field name="name">view.bank.statement.report.wizard.form</field>
+        <field name="model">report.bank.statement</field>
+        <field name="arch" type="xml">
+            <form>
+                <separator
+                    string="Please Choose an Appropriate Option to Get Bank Statement Report"
+                />
+                <group row='2'>
+                    <field name="date_from" required="1" />
+                    <field name="date_to" required="1" />
+                </group>
+                <footer>
+                    <button
+                        name="get_bank_statement_report"
+                        type="object"
+                        string="Get Bank Statement Report"
+                        class="btn-primary"
+                    />
+                    <button string="Cancel" class="oe_link" special="cancel" />
+                </footer>
+            </form>
+        </field>
+    </record>
+
+
+    <!--  Action for Get CS Production Report Wizard -->
+    <record model="ir.actions.act_window" id="action_bank_statement_report_wiz">
+        <field name="name">Bank Statement Report</field>
+        <field name="res_model">report.bank.statement</field>
+        <field name="type">ir.actions.act_window</field>
+        <field name="view_mode">form</field>
+        <field name="view_id" ref="view_bank_statement_report_wizard" />
+        <field name="target">new</field>
+    </record>
+
+    <menuitem
+        id="menu_action_bank_statement_report_wiz"
+        parent="account.menu_finance_payables"
+        action="action_bank_statement_report_wiz"
+    />
+</odoo>
diff --git a/account_report_budget/README.rst b/account_report_budget/README.rst
new file mode 100644
index 000000000..d197305c4
--- /dev/null
+++ b/account_report_budget/README.rst
@@ -0,0 +1,101 @@
+=====================================
+Budget analysis on P&L Finance Report
+=====================================
+
+.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   !! 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-LGPL--3-blue.png
+    :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+    :alt: License: LGPL-3
+.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fosi--addons-lightgray.png?logo=github
+    :target: https://github.com/OCA/osi-addons/tree/14.0/osi_custom_profit_loss
+    :alt: OCA/osi-addons
+.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
+    :target: https://translation.odoo-community.org/projects/osi-addons-14-0/osi-addons-14-0-osi_custom_profit_loss
+    :alt: Translate me on Weblate
+
+|badge1| |badge2| |badge3| |badge4| 
+
+Add budget and variation columns to the P&L report.
+
+**Table of contents**
+
+.. contents::
+   :local:
+
+Usage
+=====
+
+The P&L report is available at Accounting app > Reporting > US GAAP > Profit & Loss.
+
+Data selection options available are:
+
+    * Period: Month, Quarter, Year, etc.
+    * Comparisons: compare to previous periods
+    * Journals
+    * Analytic Account, to filter numbers by a specific segment
+
+The standard report only presents the actual amount.
+
+Two new columns are now available with:
+
+    * Budget amount: sum the values from VALIDATED Budgets, for the Budgetary positions with a name matching the report line account number. If an Analytic Account is selected, it will filter by it.
+    * Variance amount: the difference between the actual amount and the budgeted amount.
+
+Bug Tracker
+===========
+
+Bugs are tracked on `GitHub Issues <https://github.com/OCA/osi-addons/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 <https://github.com/OCA/osi-addons/issues/new?body=module:%20osi_custom_profit_loss%0Aversion:%2014.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
+
+Do not contact contributors directly about support or help with technical issues.
+
+Credits
+=======
+
+Authors
+~~~~~~~
+
+* Open Source Integrators
+
+Contributors
+~~~~~~~~~~~~
+
+* `Open Source Integrators <https://opensourceintegrators.com>`:
+
+    * Daniel Reis <dreis@opensourceintegrators.com>
+    * Chandresh Thakkar <cthakkar@opensourceintegrators.com>
+
+
+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-dreispt| image:: https://github.com/dreispt.png?size=40px
+    :target: https://github.com/dreispt
+    :alt: dreispt
+
+Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
+
+|maintainer-dreispt| 
+
+This module is part of the `OCA/osi-addons <https://github.com/OCA/osi-addons/tree/14.0/osi_custom_profit_loss>`_ project on GitHub.
+
+You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/account_report_budget/__init__.py b/account_report_budget/__init__.py
new file mode 100644
index 000000000..47d2b2851
--- /dev/null
+++ b/account_report_budget/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import models
diff --git a/account_report_budget/__manifest__.py b/account_report_budget/__manifest__.py
new file mode 100644
index 000000000..3485413c3
--- /dev/null
+++ b/account_report_budget/__manifest__.py
@@ -0,0 +1,17 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+{
+    "name": "Budget analysis on P&L Finance Report",
+    "version": "14.0.1.0.0",
+    "summary": "Add budget and variation columns to the P&L report.",
+    "author": "Open Source Integrators",
+    "category": "Accounting/Accounting",
+    "maintainer": "Open Source Integrators",
+    "website": "https://github.com/ursais/osi-addons",
+    "depends": ["account_accountant", "account_budget", "account_reports"],
+    "installable": True,
+    "license": "LGPL-3",
+    "development_status": "Beta",
+    "maintainers": ["dreispt"],
+}
diff --git a/account_report_budget/models/__init__.py b/account_report_budget/models/__init__.py
new file mode 100644
index 000000000..b44865ca4
--- /dev/null
+++ b/account_report_budget/models/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import account_financial_report
diff --git a/account_report_budget/models/account_financial_report.py b/account_report_budget/models/account_financial_report.py
new file mode 100644
index 000000000..c56030760
--- /dev/null
+++ b/account_report_budget/models/account_financial_report.py
@@ -0,0 +1,111 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import api, models
+
+
+class ReportAccountFinancialReport(models.Model):
+    _inherit = "account.financial.html.report"
+
+    filter_all_entries = False
+    filter_hierarchy = True
+
+    @api.model
+    def _build_headers_hierarchy(self, options_list, groupby_keys):
+        headers, sorted_groupby_keys = super(
+            ReportAccountFinancialReport, self
+        )._build_headers_hierarchy(options_list, groupby_keys)
+        if self._context.get("id") == 1 or self.id == 1:
+            headers[0].insert(
+                1, {"name": "Budget Amount", "class": "number", "colspan": 1}
+            )
+            if self._display_growth_comparison(options_list[0]):
+                headers[0].insert(
+                    -1, {"name": "Remaining Amount", "class": "number", "colspan": 1}
+                )
+            else:
+                headers[0].append(
+                    {"name": "Remaining Amount", "class": "number", "colspan": 1}
+                )
+        return headers, sorted_groupby_keys
+
+    @api.model
+    def _get_financial_line_report_line(
+        self, options, financial_line, solver, groupby_keys
+    ):
+        financial_report_line = super(
+            ReportAccountFinancialReport, self
+        )._get_financial_line_report_line(options, financial_line, solver, groupby_keys)
+        if self._context.get("id") == 1 or self.id == 1:
+            financial_report_line["columns"] = [
+                {"name": "", "no_format": "", "class": "number"}
+            ] + financial_report_line.get("columns")
+            if self._display_growth_comparison(options):
+                financial_report_line["columns"].insert(
+                    -1, {"name": "", "no_format": "", "class": "number"}
+                )
+            else:
+                financial_report_line["columns"].append(
+                    {"name": "", "no_format": "", "class": "number"}
+                )
+        return financial_report_line
+
+    @api.model
+    def _get_financial_aml_report_line(
+        self, options, financial_line, groupby_id, display_name, results, groupby_keys
+    ):
+        financial_line_account = super(
+            ReportAccountFinancialReport, self
+        )._get_financial_aml_report_line(
+            options, financial_line, groupby_id, display_name, results, groupby_keys
+        )
+        if self._context.get("id") == 1 or self.id == 1:
+            amount_list = []
+            if financial_line.groupby == "account_id":
+                domain = [
+                    ("general_budget_id.account_ids", "in", [groupby_id]),
+                    ("date_from", ">=", options.get("date").get("date_from")),
+                    ("date_to", "<=", options.get("date").get("date_to")),
+                    ("crossovered_budget_id.state", "in", ["validate"]),
+                ]
+                if options.get("analytic_accounts"):
+                    domain.append(
+                        ("analytic_account_id", "in", options.get("analytic_accounts"))
+                    )
+                crossovered_lines = self.env["crossovered.budget.lines"].search(domain)
+                total_budget = 0
+                for rec in crossovered_lines:
+                    if rec.general_budget_id.account_ids:
+                        amount = rec.planned_amount / len(
+                            rec.general_budget_id.account_ids
+                        )
+                        amount_list.append(amount)
+                total_budget = sum(amount_list)
+                financial_line_account["columns"] = [
+                    {
+                        "name": self._format_cell_value(financial_line, total_budget),
+                        "no_format": total_budget,
+                        "class": "number",
+                    }
+                ] + financial_line_account["columns"]
+                rem_budget = total_budget - abs(
+                    financial_line_account["columns"][1].get("no_format")
+                )
+                if self._display_growth_comparison(options):
+                    financial_line_account["columns"].insert(
+                        -1,
+                        {
+                            "name": self._format_cell_value(financial_line, rem_budget),
+                            "no_format": rem_budget,
+                            "class": "number",
+                        },
+                    )
+                else:
+                    financial_line_account["columns"].append(
+                        {
+                            "name": self._format_cell_value(financial_line, rem_budget),
+                            "no_format": rem_budget,
+                            "class": "number",
+                        }
+                    )
+        return financial_line_account
diff --git a/account_report_budget/readme/CONFIGURATION.rst b/account_report_budget/readme/CONFIGURATION.rst
new file mode 100644
index 000000000..ad8e9fa37
--- /dev/null
+++ b/account_report_budget/readme/CONFIGURATION.rst
@@ -0,0 +1,1 @@
+Budgetary Positions: initial setup needs to be done on the GL Accounts for P&L. The budgetary position names must match the GL Accounts they will be compared to in Financial Reports. For Example "400000 Sales".
diff --git a/account_report_budget/readme/CONTRIBUTORS.rst b/account_report_budget/readme/CONTRIBUTORS.rst
new file mode 100644
index 000000000..a64d47bb1
--- /dev/null
+++ b/account_report_budget/readme/CONTRIBUTORS.rst
@@ -0,0 +1,4 @@
+* `Open Source Integrators <https://opensourceintegrators.com>`:
+
+    * Daniel Reis <dreis@opensourceintegrators.com>
+    * Chandresh Thakkar <cthakkar@opensourceintegrators.com>
diff --git a/account_report_budget/readme/DESCRIPTION.rst b/account_report_budget/readme/DESCRIPTION.rst
new file mode 100644
index 000000000..a0247cf49
--- /dev/null
+++ b/account_report_budget/readme/DESCRIPTION.rst
@@ -0,0 +1,1 @@
+Add budget and variation columns to the P&L report.
diff --git a/account_report_budget/readme/USAGE.rst b/account_report_budget/readme/USAGE.rst
new file mode 100644
index 000000000..0efdef576
--- /dev/null
+++ b/account_report_budget/readme/USAGE.rst
@@ -0,0 +1,15 @@
+The P&L report is available at Accounting app > Reporting > US GAAP > Profit & Loss.
+
+Data selection options available are:
+
+    * Period: Month, Quarter, Year, etc.
+    * Comparisons: compare to previous periods
+    * Journals
+    * Analytic Account, to filter numbers by a specific segment
+
+The standard report only presents the actual amount.
+
+Two new columns are now available with:
+
+    * Budget amount: sum the values from VALIDATED Budgets, for the Budgetary positions with a name matching the report line account number. If an Analytic Account is selected, it will filter by it.
+    * Variance amount: the difference between the actual amount and the budgeted amount.
diff --git a/agreement_helpdesk/README.rst b/agreement_helpdesk/README.rst
new file mode 100644
index 000000000..3e36abe78
--- /dev/null
+++ b/agreement_helpdesk/README.rst
@@ -0,0 +1,35 @@
+.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
+   :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+   :alt: License: LGPL-3
+
+===========================
+Agreement / Helpdesk Ticket
+===========================
+
+Odoo Agreement App does not provide an easy way to access helpdesk tickets
+related to an agreement. Some organizations needs to have a quick access to
+helpdesk tickets to track the performance of an agreement.
+
+This module allows you to link a helpdesk ticket to an agreement and adds a
+smart button on the agreement to look at the list of related helpdesk tickets.
+
+Usage
+=====
+
+* Go to Helpdesk > Tickets
+* Select or create a helpdesk ticket and set the agreement
+* Go to Agreement > Agreements
+* Open the previous agreement
+* Click on the smart button "Tickets" to see the list of related helpdesk tickets
+
+Credits
+=======
+
+* Bhavesh Odedra <bodedra@opensourceintegrators.com>
+* Sandip Mangukiya <smangukiya@opensourceintegrators.com>
+
+Contributors
+------------
+
+* Open Source Integrators <contact@opensourceintegrators.com>
+* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
diff --git a/agreement_helpdesk/__init__.py b/agreement_helpdesk/__init__.py
new file mode 100644
index 000000000..47d2b2851
--- /dev/null
+++ b/agreement_helpdesk/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import models
diff --git a/agreement_helpdesk/__manifest__.py b/agreement_helpdesk/__manifest__.py
new file mode 100644
index 000000000..ab8812cb8
--- /dev/null
+++ b/agreement_helpdesk/__manifest__.py
@@ -0,0 +1,24 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+{
+    "name": "Helpdesk ticket to an agreement",
+    "summary": "Link a helpdesk ticket to an agreement",
+    "version": "14.0.1.0.0",
+    "license": "LGPL-3",
+    "author": "Open Source Integrators",
+    "category": "Helpdesk",
+    "website": "https://github.com/ursais/osi-addons",
+    "depends": [
+        "helpdesk",
+        "agreement_serviceprofile",
+    ],
+    "maintainers": [
+        "",
+    ],
+    "data": [
+        "views/helpdesk_ticket_view.xml",
+        "views/agreement_view.xml",
+    ],
+    "installable": True,
+}
diff --git a/agreement_helpdesk/models/__init__.py b/agreement_helpdesk/models/__init__.py
new file mode 100644
index 000000000..4fcc117f8
--- /dev/null
+++ b/agreement_helpdesk/models/__init__.py
@@ -0,0 +1,5 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import helpdesk_ticket
+from . import agreement
diff --git a/agreement_helpdesk/models/agreement.py b/agreement_helpdesk/models/agreement.py
new file mode 100644
index 000000000..d9123ef8d
--- /dev/null
+++ b/agreement_helpdesk/models/agreement.py
@@ -0,0 +1,32 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import fields, models
+
+
+class Agreement(models.Model):
+    _inherit = "agreement"
+
+    def _compute_ticket_count(self):
+        for agreement in self:
+            agreement.ticket_count = self.env["helpdesk.ticket"].search_count(
+                [("agreement_id", "=", agreement.id)]
+            )
+
+    ticket_count = fields.Integer(compute="_compute_ticket_count", string="# Tickets")
+
+    def action_view_ticket(self):
+        for agreement in self:
+            ticket_ids = self.env["helpdesk.ticket"].search(
+                [("agreement_id", "=", agreement.id)]
+            )
+            action = self.env.ref("helpdesk.helpdesk_ticket_action_main_tree").read()[0]
+            action["context"] = {}
+            if len(ticket_ids) == 1:
+                action["views"] = [
+                    (self.env.ref("helpdesk.helpdesk_ticket_view_form").id, "form")
+                ]
+                action["res_id"] = ticket_ids.ids[0]
+            else:
+                action["domain"] = [("id", "in", ticket_ids.ids)]
+            return action
diff --git a/agreement_helpdesk/models/helpdesk_ticket.py b/agreement_helpdesk/models/helpdesk_ticket.py
new file mode 100644
index 000000000..0d08d6274
--- /dev/null
+++ b/agreement_helpdesk/models/helpdesk_ticket.py
@@ -0,0 +1,14 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import fields, models
+
+
+class HelpdeskTicket(models.Model):
+    _inherit = "helpdesk.ticket"
+
+    agreement_id = fields.Many2one(
+        "agreement",
+        string="Agreement",
+    )
+    serviceprofile_id = fields.Many2one("agreement.serviceprofile", "Service Profile")
diff --git a/agreement_helpdesk/static/description/icon.png b/agreement_helpdesk/static/description/icon.png
new file mode 100644
index 000000000..84791119f
Binary files /dev/null and b/agreement_helpdesk/static/description/icon.png differ
diff --git a/agreement_helpdesk/views/agreement_view.xml b/agreement_helpdesk/views/agreement_view.xml
new file mode 100644
index 000000000..2cfb9b90c
--- /dev/null
+++ b/agreement_helpdesk/views/agreement_view.xml
@@ -0,0 +1,29 @@
+<odoo>
+
+    <!-- Agreement Form View -->
+    <record id="agreement_tickets_form_view" model="ir.ui.view">
+        <field name="name">agreement.form.view</field>
+        <field name="model">agreement</field>
+        <field
+            name="inherit_id"
+            ref="agreement_legal.partner_agreement_form_view"
+        />
+        <field name="arch" type="xml">
+            <div class="oe_button_box" position="inside">
+                <button
+                    name="action_view_ticket"
+                    type="object"
+                    class="oe_stat_button"
+                    icon="fa-pencil-square-o"
+                >
+                    <field
+                        name="ticket_count"
+                        widget="statinfo"
+                        string="Tickets"
+                    />
+                </button>
+            </div>
+        </field>
+    </record>
+
+</odoo>
diff --git a/agreement_helpdesk/views/helpdesk_ticket_view.xml b/agreement_helpdesk/views/helpdesk_ticket_view.xml
new file mode 100644
index 000000000..8c0e9f39e
--- /dev/null
+++ b/agreement_helpdesk/views/helpdesk_ticket_view.xml
@@ -0,0 +1,40 @@
+<odoo>
+
+    <!-- Helpdesk Ticket Form View -->
+    <record id="helpdesk_ticket_view_agreement_form" model="ir.ui.view">
+        <field name="name">helpdesk.ticket.agreement.form</field>
+        <field name="model">helpdesk.ticket</field>
+        <field name="inherit_id" ref="helpdesk.helpdesk_ticket_view_form" />
+        <field name="arch" type="xml">
+            <field name="partner_id" position="after">
+                <field
+                    name="agreement_id"
+                    domain="[('partner_id', '=', partner_id)]"
+                    widget="selection"
+                />
+                <field
+                    name="serviceprofile_id"
+                    domain="[('agreement_id', '=', agreement_id)]"
+                    widget="selection"
+                />
+            </field>
+        </field>
+    </record>
+
+    <!-- Inherit helpdesk.ticket search view-->
+    <record id="helpdesk_tickets_view_search_agreement" model="ir.ui.view">
+        <field name="name">helpdesk.ticket.select.agreement</field>
+        <field name="model">helpdesk.ticket</field>
+        <field name="inherit_id" ref="helpdesk.helpdesk_tickets_view_search" />
+        <field name="arch" type="xml">
+            <xpath expr="//group" position="inside">
+                <filter
+                    string="Service Profile"
+                    name="serviceprofile_id"
+                    domain="[]"
+                    context="{'group_by':'serviceprofile_id'}"
+                />
+            </xpath>
+        </field>
+    </record>
+</odoo>
diff --git a/agreement_rma/README.rst b/agreement_rma/README.rst
new file mode 100644
index 000000000..b1e7899c3
--- /dev/null
+++ b/agreement_rma/README.rst
@@ -0,0 +1,41 @@
+.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
+   :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
+   :alt: License: AGPL-3
+
+===============
+Agreement / RMA
+===============
+
+Odoo Agreement App does not provide an easy way to access RMAs related to an agreement.
+Some organizations needs to have a quick access to RMAs to track the performance of an agreement.
+
+This module allows you to link a RMA to an agreement and adds a smart button
+on the agreement to look at the list of related RMAs.
+
+Installation
+============
+
+You need to have the rma modules from https://github.com/eficent/stock-rma in
+your addons_path.
+
+Usage
+=====
+
+To use this module, you need to:
+
+* Go to Inventory > Customer RMA > RMA
+* Select or create a RMA and set the agreement
+* Go to Agreement > Agreements
+* Open the previous agreement
+* Click on the smart button "RMA Orders" to see the list of related RMA Orders
+
+Credits
+=======
+
+* Sandip Mangukiya <smangukiya@opensourceintegrators.com>
+
+Contributors
+------------
+
+* Open Source Integrators <contact@opensourceintegrators.com>
+* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
diff --git a/agreement_rma/__init__.py b/agreement_rma/__init__.py
new file mode 100644
index 000000000..1ae95437a
--- /dev/null
+++ b/agreement_rma/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from . import models
diff --git a/agreement_rma/__manifest__.py b/agreement_rma/__manifest__.py
new file mode 100644
index 000000000..b4b0ac95e
--- /dev/null
+++ b/agreement_rma/__manifest__.py
@@ -0,0 +1,26 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+{
+    "name": "Agreement - RMA",
+    "summary": "Link rma orders to an agreement",
+    "version": "14.0.1.0.0",
+    "category": "Contract",
+    "author": "Open Source Integrators, " "Odoo Community Association (OCA)",
+    "website": "https://github.com/ursais/osi-addons",
+    "depends": [
+        "agreement_serviceprofile",
+        "rma",
+    ],
+    "data": [
+        "views/agreement_view.xml",
+        "views/rma_view.xml",
+    ],
+    "installable": True,
+    "license": "AGPL-3",
+    "development_status": "Beta",
+    "maintainers": [
+        "smangukiya",
+        "max3903",
+    ],
+}
diff --git a/agreement_rma/models/__init__.py b/agreement_rma/models/__init__.py
new file mode 100644
index 000000000..c8d519aa6
--- /dev/null
+++ b/agreement_rma/models/__init__.py
@@ -0,0 +1,7 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from . import (
+    rma,
+    agreement,
+)
diff --git a/agreement_rma/models/agreement.py b/agreement_rma/models/agreement.py
new file mode 100644
index 000000000..b16ea9cad
--- /dev/null
+++ b/agreement_rma/models/agreement.py
@@ -0,0 +1,16 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from odoo import fields, models
+
+
+class Agreement(models.Model):
+    _inherit = "agreement"
+
+    rma_count = fields.Integer("# RMA Orders", compute="_compute_rma_count")
+
+    def _compute_rma_count(self):
+        for ag_rec in self:
+            ag_rec.rma_count = self.env["rma.order.line"].search_count(
+                [("agreement_id", "in", ag_rec.ids)]
+            )
diff --git a/agreement_rma/models/rma.py b/agreement_rma/models/rma.py
new file mode 100644
index 000000000..49493496b
--- /dev/null
+++ b/agreement_rma/models/rma.py
@@ -0,0 +1,19 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from odoo import api, fields, models
+
+
+class RMAOrderLine(models.Model):
+    _inherit = "rma.order.line"
+
+    agreement_id = fields.Many2one("agreement", "Agreement")
+    serviceprofile_id = fields.Many2one("agreement.serviceprofile", "Service Profile")
+
+    @api.onchange("partner_id")
+    def _onchange_partner(self):
+        self.agreement_id = False
+
+    @api.onchange("agreement_id")
+    def _onchange_agreement(self):
+        self.serviceprofile_id = False
diff --git a/agreement_rma/static/description/icon.png b/agreement_rma/static/description/icon.png
new file mode 100644
index 000000000..23ce93135
Binary files /dev/null and b/agreement_rma/static/description/icon.png differ
diff --git a/agreement_rma/static/description/index.html b/agreement_rma/static/description/index.html
new file mode 100644
index 000000000..5ede63176
--- /dev/null
+++ b/agreement_rma/static/description/index.html
@@ -0,0 +1,460 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.14: http://docutils.sourceforge.net/" />
+<title>Agreement - MRP</title>
+<style type="text/css">
+
+/*
+:Author: David Goodger (goodger@python.org)
+:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
+:Copyright: This stylesheet has been placed in the public domain.
+
+Default cascading style sheet for the HTML output of Docutils.
+
+See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
+customize this style sheet.
+*/
+
+/* used to remove borders from tables and images */
+.borderless, table.borderless td, table.borderless th {
+  border: 0 }
+
+table.borderless td, table.borderless th {
+  /* Override padding for "table.docutils td" with "! important".
+     The right padding separates the table cells. */
+  padding: 0 0.5em 0 0 ! important }
+
+.first {
+  /* Override more specific margin styles with "! important". */
+  margin-top: 0 ! important }
+
+.last, .with-subtitle {
+  margin-bottom: 0 ! important }
+
+.hidden {
+  display: none }
+
+.subscript {
+  vertical-align: sub;
+  font-size: smaller }
+
+.superscript {
+  vertical-align: super;
+  font-size: smaller }
+
+a.toc-backref {
+  text-decoration: none ;
+  color: black }
+
+blockquote.epigraph {
+  margin: 2em 5em ; }
+
+dl.docutils dd {
+  margin-bottom: 0.5em }
+
+object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
+  overflow: hidden;
+}
+
+/* Uncomment (and remove this text!) to get bold-faced definition list terms
+dl.docutils dt {
+  font-weight: bold }
+*/
+
+div.abstract {
+  margin: 2em 5em }
+
+div.abstract p.topic-title {
+  font-weight: bold ;
+  text-align: center }
+
+div.admonition, div.attention, div.caution, div.danger, div.error,
+div.hint, div.important, div.note, div.tip, div.warning {
+  margin: 2em ;
+  border: medium outset ;
+  padding: 1em }
+
+div.admonition p.admonition-title, div.hint p.admonition-title,
+div.important p.admonition-title, div.note p.admonition-title,
+div.tip p.admonition-title {
+  font-weight: bold ;
+  font-family: sans-serif }
+
+div.attention p.admonition-title, div.caution p.admonition-title,
+div.danger p.admonition-title, div.error p.admonition-title,
+div.warning p.admonition-title, .code .error {
+  color: red ;
+  font-weight: bold ;
+  font-family: sans-serif }
+
+/* Uncomment (and remove this text!) to get reduced vertical space in
+   compound paragraphs.
+div.compound .compound-first, div.compound .compound-middle {
+  margin-bottom: 0.5em }
+
+div.compound .compound-last, div.compound .compound-middle {
+  margin-top: 0.5em }
+*/
+
+div.dedication {
+  margin: 2em 5em ;
+  text-align: center ;
+  font-style: italic }
+
+div.dedication p.topic-title {
+  font-weight: bold ;
+  font-style: normal }
+
+div.figure {
+  margin-left: 2em ;
+  margin-right: 2em }
+
+div.footer, div.header {
+  clear: both;
+  font-size: smaller }
+
+div.line-block {
+  display: block ;
+  margin-top: 1em ;
+  margin-bottom: 1em }
+
+div.line-block div.line-block {
+  margin-top: 0 ;
+  margin-bottom: 0 ;
+  margin-left: 1.5em }
+
+div.sidebar {
+  margin: 0 0 0.5em 1em ;
+  border: medium outset ;
+  padding: 1em ;
+  background-color: #ffffee ;
+  width: 40% ;
+  float: right ;
+  clear: right }
+
+div.sidebar p.rubric {
+  font-family: sans-serif ;
+  font-size: medium }
+
+div.system-messages {
+  margin: 5em }
+
+div.system-messages h1 {
+  color: red }
+
+div.system-message {
+  border: medium outset ;
+  padding: 1em }
+
+div.system-message p.system-message-title {
+  color: red ;
+  font-weight: bold }
+
+div.topic {
+  margin: 2em }
+
+h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
+h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
+  margin-top: 0.4em }
+
+h1.title {
+  text-align: center }
+
+h2.subtitle {
+  text-align: center }
+
+hr.docutils {
+  width: 75% }
+
+img.align-left, .figure.align-left, object.align-left, table.align-left {
+  clear: left ;
+  float: left ;
+  margin-right: 1em }
+
+img.align-right, .figure.align-right, object.align-right, table.align-right {
+  clear: right ;
+  float: right ;
+  margin-left: 1em }
+
+img.align-center, .figure.align-center, object.align-center {
+  display: block;
+  margin-left: auto;
+  margin-right: auto;
+}
+
+table.align-center {
+  margin-left: auto;
+  margin-right: auto;
+}
+
+.align-left {
+  text-align: left }
+
+.align-center {
+  clear: both ;
+  text-align: center }
+
+.align-right {
+  text-align: right }
+
+/* reset inner alignment in figures */
+div.align-right {
+  text-align: inherit }
+
+/* div.align-center * { */
+/*   text-align: left } */
+
+.align-top    {
+  vertical-align: top }
+
+.align-middle {
+  vertical-align: middle }
+
+.align-bottom {
+  vertical-align: bottom }
+
+ol.simple, ul.simple {
+  margin-bottom: 1em }
+
+ol.arabic {
+  list-style: decimal }
+
+ol.loweralpha {
+  list-style: lower-alpha }
+
+ol.upperalpha {
+  list-style: upper-alpha }
+
+ol.lowerroman {
+  list-style: lower-roman }
+
+ol.upperroman {
+  list-style: upper-roman }
+
+p.attribution {
+  text-align: right ;
+  margin-left: 50% }
+
+p.caption {
+  font-style: italic }
+
+p.credits {
+  font-style: italic ;
+  font-size: smaller }
+
+p.label {
+  white-space: nowrap }
+
+p.rubric {
+  font-weight: bold ;
+  font-size: larger ;
+  color: maroon ;
+  text-align: center }
+
+p.sidebar-title {
+  font-family: sans-serif ;
+  font-weight: bold ;
+  font-size: larger }
+
+p.sidebar-subtitle {
+  font-family: sans-serif ;
+  font-weight: bold }
+
+p.topic-title {
+  font-weight: bold }
+
+pre.address {
+  margin-bottom: 0 ;
+  margin-top: 0 ;
+  font: inherit }
+
+pre.literal-block, pre.doctest-block, pre.math, pre.code {
+  margin-left: 2em ;
+  margin-right: 2em }
+
+pre.code .ln { color: grey; } /* line numbers */
+pre.code, code { background-color: #eeeeee }
+pre.code .comment, code .comment { color: #5C6576 }
+pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
+pre.code .literal.string, code .literal.string { color: #0C5404 }
+pre.code .name.builtin, code .name.builtin { color: #352B84 }
+pre.code .deleted, code .deleted { background-color: #DEB0A1}
+pre.code .inserted, code .inserted { background-color: #A3D289}
+
+span.classifier {
+  font-family: sans-serif ;
+  font-style: oblique }
+
+span.classifier-delimiter {
+  font-family: sans-serif ;
+  font-weight: bold }
+
+span.interpreted {
+  font-family: sans-serif }
+
+span.option {
+  white-space: nowrap }
+
+span.pre {
+  white-space: pre }
+
+span.problematic {
+  color: red }
+
+span.section-subtitle {
+  /* font-size relative to parent (h1..h6 element) */
+  font-size: 80% }
+
+table.citation {
+  border-left: solid 1px gray;
+  margin-left: 1px }
+
+table.docinfo {
+  margin: 2em 4em }
+
+table.docutils {
+  margin-top: 0.5em ;
+  margin-bottom: 0.5em }
+
+table.footnote {
+  border-left: solid 1px black;
+  margin-left: 1px }
+
+table.docutils td, table.docutils th,
+table.docinfo td, table.docinfo th {
+  padding-left: 0.5em ;
+  padding-right: 0.5em ;
+  vertical-align: top }
+
+table.docutils th.field-name, table.docinfo th.docinfo-name {
+  font-weight: bold ;
+  text-align: left ;
+  white-space: nowrap ;
+  padding-left: 0 }
+
+/* "booktabs" style (no vertical lines) */
+table.docutils.booktabs {
+  border: 0px;
+  border-top: 2px solid;
+  border-bottom: 2px solid;
+  border-collapse: collapse;
+}
+table.docutils.booktabs * {
+  border: 0px;
+}
+table.docutils.booktabs th {
+  border-bottom: thin solid;
+  text-align: left;
+}
+
+h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
+h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
+  font-size: 100% }
+
+ul.auto-toc {
+  list-style-type: none }
+
+</style>
+</head>
+<body>
+<div class="document" id="agreement-mrp">
+<h1 class="title">Agreement - MRP</h1>
+
+<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!! This file is generated by oca-gen-addon-readme !!
+!! changes will be overwritten.                   !!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
+<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/contract/tree/12.0/agreement_mrp"><img alt="OCA/contract" src="https://img.shields.io/badge/github-OCA%2Fcontract-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/contract-12-0/contract-12-0-agreement_mrp"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/110/12.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
+<p>Odoo Agreement App does not provide an easy way to access manufacturing orders
+related to an agreement. Some organizations needs to have a quick access to the
+production orders to track the performance of an agreement.</p>
+<p>This module allows you to link a manufacturing order to an agreement and
+adds a smart button on the agreement to look at the list of related MOs.</p>
+<p><strong>Table of contents</strong></p>
+<div class="contents local topic" id="contents">
+<ul class="simple">
+<li><a class="reference internal" href="#installation" id="id1">Installation</a></li>
+<li><a class="reference internal" href="#usage" id="id2">Usage</a></li>
+<li><a class="reference internal" href="#known-issues-roadmap" id="id3">Known issues / Roadmap</a></li>
+<li><a class="reference internal" href="#bug-tracker" id="id4">Bug Tracker</a></li>
+<li><a class="reference internal" href="#credits" id="id5">Credits</a><ul>
+<li><a class="reference internal" href="#authors" id="id6">Authors</a></li>
+<li><a class="reference internal" href="#contributors" id="id7">Contributors</a></li>
+<li><a class="reference internal" href="#other-credits" id="id8">Other credits</a></li>
+<li><a class="reference internal" href="#maintainers" id="id9">Maintainers</a></li>
+</ul>
+</li>
+</ul>
+</div>
+<div class="section" id="installation">
+<h1><a class="toc-backref" href="#id1">Installation</a></h1>
+<p>To install Field Service and have the mapping features,
+you need to install agreement and mrp</p>
+<p>Please refer to the installation instructions available at:
+<a class="reference external" href="https://github.com/OCA/contract/agreement_mrp">https://github.com/OCA/contract/agreement_mrp</a></p>
+</div>
+<div class="section" id="usage">
+<h1><a class="toc-backref" href="#id2">Usage</a></h1>
+<p>To use this module, you need to:</p>
+<ul class="simple">
+<li>Go to Inventory > Customer RMA > RMA</li>
+<li>Select or create a RMA and set the agreement</li>
+<li>Go to Agreement > Agreements</li>
+<li>Open the previous agreement</li>
+<li>Click on the smart button "RMA Orders" to see the list of related RMA Orders</li>
+</ul>
+</div>
+<div class="section" id="known-issues-roadmap">
+<h1><a class="toc-backref" href="#id3">Known issues / Roadmap</a></h1>
+<p>The roadmap of the Field Service application is documented on
+<a class="reference external" href="https://github.com/OCA/contract/issues/221">Github</a>.</p>
+</div>
+<div class="section" id="bug-tracker">
+<h1><a class="toc-backref" href="#id4">Bug Tracker</a></h1>
+<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/contract/issues">GitHub Issues</a>.
+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
+<a class="reference external" href="https://github.com/OCA/contract/issues/new?body=module:%20agreement_mrp%0Aversion:%2011.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
+<p>Do not contact contributors directly about support or help with technical issues.</p>
+</div>
+<div class="section" id="credits">
+<h1><a class="toc-backref" href="#id5">Credits</a></h1>
+<div class="section" id="authors">
+<h2><a class="toc-backref" href="#id6">Authors</a></h2>
+<ul class="simple">
+<li>Open Source Integrators</li>
+</ul>
+</div>
+<div class="section" id="contributors">
+<h2><a class="toc-backref" href="#id7">Contributors</a></h2>
+<ul class="simple">
+<li>Sandip Mangukiya <<a class="reference external" href="mailto:smangukiya&#64;opensourceintegrators.com">smangukiya&#64;opensourceintegrators.com</a>></li>
+<li>Serpent Consulting Services Pvt. Ltd. &lt;<a class="reference external" href="mailto:support&#64;serpentcs.com">support&#64;serpentcs.com</a>&gt;</li>
+</ul>
+</div>
+<div class="section" id="other-credits">
+<h2><a class="toc-backref" href="#id8">Other credits</a></h2>
+<p>The development of this module has been financially supported by:</p>
+<ul class="simple">
+<li>Open Source Integrators &lt;<a class="reference external" href="https://opensourceintegrators.com">https://opensourceintegrators.com</a>&gt;</li>
+</ul>
+</div>
+<div class="section" id="maintainers">
+<h2><a class="toc-backref" href="#id9">Maintainers</a></h2>
+<p>This module is maintained by the OCA.</p>
+<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
+<p>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.</p>
+<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainers</a>:</p>
+<p><a class="reference external" href="https://github.com/smangukiya"><img alt="smangukiya" src="https://github.com/smangukiya.png?size=40px" /></a> <a class="reference external" href="https://github.com/max3903"><img alt="max3903" src="https://github.com/max3903.png?size=40px" /></a></p>
+<p>This module is part of the <a class="reference external" href="https://github.com/OCA/contract/tree/12.0/agreement_mrp">OCA/contract</a> project on GitHub.</p>
+<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
+</div>
+</div>
+</div>
+</body>
+</html>
diff --git a/agreement_rma/views/agreement_view.xml b/agreement_rma/views/agreement_view.xml
new file mode 100644
index 000000000..ca2970274
--- /dev/null
+++ b/agreement_rma/views/agreement_view.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<odoo>
+
+    <record
+        id="action_rma_order_line_agreement_specific"
+        model="ir.actions.act_window"
+    >
+        <field name="name">RMA Order Lines</field>
+        <field name="type">ir.actions.act_window</field>
+        <field name="res_model">rma.order.line</field>
+        <field name="view_mode">tree,form</field>
+        <field name="domain">[('agreement_id', '=', active_id)]</field>
+        <field name="context">{'create': False, 'edit': False}</field>
+        <field name="help" type="html">
+            <p class="oe_view_nocontent_create">
+                Create RMA Orders Lines
+            </p>
+        </field>
+    </record>
+
+    <record id="partner_agreement_form_view_rma" model="ir.ui.view">
+        <field name="name">agreement.form.rma</field>
+        <field name="model">agreement</field>
+        <field
+            name="inherit_id"
+            ref="agreement_legal.partner_agreement_form_view"
+        />
+        <field name="arch" type="xml">
+            <xpath expr="//div[@name='button_box']" position="inside">
+                <button
+                    name="%(action_rma_order_line_agreement_specific)d"
+                    type="action"
+                    class="oe_stat_button"
+                    icon="fa-link"
+                >
+                    <div class="o_field_widget o_stat_info">
+                        <span class="o_stat_value">
+                            <field
+                                name="rma_count"
+                                widget="statinfo"
+                                nolabel="1"
+                            />
+                        </span>
+                        <span class="o_stat_text">RMA Orders</span>
+                    </div>
+                </button>
+            </xpath>
+        </field>
+    </record>
+
+</odoo>
diff --git a/agreement_rma/views/rma_view.xml b/agreement_rma/views/rma_view.xml
new file mode 100644
index 000000000..5c3d495bf
--- /dev/null
+++ b/agreement_rma/views/rma_view.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<odoo>
+
+    <record id="view_rma_line_form_agreement" model="ir.ui.view">
+        <field name="name">rma.order.line.agreement</field>
+        <field name="model">rma.order.line</field>
+        <field name="inherit_id" ref="rma.view_rma_line_form" />
+        <field name="arch" type="xml">
+            <xpath expr="//field[@name='partner_id']" position="after">
+                <field
+                    name="agreement_id"
+                    domain="[('partner_id', '=', partner_id)]"
+                    options="{'no_create': True, 'no_open': True}"
+                />
+                <field
+                    name="serviceprofile_id"
+                    domain="[('agreement_id', '=', agreement_id)]"
+                    options="{'no_create': True, 'no_open': True}"
+                />
+            </xpath>
+        </field>
+    </record>
+
+    <!-- Inherit mrp repair search view-->
+    <record id="view_rma_rma_line_filter_agreement" model="ir.ui.view">
+        <field name="name">rma.order.line.select.agreement</field>
+        <field name="model">rma.order.line</field>
+        <field name="inherit_id" ref="rma.view_rma_rma_line_filter" />
+        <field name="arch" type="xml">
+            <xpath expr="//group" position="inside">
+                <filter
+                    string="Service Profile"
+                    name="serviceprofile_id"
+                    domain="[]"
+                    context="{'group_by':'serviceprofile_id'}"
+                />
+            </xpath>
+        </field>
+    </record>
+
+</odoo>
diff --git a/documents_helpdesk/README.rst b/documents_helpdesk/README.rst
new file mode 100644
index 000000000..cfd1ca321
--- /dev/null
+++ b/documents_helpdesk/README.rst
@@ -0,0 +1,95 @@
+=====================
+Documents - Help Desk
+=====================
+
+.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   !! 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-LGPL--3-blue.png
+    :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+    :alt: License: AGPL-3
+.. |badge3| image:: https://img.shields.io/badge/github-ursais%2Fosi--addons-lightgray.png?logo=github
+    :target: https://github.com/ursais/osi-addons/tree/14.0/documents_helpdesk
+    :alt: ursais/osi-addons
+
+|badge1| |badge2| |badge3|
+
+This module allows you to manage Help Desk documents in the Documents app.
+
+**Table of contents**
+
+.. contents::
+   :local:
+
+Configuration
+=============
+
+#. Go to Documents
+#. Activate the Helpdesk
+#. Configure the folder and the tags
+
+Usage
+=====
+
+To use this module, you need to:
+
+#. Go to Helpdesk
+#. Create or select a ticket
+#. Add an attachment
+
+Bug Tracker
+===========
+
+Bugs are tracked on `GitHub Issues <https://github.com/ursais/osi-addons/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 <https://github.com/ursais/osi-addons/issues/new?body=module:%20documents_helpdesk%0Aversion:%2014.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
+
+Credits
+=======
+
+Authors
+~~~~~~~
+
+* Open Source Integrators
+
+Contributors
+~~~~~~~~~~~~
+
+* Maxime Chambreuil <mchambreuil@opensourceintegrators.com>
+
+Other credits
+~~~~~~~~~~~~~
+
+The development of this module has been financially supported by:
+
+* Open Source Integrators <https://www.opensourceintegrators.com>
+
+Maintainers
+~~~~~~~~~~~
+
+This module is maintained by Open Source Integrators.
+
+.. image:: https://github.com/ursais.png
+   :alt: Open Source Integrators
+   :target: https://opensourceintegrators.com
+
+Open Source Integrators™ (OSI) provides customers a unique combination of open source
+business process consulting and implementations.
+
+.. |maintainer-max3903| image:: https://github.com/max3903.png?size=40px
+    :target: https://github.com/max3903
+    :alt: max3903
+
+Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
+
+|maintainer-max3903|
+
+This module is part of the `ursais/osi-addons <https://github.com/ursais/osi-addons/tree/14.0/documents_helpdesk>`_ project on GitHub.
+
+You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/documents_helpdesk/__init__.py b/documents_helpdesk/__init__.py
new file mode 100644
index 000000000..708e164fd
--- /dev/null
+++ b/documents_helpdesk/__init__.py
@@ -0,0 +1,3 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from . import models
diff --git a/documents_helpdesk/__manifest__.py b/documents_helpdesk/__manifest__.py
new file mode 100644
index 000000000..ef4d61417
--- /dev/null
+++ b/documents_helpdesk/__manifest__.py
@@ -0,0 +1,21 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+{
+    "name": "Documents for Helpdesk",
+    "version": "14.0.1.0.0",
+    "category": "Documents",
+    "summary": """Manage Helpdesk documents""",
+    "website": "https://github.com/ursais/osi-addons",
+    "author": "Open Source Integrators",
+    "license": "LGPL-3",
+    "depends": ["documents", "helpdesk"],
+    "data": [
+        "data/documents_folder.xml",
+        "data/documents_facet.xml",
+        "data/res_company.xml",
+        "data/documents_workflow_rule.xml",
+        "views/res_config_settings.xml",
+    ],
+    "development_status": "Beta",
+    "maintainers": ["max3903"],
+}
diff --git a/documents_helpdesk/data/documents_facet.xml b/documents_helpdesk/data/documents_facet.xml
new file mode 100644
index 000000000..73294ac10
--- /dev/null
+++ b/documents_helpdesk/data/documents_facet.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" ?>
+<odoo noupdate="1">
+
+    <record
+        id="documents_facet_helpdesk"
+        model="documents.facet"
+        forcecreate="0"
+    >
+        <field name="name">Helpdesk</field>
+        <field name="sequence">6</field>
+        <field name="folder_id" ref="documents_folder_helpdesk" />
+    </record>
+
+</odoo>
diff --git a/documents_helpdesk/data/documents_folder.xml b/documents_helpdesk/data/documents_folder.xml
new file mode 100644
index 000000000..8141ee487
--- /dev/null
+++ b/documents_helpdesk/data/documents_folder.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" ?>
+<odoo noupdate="1">
+
+    <record
+        id="documents_folder_helpdesk"
+        model="documents.folder"
+        forcecreate="0"
+    >
+        <field name="name">Helpdesk</field>
+        <field name="group_ids" eval="[(4, ref('base.group_user'))]" />
+        <field name="read_group_ids" eval="[(4, ref('base.group_user'))]" />
+        <field name="user_specific">True</field>
+        <field name="sequence">12</field>
+    </record>
+
+</odoo>
diff --git a/documents_helpdesk/data/documents_workflow_rule.xml b/documents_helpdesk/data/documents_workflow_rule.xml
new file mode 100644
index 000000000..587b5293b
--- /dev/null
+++ b/documents_helpdesk/data/documents_workflow_rule.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" ?>
+<odoo noupdate="1">
+
+    <record
+        id="documents_workflow_rule_helpdesk"
+        model="documents.workflow.rule"
+        forcecreate="0"
+    >
+        <field name="name">Create Ticket</field>
+        <field name="domain_folder_id" ref="documents_folder_helpdesk" />
+        <field name="condition_type">criteria</field>
+        <field name="create_model">helpdesk.ticket</field>
+    </record>
+
+</odoo>
diff --git a/documents_helpdesk/data/res_company.xml b/documents_helpdesk/data/res_company.xml
new file mode 100644
index 000000000..b23ab76a0
--- /dev/null
+++ b/documents_helpdesk/data/res_company.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" ?>
+<odoo noupdate="1">
+
+    <record id="base.main_company" model="res.company">
+        <field name="helpdesk_folder" ref="documents_folder_helpdesk" />
+    </record>
+
+</odoo>
diff --git a/documents_helpdesk/models/__init__.py b/documents_helpdesk/models/__init__.py
new file mode 100644
index 000000000..03ffe23a4
--- /dev/null
+++ b/documents_helpdesk/models/__init__.py
@@ -0,0 +1,8 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from . import (
+    res_company,
+    res_config_settings,
+    helpdesk_ticket,
+    documents_workflow_rule,
+)
diff --git a/documents_helpdesk/models/documents_workflow_rule.py b/documents_helpdesk/models/documents_workflow_rule.py
new file mode 100644
index 000000000..a7dfadc06
--- /dev/null
+++ b/documents_helpdesk/models/documents_workflow_rule.py
@@ -0,0 +1,55 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from odoo import fields, models
+
+
+class DocumentsWorkflowRule(models.Model):
+    _inherit = ["documents.workflow.rule"]
+
+    def _compute_business(self):
+        return self._get_business()
+
+    has_business_option = fields.Boolean(default=True, compute="_compute_business")
+    create_model = fields.Selection(
+        selection_add=[("helpdesk.ticket", "Helpdesk Ticket")]
+    )
+
+    def create_record(self, documents=None):
+        res = super(DocumentsWorkflowRule, self).create_record(documents=documents)
+        if self.create_model == "helpdesk.ticket":
+            ticket = self.env[self.create_model].create(
+                {
+                    "name": "Ticket created from Documents",
+                    "team_id": self.env.ref("helpdesk.helpdesk_team1").id,
+                }
+            )
+
+            for document in documents:
+                # this_document is the document in use for the workflow
+                this_document = document
+                if (
+                    document.res_model or document.res_id
+                ) and document.res_model != "documents.document":
+                    attachment_copy = document.attachment_id.with_context(
+                        no_document=True
+                    ).copy()
+                    this_document = document.copy({"attachment_id": attachment_copy.id})
+                this_document.write(
+                    {
+                        "res_model": ticket._name,
+                        "res_id": ticket.id,
+                    }
+                )
+
+            view_id = self.env.ref("helpdesk.helpdesk_ticket_view_form").id
+            return {
+                "type": "ir.actions.act_window",
+                "res_model": "helpdesk.ticket",
+                "name": "New helpdesk ticket",
+                "context": self._context,
+                "view_mode": "form",
+                "views": [(view_id, "form")],
+                "res_id": ticket.id if ticket else False,
+                "view_id": view_id,
+            }
+        return res
diff --git a/documents_helpdesk/models/helpdesk_ticket.py b/documents_helpdesk/models/helpdesk_ticket.py
new file mode 100644
index 000000000..e65182efb
--- /dev/null
+++ b/documents_helpdesk/models/helpdesk_ticket.py
@@ -0,0 +1,11 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from odoo import models
+
+
+class HelpdeskTicket(models.Model):
+    _name = "helpdesk.ticket"
+    _inherit = ["helpdesk.ticket", "documents.mixin"]
+
+    def _get_document_folder(self):
+        return self.company_id.helpdesk_folder
diff --git a/documents_helpdesk/models/res_company.py b/documents_helpdesk/models/res_company.py
new file mode 100644
index 000000000..acaef4a16
--- /dev/null
+++ b/documents_helpdesk/models/res_company.py
@@ -0,0 +1,25 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from odoo import fields, models
+
+
+class ResCompany(models.Model):
+    _inherit = "res.company"
+
+    def _domain_company(self):
+        company = self.env.company
+        return ["|", ("company_id", "=", False), ("company_id", "=", company)]
+
+    documents_helpdesk_settings = fields.Boolean()
+    helpdesk_folder = fields.Many2one(
+        "documents.folder",
+        string="Helpdesk Workspace",
+        domain=_domain_company,
+        default=lambda self: self.env.ref(
+            "documents_helpdesk.documents_folder_helpdesk",
+            raise_if_not_found=False,
+        ),
+    )
+    document_helpdesk_tags = fields.Many2many(
+        "documents.tag", "document_helpdesk_tag", string="Helpdesk Tags"
+    )
diff --git a/documents_helpdesk/models/res_config_settings.py b/documents_helpdesk/models/res_config_settings.py
new file mode 100644
index 000000000..f4399c4d9
--- /dev/null
+++ b/documents_helpdesk/models/res_config_settings.py
@@ -0,0 +1,31 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from odoo import api, fields, models
+
+
+class ResConfigSettings(models.TransientModel):
+    _inherit = "res.config.settings"
+
+    documents_helpdesk_settings = fields.Boolean(
+        related="company_id.documents_helpdesk_settings",
+        readonly=False,
+        string="Helpdesk",
+    )
+    helpdesk_folder = fields.Many2one(
+        "documents.folder",
+        related="company_id.helpdesk_folder",
+        readonly=False,
+        string="Helpdesk Default Workspace",
+    )
+    helpdesk_tags = fields.Many2many(
+        "documents.tag",
+        "document_helpdesk_tag",
+        related="company_id.document_helpdesk_tags",
+        readonly=False,
+        string="Helpdesk Tags",
+    )
+
+    @api.onchange("helpdesk_folder")
+    def on_helpdesk_folder_change(self):
+        if self.helpdesk_folder != self.helpdesk_tags.mapped("folder_id"):
+            self.helpdesk_tags = False
diff --git a/documents_helpdesk/static/description/icon.png b/documents_helpdesk/static/description/icon.png
new file mode 100644
index 000000000..ff28f5b3a
Binary files /dev/null and b/documents_helpdesk/static/description/icon.png differ
diff --git a/documents_helpdesk/views/res_config_settings.xml b/documents_helpdesk/views/res_config_settings.xml
new file mode 100644
index 000000000..033d2e10b
--- /dev/null
+++ b/documents_helpdesk/views/res_config_settings.xml
@@ -0,0 +1,80 @@
+<odoo>
+
+    <record
+        id="res_config_settings_documents_helpdesk_view_form"
+        model="ir.ui.view"
+    >
+        <field
+            name="name"
+        >res.config.settings.view.form.documents.helpdesk</field>
+        <field name="model">res.config.settings</field>
+        <field name="priority" eval="70" />
+        <field name="inherit_id" ref="base.res_config_settings_view_form" />
+        <field name="arch" type="xml">
+            <xpath
+                expr="//div[hasclass('o_documents_block')]"
+                position="attributes"
+            >
+                <attribute name="invisible">0</attribute>
+            </xpath>
+            <xpath
+                expr="//div[hasclass('o_documents_block')]"
+                position="inside"
+            >
+                <div class="row mt16 o_settings_container">
+                    <div class="col-xs-12 col-md-6 o_setting_box">
+                        <div class="o_setting_left_pane">
+                            <field name="documents_helpdesk_settings" />
+                        </div>
+                        <div
+                            class="o_setting_right_pane o_documents_right_pane"
+                        >
+                            <label for="documents_helpdesk_settings" />
+                            <span
+                                class="fa fa-lg fa-building-o"
+                                title="Values set here are company-specific."
+                                aria-label="Values set here are company-specific."
+                                groups="base.group_multi_company"
+                                role="img"
+                            />
+                            <div class="row">
+                                <div class="text-muted col-md-12">
+                                    Centralize files attached to helpdesk tickets.
+                                </div>
+                            </div>
+                            <div
+                                class="content-group"
+                                attrs="{'invisible' : [('documents_helpdesk_settings', '=', False)]}"
+                            >
+                                <div class="row mt16">
+                                    <label
+                                        class="o_form_label col-lg-3"
+                                        for="helpdesk_folder"
+                                        string="Workspace"
+                                    />
+                                    <field
+                                        name="helpdesk_folder"
+                                        attrs="{'required' : [('documents_helpdesk_settings', '=', True)]}"
+                                    />
+                                </div>
+                                <div class="row">
+                                    <label
+                                        class="o_form_label col-lg-3"
+                                        for="helpdesk_tags"
+                                        string="Default Tags"
+                                    />
+                                    <field
+                                        name="helpdesk_tags"
+                                        widget="many2many_tags"
+                                        domain="[('folder_id','=', helpdesk_folder)]"
+                                    />
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </xpath>
+        </field>
+    </record>
+
+</odoo>
diff --git a/documents_purchase/README.rst b/documents_purchase/README.rst
new file mode 100644
index 000000000..af67436c9
--- /dev/null
+++ b/documents_purchase/README.rst
@@ -0,0 +1,84 @@
+=============================
+Documents for Purchase Orders
+=============================
+
+.. |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-LGPL--3-blue.png
+    :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+    :alt: License: LGPL-3
+.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fosi--addons-lightgray.png?logo=github
+    :target: https://github.com/OCA/osi-addons/tree/14.0/osi_custom_profit_loss
+    :alt: OCA/osi-addons
+
+|badge1| |badge2| |badge3|
+
+This module provides a documents folder where all the purchase orders attachments will
+be available.
+
+**Table of contents**
+
+.. contents::
+   :local:
+
+Usage
+=====
+
+* Go to Purchase > Orders > Requests for Quotation (or Purchase Orders)
+* Create or open a record
+* Upload a file as an attachment
+* Go to Documents
+* Select the Purchase folder
+* Select the file uploaded previously. It is linked to the Purchase Order.
+
+Bug Tracker
+===========
+
+Bugs are tracked on `GitHub Issues <https://github.com/OCA/osi-addons/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 <https://github.com/OCA/osi-addons/issues/new?body=module:%20osi_custom_profit_loss%0Aversion:%2014.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
+
+Do not contact contributors directly about support or help with technical issues.
+
+Credits
+=======
+
+Authors
+~~~~~~~
+
+* Open Source Integrators
+
+Contributors
+~~~~~~~~~~~~
+
+* `Open Source Integrators <https://www.opensourceintegrators.com>`__:
+
+  * Antonio Yamuta <ayamuta@opensourceintegrators.com>
+  * Maxime Chambreuil <mchambreuil@opensourceintegrators.com>
+  * Melody Fetterly <mfetterly@opensourceintegrators.com>
+
+Maintainers
+~~~~~~~~~~~
+
+This module is maintained by Open Source Integrators.
+
+.. image:: https://github.com/ursais.png
+   :alt: Open Source Integrators
+   :target: https://www.opensourceintegrators.com
+
+Open Source Integrators™ (OSI) provides customers a unique combination of
+open source business process consulting and implementations.
+
+.. |maintainer-max3903| image:: https://github.com/max3903.png?size=40px
+    :target: https://github.com/max3903
+    :alt: max3903
+
+Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
+
+|maintainer-max3903|
+
+This module is part of the `OSI Addons <https://github.com/ursais/osi-addons>`_ project on GitHub.
+
+You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/documents_purchase/__init__.py b/documents_purchase/__init__.py
new file mode 100644
index 000000000..708e164fd
--- /dev/null
+++ b/documents_purchase/__init__.py
@@ -0,0 +1,3 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from . import models
diff --git a/documents_purchase/__manifest__.py b/documents_purchase/__manifest__.py
new file mode 100644
index 000000000..47e826a8d
--- /dev/null
+++ b/documents_purchase/__manifest__.py
@@ -0,0 +1,22 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+{
+    "name": "Documents - Purchase",
+    "summary": "Documents for Purchase Orders",
+    "category": "Productivity/Documents",
+    "website": "https://github.com/ursais/osi-addons",
+    "author": "Open Source Integrators",
+    "maintainer": "Open Source Integrators",
+    "version": "14.0.1.0.0",
+    "license": "LGPL-3",
+    "depends": ["documents", "purchase"],
+    "data": [
+        "data/documents_folder.xml",
+        "data/res_company.xml",
+        "data/documents_facet.xml",
+        "data/documents_tag.xml",
+        "views/res_config_settings.xml",
+    ],
+    "development_status": "Beta",
+    "maintainers": ["max3903"],
+}
diff --git a/documents_purchase/data/documents_facet.xml b/documents_purchase/data/documents_facet.xml
new file mode 100644
index 000000000..381e8e13b
--- /dev/null
+++ b/documents_purchase/data/documents_facet.xml
@@ -0,0 +1,9 @@
+<odoo noupdate="1">
+
+    <record id="documents_purchase_facet" model="documents.facet">
+        <field name="name">Documents</field>
+        <field name="sequence">5</field>
+        <field name="folder_id" ref="documents_purchase_folder" />
+    </record>
+
+</odoo>
diff --git a/documents_purchase/data/documents_folder.xml b/documents_purchase/data/documents_folder.xml
new file mode 100644
index 000000000..a99915dd1
--- /dev/null
+++ b/documents_purchase/data/documents_folder.xml
@@ -0,0 +1,8 @@
+<odoo noupdate="1">
+
+    <record id="documents_purchase_folder" model="documents.folder">
+        <field name="name">Purchase</field>
+        <field name="sequence">14</field>
+    </record>
+
+</odoo>
diff --git a/documents_purchase/data/documents_tag.xml b/documents_purchase/data/documents_tag.xml
new file mode 100644
index 000000000..e7a31c501
--- /dev/null
+++ b/documents_purchase/data/documents_tag.xml
@@ -0,0 +1,9 @@
+<odoo noupdate="1">
+
+    <record id="documents_tag_new" model="documents.tag">
+        <field name="name">New</field>
+        <field name="facet_id" ref="documents_purchase_facet" />
+        <field name="sequence">10</field>
+    </record>
+
+</odoo>
diff --git a/documents_purchase/data/res_company.xml b/documents_purchase/data/res_company.xml
new file mode 100644
index 000000000..00cfc4f50
--- /dev/null
+++ b/documents_purchase/data/res_company.xml
@@ -0,0 +1,7 @@
+<odoo noupdate="1">
+
+    <record id="base.main_company" model="res.company">
+        <field name="purchase_folder" ref="documents_purchase_folder" />
+    </record>
+
+</odoo>
diff --git a/documents_purchase/models/__init__.py b/documents_purchase/models/__init__.py
new file mode 100644
index 000000000..3cd166333
--- /dev/null
+++ b/documents_purchase/models/__init__.py
@@ -0,0 +1,5 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from . import purchase_order
+from . import res_config_settings
+from . import res_company
diff --git a/documents_purchase/models/purchase_order.py b/documents_purchase/models/purchase_order.py
new file mode 100644
index 000000000..862a1345c
--- /dev/null
+++ b/documents_purchase/models/purchase_order.py
@@ -0,0 +1,20 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from odoo import models
+
+
+class PurchaseOrder(models.Model):
+    _name = "purchase.order"
+    _inherit = ["purchase.order", "documents.mixin"]
+
+    def _get_document_tags(self):
+        company = self.company_id or self.env.company
+        return company.purchase_tags
+
+    def _get_document_folder(self):
+        company = self.company_id or self.env.company
+        return company.purchase_folder
+
+    def _check_create_documents(self):
+        company = self.company_id or self.env.company
+        return company.documents_purchase_settings and super()._check_create_documents()
diff --git a/documents_purchase/models/res_company.py b/documents_purchase/models/res_company.py
new file mode 100644
index 000000000..d67c84a10
--- /dev/null
+++ b/documents_purchase/models/res_company.py
@@ -0,0 +1,22 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from odoo import fields, models
+
+
+class ResCompany(models.Model):
+    _inherit = "res.company"
+
+    def _domain_company(self):
+        company = self.env.company
+        return ["|", ("company_id", "=", False), ("company_id", "=", company)]
+
+    documents_purchase_settings = fields.Boolean()
+    purchase_folder = fields.Many2one(
+        "documents.folder",
+        string="Purchase Workspace",
+        domain=_domain_company,
+        default=lambda self: self.env.ref(
+            "documents_purchase_folder", raise_if_not_found=False
+        ),
+    )
+    purchase_tags = fields.Many2many("documents.tag", "purchase_tags_table")
diff --git a/documents_purchase/models/res_config_settings.py b/documents_purchase/models/res_config_settings.py
new file mode 100644
index 000000000..91361f913
--- /dev/null
+++ b/documents_purchase/models/res_config_settings.py
@@ -0,0 +1,31 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from odoo import api, fields, models
+
+
+class ResConfigSettings(models.TransientModel):
+    _inherit = "res.config.settings"
+
+    documents_purchase_settings = fields.Boolean(
+        related="company_id.documents_purchase_settings",
+        readonly=False,
+        string="Purchase",
+    )
+    purchase_folder = fields.Many2one(
+        "documents.folder",
+        related="company_id.purchase_folder",
+        readonly=False,
+        string="Purchase Default Workspace",
+    )
+    purchase_tags = fields.Many2many(
+        "documents.tag",
+        "purchase_tags_table",
+        related="company_id.purchase_tags",
+        readonly=False,
+        string="Purchase Tags",
+    )
+
+    @api.onchange("purchase_folder")
+    def on_purchase_folder_change(self):
+        if self.purchase_folder != self.purchase_tags.mapped("folder_id"):
+            self.purchase_tags = False
diff --git a/documents_purchase/static/description/icon.png b/documents_purchase/static/description/icon.png
new file mode 100644
index 000000000..ff28f5b3a
Binary files /dev/null and b/documents_purchase/static/description/icon.png differ
diff --git a/documents_purchase/views/res_config_settings.xml b/documents_purchase/views/res_config_settings.xml
new file mode 100644
index 000000000..ae1975cf6
--- /dev/null
+++ b/documents_purchase/views/res_config_settings.xml
@@ -0,0 +1,75 @@
+<odoo>
+
+    <record id="res_config_settings_view_form" model="ir.ui.view">
+        <field name="name">res.config.settings.documents.purchase</field>
+        <field name="model">res.config.settings</field>
+        <field name="priority" eval="70" />
+        <field name="inherit_id" ref="base.res_config_settings_view_form" />
+        <field name="arch" type="xml">
+            <xpath
+                expr="//div[hasclass('o_documents_block')]"
+                position="attributes"
+            >
+                <attribute name="invisible">0</attribute>
+            </xpath>
+            <xpath
+                expr="//div[hasclass('o_documents_block')]"
+                position="inside"
+            >
+                <div class="row mt16 o_settings_container">
+                    <div class="col-xs-12 col-md-6 o_setting_box">
+                        <div class="o_setting_left_pane">
+                            <field name="documents_purchase_settings" />
+                        </div>
+                        <div
+                            class="o_setting_right_pane o_documents_right_pane"
+                        >
+                            <label for="documents_purchase_settings" />
+                            <span
+                                class="fa fa-lg fa-building-o"
+                                title="Values set here are company-specific."
+                                aria-label="Values set here are company-specific."
+                                groups="base.group_multi_company"
+                                role="img"
+                            />
+                            <div class="row">
+                                <div class="text-muted col-md-12">
+                                    Centralize files attached to request for quotations and purchase orders
+                                </div>
+                            </div>
+                            <div
+                                class="content-group"
+                                attrs="{'invisible' : [('documents_purchase_settings', '=', False)]}"
+                            >
+                                <div class="row mt16">
+                                    <label
+                                        class="o_form_label col-lg-3"
+                                        for="purchase_folder"
+                                        string="Workspace"
+                                    />
+                                    <field
+                                        name="purchase_folder"
+                                        attrs="{'required' : [('documents_purchase_settings', '=', True)]}"
+                                    />
+                                </div>
+                                <div class="row">
+                                    <label
+                                        class="o_form_label col-lg-3"
+                                        for="purchase_tags"
+                                        string="Default Tags"
+                                    />
+                                    <field
+                                        name="purchase_tags"
+                                        widget="many2many_tags"
+                                        domain="[('folder_id','=', purchase_folder)]"
+                                    />
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </xpath>
+        </field>
+    </record>
+
+</odoo>
diff --git a/fieldservice_agreement_helpdesk/README.rst b/fieldservice_agreement_helpdesk/README.rst
new file mode 100644
index 000000000..4cf34fe4b
--- /dev/null
+++ b/fieldservice_agreement_helpdesk/README.rst
@@ -0,0 +1,31 @@
+.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
+   :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+   :alt: License: LGPL-3
+
+====================================
+Field Service - Agreement - Helpdesk
+====================================
+
+This module links Field Service, Agreements and Help Desk together by:
+
+* setting the agreement fields when creating Field Service orders from a ticket.
+
+Usage
+=====
+
+* Go to Helpdesk
+* Create or select a ticket
+* Create an FSM Order
+
+To close a ticket, all the related service orders must be closed.
+
+Credits
+=======
+
+* Steve Campbell <scampbell@opensourceintegrators.com>
+* Vimal Patel <vpatel@opensourceintegrators.com>
+
+Contributors
+------------
+
+* Open Source Integrators <contact@opensourceintegrators.com>
diff --git a/fieldservice_agreement_helpdesk/__init__.py b/fieldservice_agreement_helpdesk/__init__.py
new file mode 100644
index 000000000..47d2b2851
--- /dev/null
+++ b/fieldservice_agreement_helpdesk/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import models
diff --git a/fieldservice_agreement_helpdesk/__manifest__.py b/fieldservice_agreement_helpdesk/__manifest__.py
new file mode 100644
index 000000000..87b841cea
--- /dev/null
+++ b/fieldservice_agreement_helpdesk/__manifest__.py
@@ -0,0 +1,22 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+{
+    "name": "Field Service - Agreement - Helpdesk",
+    "summary": "Create links between Field Service, Agreements, and Helpdesk",
+    "version": "14.0.1.0.0",
+    "license": "LGPL-3",
+    "author": "Open Source Integrators",
+    "category": "Helpdesk",
+    "website": "https://github.com/ursais/osi-addons",
+    "depends": [
+        "helpdesk_fieldservice",
+        "agreement_helpdesk",
+        "fieldservice_agreement",
+    ],
+    "data": ["views/helpdesk_ticket.xml"],
+    "installable": True,
+    "auto_install": True,
+    "development_status": "Beta",
+    "maintainers": ["osi-scampbell"],
+}
diff --git a/fieldservice_agreement_helpdesk/models/__init__.py b/fieldservice_agreement_helpdesk/models/__init__.py
new file mode 100644
index 000000000..9d0d9bccd
--- /dev/null
+++ b/fieldservice_agreement_helpdesk/models/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import helpdesk_ticket
diff --git a/fieldservice_agreement_helpdesk/models/helpdesk_ticket.py b/fieldservice_agreement_helpdesk/models/helpdesk_ticket.py
new file mode 100644
index 000000000..9c8269cc8
--- /dev/null
+++ b/fieldservice_agreement_helpdesk/models/helpdesk_ticket.py
@@ -0,0 +1,22 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from odoo import models
+
+
+class HelpdeskTicket(models.Model):
+    _inherit = "helpdesk.ticket"
+
+    def action_create_order(self):
+        """
+        This function returns an action that displays a full FSM Order
+        form when creating an FSM Order from a ticket.
+        """
+        res = super().action_create_order()
+        # override the context to get rid of the default filtering
+        res["context"].update(
+            {
+                "default_agreement_id": self.agreement_id.id,
+                "default_serviceprofile_id": self.serviceprofile_id.id,
+            }
+        )
+        return res
diff --git a/fieldservice_agreement_helpdesk/static/description/icon.png b/fieldservice_agreement_helpdesk/static/description/icon.png
new file mode 100644
index 000000000..955674d8f
Binary files /dev/null and b/fieldservice_agreement_helpdesk/static/description/icon.png differ
diff --git a/fieldservice_agreement_helpdesk/views/helpdesk_ticket.xml b/fieldservice_agreement_helpdesk/views/helpdesk_ticket.xml
new file mode 100644
index 000000000..3fb4a5f38
--- /dev/null
+++ b/fieldservice_agreement_helpdesk/views/helpdesk_ticket.xml
@@ -0,0 +1,20 @@
+<odoo>
+    <!-- Copyright 2021 Open Source Integrators
+         License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
+
+    <!-- Helpdesk Ticket Form View -->
+    <record id="helpdesk_ticket_view_service_request_form" model="ir.ui.view">
+        <field name="name">helpdesk.ticket.service.request.form</field>
+        <field name="model">helpdesk.ticket</field>
+        <field name="inherit_id" ref="helpdesk.helpdesk_ticket_view_form" />
+        <field name="arch" type="xml">
+            <field name="agreement_id" position="attributes">
+                <attribute name="domain">[
+                    '|',
+                    ('partner_id', '=', partner_id),
+                    ('fsm_location_id', '=', fsm_location_id)
+                    ]</attribute>
+            </field>
+        </field>
+    </record>
+</odoo>
diff --git a/fieldservice_googlemaps_address_autocompletion/README.rst b/fieldservice_googlemaps_address_autocompletion/README.rst
new file mode 100644
index 000000000..bf8702fa9
--- /dev/null
+++ b/fieldservice_googlemaps_address_autocompletion/README.rst
@@ -0,0 +1,42 @@
+.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
+   :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
+   :alt: License: AGPL-3
+
+===================================================
+Field Service - Google Maps Address Auto-completion
+===================================================
+
+This module adds address auto-completition to Field Service Locations.
+It also adds logic to create and sync PostGIS geometries between 
+FSM Locations and FSM Orders associated with that location.
+
+Installation
+============
+
+To install Field Service and have the mapping features, you need to install GeoEngine.
+
+Please refer to the installation instructions available at:
+https://github.com/OCA/geospatial/tree/12.0/base_geoengine
+
+Usage
+=====
+
+* Go to Field Service > Master Data > Locations
+* Create a new location and start typing the address.
+  The address will be auto-completed.
+* Go to Field Service > Operations > Orders
+* Edit an existing order to modify the location.
+  The geometry of the order will be updated accordingly.
+
+Credits
+=======
+
+* Michael Allen <mallen@opensourceintegrators.com>
+* Vimal Patel <vpatel@opensourceintegrators.com>
+
+
+Contributors
+------------
+
+* Open Source Integrators <http://www.opensourceintegrators.com>
+* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
diff --git a/fieldservice_googlemaps_address_autocompletion/__init__.py b/fieldservice_googlemaps_address_autocompletion/__init__.py
new file mode 100644
index 000000000..01a25d089
--- /dev/null
+++ b/fieldservice_googlemaps_address_autocompletion/__init__.py
@@ -0,0 +1,2 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
diff --git a/fieldservice_googlemaps_address_autocompletion/__manifest__.py b/fieldservice_googlemaps_address_autocompletion/__manifest__.py
new file mode 100644
index 000000000..e1d9c0063
--- /dev/null
+++ b/fieldservice_googlemaps_address_autocompletion/__manifest__.py
@@ -0,0 +1,25 @@
+# Copyright (C) 2021 Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+{
+    "name": "Field Service - Google Maps Address Auto-completion",
+    "version": "14.0.1.0.0",
+    "license": "AGPL-3",
+    "summary": "Auto-complete addresses with Google Maps",
+    "author": "Open Source Integrators",
+    "maintainer": "Open Source Integrators",
+    "website": "https://github.com/ursais/osi-addons",
+    "depends": [
+        "web_view_google_map",
+        "fieldservice",
+    ],
+    "data": [
+        "views/fsm_location.xml",
+        "views/res_partner.xml",
+    ],
+    "development_status": "Beta",
+    "maintainers": [
+        "osimallen",
+    ],
+    "installable": True,
+}
diff --git a/fieldservice_googlemaps_address_autocompletion/static/description/icon.png b/fieldservice_googlemaps_address_autocompletion/static/description/icon.png
new file mode 100644
index 000000000..955674d8f
Binary files /dev/null and b/fieldservice_googlemaps_address_autocompletion/static/description/icon.png differ
diff --git a/fieldservice_googlemaps_address_autocompletion/views/fsm_location.xml b/fieldservice_googlemaps_address_autocompletion/views/fsm_location.xml
new file mode 100644
index 000000000..39673c1af
--- /dev/null
+++ b/fieldservice_googlemaps_address_autocompletion/views/fsm_location.xml
@@ -0,0 +1,26 @@
+<odoo>
+
+    <!-- Field Service Location Form View-->
+    <record id="fsm_location_form_view_autocomplete" model="ir.ui.view">
+        <field name="name">fsm.location.form.autocomplete</field>
+        <field name="model">fsm.location</field>
+        <field name='inherit_id' ref='fieldservice.fsm_location_form_view' />
+        <field name="arch" type="xml">
+            <field name='name' position='attributes'>
+                <attribute name='widget'>gplaces_autocomplete</attribute>
+                <attribute name='options'>
+                    {'lat':'partner_latitude','lng':'partner_longitude'}
+                </attribute>
+            </field>
+            <field name="street" position='attributes'>
+                <attribute
+                    name='widget'
+                >gplaces_address_autocomplete</attribute>
+                <attribute name='options'>
+                    {'lat':'partner_latitude','lng':'partner_longitude'}
+                </attribute>
+            </field>
+        </field>
+    </record>
+
+</odoo>
diff --git a/fieldservice_googlemaps_address_autocompletion/views/res_partner.xml b/fieldservice_googlemaps_address_autocompletion/views/res_partner.xml
new file mode 100644
index 000000000..15c4d4f2c
--- /dev/null
+++ b/fieldservice_googlemaps_address_autocompletion/views/res_partner.xml
@@ -0,0 +1,25 @@
+<odoo>
+
+    <record id="fsm_partner_fields" model="ir.ui.view">
+        <field name="name">res.partner.fsm.form</field>
+        <field name="model">res.partner</field>
+        <field name="inherit_id" ref="base.view_partner_form" />
+        <field name="arch" type="xml">
+            <field name="name" position='attributes'>
+                <attribute name='widget'>gplaces_autocomplete</attribute>
+                <attribute name='options'>
+                    {'lat':'partner_latitude','lng':'partner_longitude'}
+                </attribute>
+            </field>
+            <field name="street" position='attributes'>
+                <attribute
+                    name='widget'
+                >gplaces_address_autocomplete</attribute>
+                <attribute name='options'>
+                    {'lat':'partner_latitude','lng':'partner_longitude'}
+                </attribute>
+            </field>
+        </field>
+    </record>
+
+</odoo>
diff --git a/fieldservice_helpdesk_stock/README.rst b/fieldservice_helpdesk_stock/README.rst
new file mode 100644
index 000000000..176af5f94
--- /dev/null
+++ b/fieldservice_helpdesk_stock/README.rst
@@ -0,0 +1,94 @@
+=================================
+Field Service - Help Desk - Stock
+=================================
+
+.. |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-LGPL--3-blue.png
+    :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+    :alt: License: LGPL-3
+
+|badge1| |badge2| 
+
+Odoo Field Service App allows to manage service requests and orders. The app
+does not support the logistic side of those activities: Sometimes, the
+dispatcher needs to ship materials to the field service worker or to the
+serviced location.
+
+Odoo Help Desk App allows to manage support tickets or customer service requests.
+The app does not support the logistic side of those activities: Sometimes,
+helpdesk users need to ship materials to the customer or to the serviced
+location to solve a ticket.
+
+This module allows to integrate material requests between a helpdesk ticket and
+field service order to be shipped to the customer location or serviced location
+and follow up with the Inventory team.
+
+**Table of contents**
+
+.. contents::
+   :local:
+
+Usage
+=====
+
+* Create a service order with a customer and a ticket
+* In Inventory, add products with quantity
+* Click on Confirm
+
+  * The delivery order is created
+  * The transfer is set on the ticket
+  * The state is updated to Confirmed
+  * The product, description and quantity requested cannot be changed
+
+* Transfer partially the delivery order
+
+  * The state is updated to Partially Shipped
+
+* Transfer completely the delivery order
+
+  * The state is updated to Done
+
+Bug Tracker
+===========
+
+Bugs are tracked on `GitHub Issues <https://github.com/ursais/12.0/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 <https://github.com/ursais/12.0/issues/new?body=module:%20fieldservice_helpdesk_stock%0Aversion:%2011.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
+
+Do not contact contributors directly about support or help with technical issues.
+
+Credits
+=======
+
+Authors
+~~~~~~~
+
+* Open Source Integrators
+
+Contributors
+~~~~~~~~~~~~
+
+* Bhavesh Odedra <bodedra@opensourceintegrators.com>
+* Maxime Chambreuil <mchambreuil@opensourceintegrators.com>
+
+Other credits
+~~~~~~~~~~~~~
+
+The development of this module has been financially supported by:
+
+* Open Source Integrators
+
+Maintainers
+~~~~~~~~~~~
+
+.. |maintainer-max3903| image:: https://github.com/max3903.png?size=40px
+    :target: https://github.com/max3903
+    :alt: max3903
+.. |maintainer-bodedra| image:: https://github.com/bodedra.png?size=40px
+    :target: https://github.com/bodedra
+    :alt: bodedra
+
+|maintainer-max3903| |maintainer-bodedra| 
diff --git a/fieldservice_helpdesk_stock/__init__.py b/fieldservice_helpdesk_stock/__init__.py
new file mode 100644
index 000000000..47d2b2851
--- /dev/null
+++ b/fieldservice_helpdesk_stock/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import models
diff --git a/fieldservice_helpdesk_stock/__manifest__.py b/fieldservice_helpdesk_stock/__manifest__.py
new file mode 100644
index 000000000..e7a86c016
--- /dev/null
+++ b/fieldservice_helpdesk_stock/__manifest__.py
@@ -0,0 +1,26 @@
+# Copyright (C) 2021     - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+{
+    "name": "Field Service - Helpdesk - Stock",
+    "summary": "Manage material requirements from Field Service and Helpdesk",
+    "author": "Open Source Integrators",
+    "website": "https://github.com/ursais/osi-addons",
+    "category": "Field Service",
+    "license": "LGPL-3",
+    "version": "14.0.1.0.0",
+    "depends": [
+        "fieldservice_stock_request",
+        "helpdesk_fieldservice",
+        "helpdesk_stock",
+    ],
+    "data": [
+        "views/helpdesk_views.xml",
+        "views/stock_request_order.xml",
+        "views/stock_request.xml",
+        "views/fsm_location.xml",
+    ],
+    "development_status": "Beta",
+    "maintainers": ["max3903", "bodedra"],
+    "auto_install": True,
+}
diff --git a/fieldservice_helpdesk_stock/models/__init__.py b/fieldservice_helpdesk_stock/models/__init__.py
new file mode 100644
index 000000000..e1ceefd33
--- /dev/null
+++ b/fieldservice_helpdesk_stock/models/__init__.py
@@ -0,0 +1,11 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import (
+    fsm_order,
+    helpdesk_ticket,
+    stock_request,
+    stock_request_order,
+    fsm_location,
+    procurement_group,
+)
diff --git a/fieldservice_helpdesk_stock/models/fsm_location.py b/fieldservice_helpdesk_stock/models/fsm_location.py
new file mode 100644
index 000000000..460063fbe
--- /dev/null
+++ b/fieldservice_helpdesk_stock/models/fsm_location.py
@@ -0,0 +1,12 @@
+# Copyright (C) 2021 - TODAY, Brian McMaster
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from odoo import fields, models
+
+
+class FSMLocation(models.Model):
+    _inherit = "fsm.location"
+
+    default_warehouse_id = fields.Many2one(
+        "stock.warehouse", string="Default Warehouse"
+    )
diff --git a/fieldservice_helpdesk_stock/models/fsm_order.py b/fieldservice_helpdesk_stock/models/fsm_order.py
new file mode 100644
index 000000000..b3033cd52
--- /dev/null
+++ b/fieldservice_helpdesk_stock/models/fsm_order.py
@@ -0,0 +1,29 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import api, models
+
+
+class FSMOrder(models.Model):
+    _inherit = "fsm.order"
+
+    def action_request_confirm(self):
+        res = super(FSMOrder, self).action_request_confirm()
+        for order in self:
+            if order.ticket_id:
+                order.ticket_id.request_stage = order.request_stage
+        return res
+
+    def write(self, vals):
+        res = super(FSMOrder, self).write(vals)
+        if "ticket_id" in vals:
+            for line in self.stock_request_ids:
+                if line.state in ("draft", "cancelled"):
+                    line.ticket_id = vals.get("ticket_id")
+        return res
+
+    @api.onchange("location_id")
+    def onchange_location_id(self):
+        res = super().onchange_location_id()
+        self.warehouse_id = self.location_id.default_warehouse_id
+        return res
diff --git a/fieldservice_helpdesk_stock/models/helpdesk_ticket.py b/fieldservice_helpdesk_stock/models/helpdesk_ticket.py
new file mode 100644
index 000000000..7d6b7f4e7
--- /dev/null
+++ b/fieldservice_helpdesk_stock/models/helpdesk_ticket.py
@@ -0,0 +1,12 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import fields, models
+
+
+class HelpdeskTicket(models.Model):
+    _inherit = "helpdesk.ticket"
+
+    inventory_location_id = fields.Many2one(
+        related="fsm_location_id.inventory_location_id", store=True
+    )
diff --git a/fieldservice_helpdesk_stock/models/procurement_group.py b/fieldservice_helpdesk_stock/models/procurement_group.py
new file mode 100644
index 000000000..4ee2243cc
--- /dev/null
+++ b/fieldservice_helpdesk_stock/models/procurement_group.py
@@ -0,0 +1,10 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import fields, models
+
+
+class ProcurementGroup(models.Model):
+    _inherit = "procurement.group"
+
+    helpdesk_ticket_id = fields.Many2one("helpdesk.ticket", "Ticket")
diff --git a/fieldservice_helpdesk_stock/models/stock_request.py b/fieldservice_helpdesk_stock/models/stock_request.py
new file mode 100644
index 000000000..61edc2f2a
--- /dev/null
+++ b/fieldservice_helpdesk_stock/models/stock_request.py
@@ -0,0 +1,134 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import api, fields, models
+
+
+class StockRequest(models.Model):
+    _inherit = "stock.request"
+
+    fsm_location_id = fields.Many2one("fsm.location", string="FSM Location")
+    helpdesk_ticket_id = fields.Many2one("helpdesk.ticket", string="Ticket")
+
+    @api.onchange("direction", "fsm_order_id", "helpdesk_ticket_id")
+    def _onchange_location_id(self):
+        super()._onchange_location_id()
+        if self.fsm_order_id:
+            # FSM Order takes priority over Helpdesk Ticket
+            if self.direction == "outbound":
+                # Inventory location of the FSM location of the order
+                self.location_id = (
+                    self.fsm_order_id.location_id.inventory_location_id.id
+                )
+            else:
+                # Otherwise the stock location of the warehouse
+                self.location_id = self.fsm_order_id.warehouse_id.lot_stock_id.id
+            self.fsm_location_id = self.fsm_order_id.location_id.id
+
+    @api.model
+    def create(self, vals):
+        if vals.get("fsm_order_id"):
+            order = self.env["fsm.order"].browse(vals["fsm_order_id"])
+            vals.update({"helpdesk_ticket_id": order.ticket_id.id or False})
+            vals.update({"fsm_location_id": order.location_id.id or False})
+        elif vals.get("helpdesk_ticket_id", False):
+            ticket = self.env["helpdesk.ticket"].browse(vals["helpdesk_ticket_id"])
+            vals.update({"fsm_location_id": ticket.fsm_location_id.id or False})
+        return super().create(vals)
+
+    def write(self, vals):
+        if vals.get("fsm_order_id"):
+            order = self.env["fsm.order"].browse(vals["fsm_order_id"])
+            vals.update({"helpdesk_ticket_id": order.ticket_id.id or False})
+        return super().write(vals)
+
+    def prepare_order_values(self, vals):
+        res = super().prepare_order_values(vals)
+        if vals.get("fsm_order_id"):
+            fsm_order = self.env["fsm.order"].browse(vals["fsm_order_id"])
+            res.update(
+                {
+                    "helpdesk_ticket_id": fsm_order.ticket_id.id or False,
+                    "fsm_location_id": fsm_order.location_id.id,
+                }
+            )
+        return res
+
+    def _prepare_procurement_values(self, group_id=False):
+        res = super()._prepare_procurement_values(group_id=group_id)
+        if self.helpdesk_ticket_id:
+            res.update(
+                {
+                    "helpdesk_ticket_id": self.helpdesk_ticket_id.id,
+                    "partner_id": self.helpdesk_ticket_id.fsm_location_id.shipping_address_id.id
+                    or self.helpdesk_ticket_id.fsm_location_id.partner_id.id,
+                }
+            )
+        if self.fsm_order_id:
+            res.update(
+                {
+                    "fsm_order_id": self.fsm_order_id.id,
+                    "helpdesk_ticket_id": self.fsm_order_id.ticket_id.id or False,
+                    "partner_id": self.fsm_order_id.location_id.shipping_address_id.id
+                    or self.fsm_order_id.location_id.partner_id.id,
+                }
+            )
+        return res
+
+    def _prepare_procurement_group_values(self):
+        res = super()._prepare_procurement_group_values()
+        res.update(
+            {
+                "name": self.fsm_order_id.name,
+                "fsm_order_id": self.fsm_order_id.id,
+                "helpdesk_ticket_id": self.fsm_order_id.ticket_id.id or False,
+            }
+        )
+        return res
+
+    def _action_confirm(self):
+        for req in self:
+            # If we can find a group, use it
+            if (req.procurement_group_id) or (
+                req.order_id and req.order_id.procurement_group_id
+            ):
+                req.procurement_group_id = req.procurement_group_id.id or (
+                    req.order_id and req.order_id.procurement_group_id.id
+                )
+                res = super(StockRequest, req)._action_confirm()
+            # otherwise create one with the fsm order if we have one
+            elif req.fsm_order_id:
+                fsm_order = req.fsm_order_id
+                group = self.env["procurement.group"].search(
+                    [("fsm_order_id", "=", fsm_order.id)]
+                )
+                if not group:
+                    values = req._prepare_procurement_group_values()
+                    group = self.env["procurement.group"].create(values)
+                if req.order_id:
+                    req.order_id.procurement_group_id = group.id
+                req.procurement_group_id = group.id
+                res = super(StockRequest, req)._action_confirm()
+                fsm_order.request_stage = "open"
+            # otherwise create one with the ticket if we have one
+            elif req.helpdesk_ticket_id:
+                ticket = req.helpdesk_ticket_id
+                # If the ticket has many fsm orders, use the group with no
+                # fsm_order_id
+                group = self.env["procurement.group"].search(
+                    [
+                        ("helpdesk_ticket_id", "=", ticket.id),
+                        ("fsm_order_id", "=", False),
+                    ]
+                )
+                if not group:
+                    values = req._prepare_procurement_group_values()
+                    group = self.env["procurement.group"].create(values)
+                if req.order_id:
+                    req.order_id.procurement_group_id = group.id
+                req.procurement_group_id = group.id
+                res = super(StockRequest, req)._action_confirm()
+                ticket.request_stage = "open"
+            else:
+                res = super(StockRequest, req)._action_confirm()
+        return res
diff --git a/fieldservice_helpdesk_stock/models/stock_request_order.py b/fieldservice_helpdesk_stock/models/stock_request_order.py
new file mode 100644
index 000000000..6adf9ce96
--- /dev/null
+++ b/fieldservice_helpdesk_stock/models/stock_request_order.py
@@ -0,0 +1,70 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import api, fields, models
+
+
+class StockRequestOrder(models.Model):
+    _inherit = "stock.request.order"
+
+    fsm_location_id = fields.Many2one("fsm.location", string="FSM Location")
+    helpdesk_ticket_id = fields.Many2one("helpdesk.ticket", string="Ticket")
+
+    @api.model
+    def create(self, vals):
+        if vals.get("fsm_order_id"):
+            fsm_order = self.env["fsm.order"].browse(vals["fsm_order_id"])
+            vals.update(
+                {
+                    "helpdesk_ticket_id": fsm_order.ticket_id.id or False,
+                    "fsm_location_id": fsm_order.location_id.id or False,
+                }
+            )
+        elif vals.get("helpdesk_ticket_id", False):
+            ticket = self.env["helpdesk.ticket"].browse(vals["helpdesk_ticket_id"])
+            vals.update({"fsm_location_id": ticket.fsm_location_id.id or False})
+        return super().create(vals)
+
+    @api.onchange("warehouse_id", "direction", "fsm_order_id", "helpdesk_ticket_id")
+    def _onchange_location_id(self):
+        super()._onchange_location_id()
+        # FSM Order takes priority over Helpdesk Ticket
+        order = self.fsm_order_id or self.helpdesk_ticket_id
+        if order:
+            if self.direction == "outbound":
+                self.location_id = order.inventory_location_id.id
+            else:
+                self.location_id = order.warehouse_id.lot_stock_id.id
+            self.fsm_location_id = self.fsm_order_id.location_id.id
+            self.change_childs()
+
+    def change_childs(self):
+        super().change_childs()
+        if not self._context.get("no_change_childs", False):
+            for line in self.stock_request_ids:
+                line.fsm_order_id = self.fsm_order_id.id
+                line.helpdesk_ticket_id = self.fsm_order_id.ticket_id.id or False
+                if not line.helpdesk_ticket_id:
+                    line.helpdesk_ticket_id = self.helpdesk_ticket_id
+
+    def write(self, vals):
+        if vals.get("fsm_order_id"):
+            order = self.env["fsm.order"].browse(vals["fsm_order_id"])
+            vals.update(
+                {
+                    "helpdesk_ticket_id": order.ticket_id.id or False,
+                    "fsm_location_id": order.fsm_location_id.id or False,
+                }
+            )
+        return super().write(vals)
+
+    def _prepare_procurement_group_values(self):
+        res = super()._prepare_procurement_group_values()
+        res.update(
+            {
+                "name": self.fsm_order_id.name,
+                "fsm_order_id": self.fsm_order_id.id,
+                "helpdesk_ticket_id": self.fsm_order_id.ticket_id.id or False,
+            }
+        )
+        return res
diff --git a/fieldservice_helpdesk_stock/readme/CONFIGURE.rst b/fieldservice_helpdesk_stock/readme/CONFIGURE.rst
new file mode 100644
index 000000000..e69de29bb
diff --git a/fieldservice_helpdesk_stock/readme/CONTRIBUTORS.rst b/fieldservice_helpdesk_stock/readme/CONTRIBUTORS.rst
new file mode 100644
index 000000000..567f85bd6
--- /dev/null
+++ b/fieldservice_helpdesk_stock/readme/CONTRIBUTORS.rst
@@ -0,0 +1,1 @@
+* Bhavesh Odedra <bodedra@opensourceintegrators.com>
diff --git a/fieldservice_helpdesk_stock/readme/CREDITS.rst b/fieldservice_helpdesk_stock/readme/CREDITS.rst
new file mode 100644
index 000000000..8209266d9
--- /dev/null
+++ b/fieldservice_helpdesk_stock/readme/CREDITS.rst
@@ -0,0 +1,3 @@
+The development of this module has been financially supported by:
+
+* Open Source Integrators
diff --git a/fieldservice_helpdesk_stock/readme/DESCRIPTION.rst b/fieldservice_helpdesk_stock/readme/DESCRIPTION.rst
new file mode 100644
index 000000000..879797bb5
--- /dev/null
+++ b/fieldservice_helpdesk_stock/readme/DESCRIPTION.rst
@@ -0,0 +1,13 @@
+Odoo Field Service App allows to manage service requests and orders. The app
+does not support the logistic side of those activities: Sometimes, the
+dispatcher need to ship materials to the field service worker or to the
+serviced location.
+
+Odoo Helpdesk App allows to manage support tickets or customer service requests.
+The app does not support the logistic side of those activities: Sometimes,
+helpdesk users need to ship materials to the customer or to the serviced
+location to solve a ticket.
+
+This module allows to integrate material request between a helpdesk ticket and
+field service order to be shipped to the customer location or serviced location
+and follow up with the Inventory team.
diff --git a/fieldservice_helpdesk_stock/readme/ROADMAP.rst b/fieldservice_helpdesk_stock/readme/ROADMAP.rst
new file mode 100644
index 000000000..e69de29bb
diff --git a/fieldservice_helpdesk_stock/readme/USAGE.rst b/fieldservice_helpdesk_stock/readme/USAGE.rst
new file mode 100644
index 000000000..df41d720a
--- /dev/null
+++ b/fieldservice_helpdesk_stock/readme/USAGE.rst
@@ -0,0 +1,16 @@
+* Create a service order with a customer and a ticket
+* In Inventory, add products with quantity
+* Click on Confirm
+
+    * The delivery order is created
+    * The transfer is set on the ticket
+    * The state is updated to Confirmed
+    * The product, description and quantity requested cannot be changed
+
+* Transfer partially the delivery order
+
+    * The state is updated to Partially Shipped
+
+* Transfer completely the delivery order
+
+    * The state is updated to Done
diff --git a/fieldservice_helpdesk_stock/static/description/icon.png b/fieldservice_helpdesk_stock/static/description/icon.png
new file mode 100644
index 000000000..955674d8f
Binary files /dev/null and b/fieldservice_helpdesk_stock/static/description/icon.png differ
diff --git a/fieldservice_helpdesk_stock/views/fsm_location.xml b/fieldservice_helpdesk_stock/views/fsm_location.xml
new file mode 100644
index 000000000..290236138
--- /dev/null
+++ b/fieldservice_helpdesk_stock/views/fsm_location.xml
@@ -0,0 +1,16 @@
+<!-- Copyright (C) 2018 Brian McMaster
+     Copyright (C) 2021 Open Source Integrators
+     License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
+<odoo>
+
+    <record id="fsm_location_stock_add_default_warehouse" model="ir.ui.view">
+        <field name="model">fsm.location</field>
+        <field name="inherit_id" ref="fieldservice.fsm_location_form_view" />
+        <field name="arch" type="xml">
+            <field name="inventory_location_id" position="after">
+                <field name="default_warehouse_id" />
+            </field>
+        </field>
+    </record>
+
+</odoo>
diff --git a/fieldservice_helpdesk_stock/views/helpdesk_views.xml b/fieldservice_helpdesk_stock/views/helpdesk_views.xml
new file mode 100644
index 000000000..b7df81886
--- /dev/null
+++ b/fieldservice_helpdesk_stock/views/helpdesk_views.xml
@@ -0,0 +1,30 @@
+<odoo>
+
+    <!-- Copyright (C) 2021 - TODAY, Open Source Integrators
+    License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
+
+    <menuitem
+        id="menu_helpdesk_location"
+        name="Locations"
+        action="fieldservice.action_fsm_location"
+        parent="helpdesk.helpdesk_menu_config"
+        sequence="60"
+    />
+
+    <menuitem
+        id="menu_helpdesk_equipment"
+        name="Equipment"
+        action="fieldservice.action_fsm_equipment"
+        parent="helpdesk.helpdesk_menu_config"
+        sequence="70"
+    />
+
+    <menuitem
+        id="menu_helpdesk_contacts"
+        name="Contacts"
+        action="contacts.action_contacts"
+        parent="helpdesk.helpdesk_menu_config"
+        sequence="80"
+    />
+
+</odoo>
diff --git a/fieldservice_helpdesk_stock/views/stock_request.xml b/fieldservice_helpdesk_stock/views/stock_request.xml
new file mode 100644
index 000000000..33098229e
--- /dev/null
+++ b/fieldservice_helpdesk_stock/views/stock_request.xml
@@ -0,0 +1,16 @@
+<odoo>
+    <record id="stock_request_fsm_location" model="ir.ui.view">
+        <field name="name">stock.request.fsm.location</field>
+        <field name="model">stock.request</field>
+        <field
+            name="inherit_id"
+            ref="fieldservice_stock_request.stock_request_fsm_order_form"
+        />
+        <field name="arch" type="xml">
+            <field name="fsm_order_id" position="after">
+                <field name="fsm_location_id" />
+                <field name="helpdesk_ticket_id" />
+            </field>
+        </field>
+    </record>
+</odoo>
diff --git a/fieldservice_helpdesk_stock/views/stock_request_order.xml b/fieldservice_helpdesk_stock/views/stock_request_order.xml
new file mode 100644
index 000000000..61aed4fe1
--- /dev/null
+++ b/fieldservice_helpdesk_stock/views/stock_request_order.xml
@@ -0,0 +1,16 @@
+<odoo>
+    <record id="stock_request_order_fsm_location" model="ir.ui.view">
+        <field name="name">stock.request.order.fsm.location</field>
+        <field name="model">stock.request.order</field>
+        <field
+            name="inherit_id"
+            ref="fieldservice_stock_request.stock_request_order_fsm_order_form"
+        />
+        <field name="arch" type="xml">
+            <field name="fsm_order_id" position="after">
+                <field name="fsm_location_id" />
+                <field name="helpdesk_ticket_id" />
+            </field>
+        </field>
+    </record>
+</odoo>
diff --git a/fieldservice_mobile/README.rst b/fieldservice_mobile/README.rst
new file mode 100644
index 000000000..837ac2c7b
--- /dev/null
+++ b/fieldservice_mobile/README.rst
@@ -0,0 +1,39 @@
+.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
+   :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+   :alt: License: LGPL-3
+
+====================
+Field Service Mobile
+====================
+
+This module is manage FSM mobile stages based on configuration.
+
+Configuration
+=============
+
+To configure this module, you need to:
+
+* Go to Field Service > Configuration > Stages.
+* Check Display in Mobile for display stage in FSM Mobile.
+* Check Display in Odoo for display stage in Odoo FSM Order.
+* Select a server action based on Stages.
+
+* Manage domain on Automated Actions based on Stage sequence.
+
+For Example:- If the Started stage sequence is 6.
+
+* Go to Settings > Automated Actions > FSM Order Started Stage Update > Apply on > [["stage_id.sequence","=",6]]
+
+Credits
+=======
+
+* Open Source Integrators <https://opensourceintegrators.com>
+* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
+
+Contributors
+~~~~~~~~~~~~
+
+* Wolfgang Hall <whall@opensourceintegrators.com>
+* Sandip Mangukiya <smangukiya@opensourceintegrators.com>
+* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
+* Ammar Officewala <aofficewala@opensourceintegrators.com>
diff --git a/fieldservice_mobile/__init__.py b/fieldservice_mobile/__init__.py
new file mode 100644
index 000000000..69f7babdf
--- /dev/null
+++ b/fieldservice_mobile/__init__.py
@@ -0,0 +1,3 @@
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from . import models
diff --git a/fieldservice_mobile/__manifest__.py b/fieldservice_mobile/__manifest__.py
new file mode 100644
index 000000000..3cfa0e8c7
--- /dev/null
+++ b/fieldservice_mobile/__manifest__.py
@@ -0,0 +1,37 @@
+# Copyright (C) 2020 Open Source Integrators
+# Copyright (C) 2020 Serpent Consulting Services Pvt. Ltd.
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+{
+    "name": "Field Service Mobile",
+    "summary": "Field Service Mobile backend support.",
+    "license": "AGPL-3",
+    "version": "14.0.1.2.0",
+    "category": "Field Service",
+    "author": "Open Source Integrators",
+    "website": "https://github.com/ursais/osi-addons",
+    "depends": [
+        "fieldservice_stage_server_action",
+        "fieldservice_vehicle",
+        "fieldservice_sale_order_line",
+        "fieldservice_tracking",
+        "fieldservice_sign",
+        "fieldservice_stock_request",
+        "fieldservice_account_analytic",
+        "fieldservice_isp_account",
+        "fieldservice_project",
+        "fieldservice_equipment_stock",
+        "fieldservice_maintenance",
+        "fieldservice_vehicle_stock",
+    ],
+    "data": [
+        "security/ir_rule.xml",
+        "security/ir.model.access.csv",
+        "data/base_automation.xml",
+        "views/res_config_settings.xml",
+        "views/fsm_stage_view.xml",
+        "views/fsm_order_view.xml",
+    ],
+    "development_status": "Beta",
+    "maintainers": ["wolfhall"],
+}
diff --git a/fieldservice_mobile/data/base_automation.xml b/fieldservice_mobile/data/base_automation.xml
new file mode 100644
index 000000000..584194ed5
--- /dev/null
+++ b/fieldservice_mobile/data/base_automation.xml
@@ -0,0 +1,89 @@
+<odoo>
+
+    <record id="fsm_order_started_stage_update" model="base.automation">
+        <field name="name">FSM Order Started Stage Update</field>
+        <field name="model_id" ref="fieldservice.model_fsm_order" />
+        <field name="trigger">on_write</field>
+        <field name="active" eval="True" />
+        <field name="filter_domain">[["stage_id.sequence","=",6]]</field>
+        <field name="state">code</field>
+        <field name="code">for rec in records:
+    stage_rec = env['fsm.stage.history'].search([('order_id', '=', rec.id)], order='id desc', limit=1)
+    call_it = False
+    if not stage_rec:
+        call_it = True
+    if stage_rec.stage_id != rec.stage_id:
+        call_it = True
+    if call_it and rec.stage_id.action_id:
+        rec.write(
+          {'date_start': datetime.datetime.now(),
+          'fsm_stage_history_ids': [(0, 0, {'start_datetime': datetime.datetime.now(), 'stage_id': rec.stage_id.id, 'duration': 0.0, 'total_duration': 0.0
+          })]})</field>
+    </record>
+
+    <record id="fsm_order_break_stage_update" model="base.automation">
+        <field name="name">FSM Order Break Stage Update</field>
+        <field name="model_id" ref="fieldservice.model_fsm_order" />
+        <field name="trigger">on_write</field>
+        <field name="active" eval="True" />
+        <field name="filter_domain">[["stage_id.sequence","=",7]]</field>
+        <field name="state">code</field>
+        <field name="code">for rec in records:
+    stage_rec = env['fsm.stage.history'].search([('order_id', '=', rec.id)], order='id desc', limit=1)
+    call_it = False
+    if not stage_rec:
+        call_it = True
+    if stage_rec.stage_id != rec.stage_id:
+        call_it = True
+    if call_it and rec.stage_id.action_id:
+        delta = datetime.datetime.now() - stage_rec.start_datetime
+        duration = round((delta.total_seconds() / 3600), 2)
+        rec.write(
+        {'fsm_stage_history_ids': [(0, 0, {'start_datetime': datetime.datetime.now(), 'stage_id': rec.stage_id.id, 'duration': duration, 'total_duration': round((duration + stage_rec.total_duration), 2)
+        })]})</field>
+    </record>
+
+    <record id="fsm_order_resume_stage_update" model="base.automation">
+        <field name="name">FSM Order Resume Stage Update</field>
+        <field name="model_id" ref="fieldservice.model_fsm_order" />
+        <field name="trigger">on_write</field>
+        <field name="active" eval="True" />
+        <field name="filter_domain">[["stage_id.sequence","=",  8]]</field>
+        <field name="state">code</field>
+        <field name="code">for rec in records:
+    stage_rec = env['fsm.stage.history'].search([('order_id', '=', rec.id)], order='id desc', limit=1)
+    call_it = False
+    if not stage_rec:
+        call_it = True
+    if stage_rec.stage_id != rec.stage_id:
+        call_it = True
+    if call_it and rec.stage_id.action_id:
+        rec.write(
+          {'fsm_stage_history_ids': [(0, 0, {'start_datetime': datetime.datetime.now(), 'stage_id': rec.stage_id.id, 'duration': 0.0, 'total_duration': round((rec.duration + stage_rec.total_duration), 2)
+          })]})</field>
+    </record>
+
+    <record id="fsm_order_completed_stage_update" model="base.automation">
+        <field name="name">FSM Order Completed Stage Update</field>
+        <field name="model_id" ref="fieldservice.model_fsm_order" />
+        <field name="trigger">on_write</field>
+        <field name="active" eval="True" />
+        <field name="filter_domain">[["stage_id.sequence","=",9]]</field>
+        <field name="state">code</field>
+        <field name="code">for rec in records:
+    stage_rec = env['fsm.stage.history'].search([('order_id', '=', rec.id)], order='id desc', limit=1)
+    call_it = False
+    if not stage_rec:
+        call_it = True
+    if stage_rec.stage_id != rec.stage_id:
+        call_it = True
+    if call_it and rec.stage_id.action_id:
+        delta = datetime.datetime.now() - stage_rec.start_datetime
+        duration = round((delta.total_seconds() / 3600), 2)
+        rec.write(
+          {'date_end': datetime.datetime.now(),
+            'fsm_stage_history_ids': [(0, 0, {'start_datetime': datetime.datetime.now(), 'stage_id': rec.stage_id.id, 'duration': duration, 'total_duration': round((duration + stage_rec.total_duration), 2)
+          })]})</field>
+    </record>
+
+</odoo>
diff --git a/fieldservice_mobile/models/__init__.py b/fieldservice_mobile/models/__init__.py
new file mode 100644
index 000000000..e9bab7860
--- /dev/null
+++ b/fieldservice_mobile/models/__init__.py
@@ -0,0 +1,8 @@
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from . import fsm_stage
+from . import fsm_order
+from . import fsm_stage_history
+from . import res_config_settings
+from . import res_users
+from . import ir_attachment
diff --git a/fieldservice_mobile/models/fsm_order.py b/fieldservice_mobile/models/fsm_order.py
new file mode 100644
index 000000000..8398a279b
--- /dev/null
+++ b/fieldservice_mobile/models/fsm_order.py
@@ -0,0 +1,49 @@
+# Copyright (C) 2020 Open Source Integrators
+# Copyright (C) 2020 Serpent Consulting Services Pvt. Ltd.
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from odoo import api, fields, models
+
+
+class FSMOrder(models.Model):
+    _inherit = "fsm.order"
+
+    @api.depends("date_start", "date_end")
+    def _compute_duration(self):
+        res = super()._compute_duration()
+        for rec in self:
+            if rec.fsm_stage_history_ids and rec.date_end:
+                stage_rec = self.env["fsm.stage.history"].search(
+                    [("order_id", "=", rec.id)], order="id desc", limit=1
+                )
+                rec.duration = stage_rec.total_duration
+            elif not rec.date_end:
+                rec.duration = 0.0
+        return res
+
+    duration = fields.Float(
+        string="Actual duration",
+        compute=_compute_duration,
+        help="Actual duration in hours",
+        store=True,
+    )
+    fsm_stage_history_ids = fields.One2many(
+        "fsm.stage.history", "order_id", string="Stage History"
+    )
+
+    @api.model
+    def create_fsm_attachment(self, name, datas, res_model, res_id):
+        if res_model == "fsm.order":
+            attachment = (
+                self.env["ir.attachment"]
+                .sudo()
+                .create(
+                    {
+                        "name": name,
+                        "datas": datas,
+                        "res_model": res_model,
+                        "res_id": res_id,
+                    }
+                )
+            )
+            return attachment.id
diff --git a/fieldservice_mobile/models/fsm_stage.py b/fieldservice_mobile/models/fsm_stage.py
new file mode 100644
index 000000000..a14179666
--- /dev/null
+++ b/fieldservice_mobile/models/fsm_stage.py
@@ -0,0 +1,12 @@
+# Copyright (C) 2020 Open Source Integrators
+# Copyright (C) 2020 Serpent Consulting Services Pvt. Ltd.
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from odoo import fields, models
+
+
+class FSMStage(models.Model):
+    _inherit = "fsm.stage"
+
+    is_display_in_mobile = fields.Boolean("Display in Mobile", default=False)
+    is_display_in_odoo = fields.Boolean("Display in Odoo", default=True)
diff --git a/fieldservice_mobile/models/fsm_stage_history.py b/fieldservice_mobile/models/fsm_stage_history.py
new file mode 100644
index 000000000..533dabfab
--- /dev/null
+++ b/fieldservice_mobile/models/fsm_stage_history.py
@@ -0,0 +1,20 @@
+# Copyright (C) 2020 Open Source Integrators
+# Copyright (C) 2020 Serpent Consulting Services Pvt. Ltd.
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from odoo import fields, models
+
+
+class FsmStageHistory(models.Model):
+    _name = "fsm.stage.history"
+    _description = "FSM Stage History"
+
+    order_id = fields.Many2one("fsm.order", string="FSM Order")
+    start_datetime = fields.Datetime("Start Date&time")
+    stage_id = fields.Many2one("fsm.stage", string="Stage")
+    duration = fields.Float(
+        string="Duration",
+    )
+    total_duration = fields.Float(
+        string="Total Duration",
+    )
diff --git a/fieldservice_mobile/models/ir_attachment.py b/fieldservice_mobile/models/ir_attachment.py
new file mode 100644
index 000000000..884abbe02
--- /dev/null
+++ b/fieldservice_mobile/models/ir_attachment.py
@@ -0,0 +1,71 @@
+# Copyright (C) 2021 Open Source Integrators
+# Copyright (C) 2021 Serpent Consulting Services Pvt. Ltd.
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+from collections import defaultdict
+
+from odoo import _, api, models
+from odoo.exceptions import AccessError
+
+
+class IrAttachment(models.Model):
+    _inherit = "ir.attachment"
+
+    """Overwrite check method for allow portal user to read attachment"""
+
+    @api.model
+    def check(self, mode, values=None):
+        """Restricts the access to an ir.attachment, according to referred mode"""
+        if self.env.is_superuser():
+            return True
+        # Always require an internal user (aka, employee) to access to a attachment
+
+        # if not (self.env.is_admin() or self.env.user.has_group('base.group_user')):
+        #     raise AccessError(_("Sorry, you are not allowed to access this document."))
+
+        # collect the records to check (by model)
+        model_ids = defaultdict(set)  # {model_name: set(ids)}
+        if self:
+            # DLE P173: `test_01_portal_attachment`
+            self.env["ir.attachment"].flush(
+                ["res_model", "res_id", "public", "res_field"]
+            )
+            self._cr.execute(
+                """SELECT res_model, res_id, create_uid, public, res_field
+                  FROM ir_attachment WHERE id IN %s""",
+                [tuple(self.ids)],
+            )
+            for res_model, res_id, public, res_field in self._cr.fetchall():
+                if not self.env.is_system() and res_field:
+                    raise AccessError(
+                        _("Sorry, you are not allowed to access this document.")
+                    )
+                if public and mode == "read":
+                    continue
+                if not (res_model and res_id):
+                    continue
+                model_ids[res_model].add(res_id)
+        if values and values.get("res_model") and values.get("res_id"):
+            model_ids[values["res_model"]].add(values["res_id"])
+
+        # check access rights on the records
+        for res_model, res_ids in model_ids.items():
+            # ignore attachments that are not attached to a resource anymore
+            # when checking access rights (resource was deleted but attachment
+            # was not)
+            if res_model not in self.env:
+                continue
+            if (
+                res_model == "res.users"
+                and len(res_ids) == 1
+                and self.env.uid == list(res_ids)[0]
+            ):
+                # by default a user cannot write on itself, despite the list of writeable fields
+                # e.g. in the case of a user inserting an image into his image signature
+                # we need to bypass this check which would needlessly throw us away
+                continue
+            records = self.env[res_model].browse(res_ids).exists()
+            # For related models, check if we can write to the model, as unlinking
+            # and creating attachments can be seen as an update to the model
+            access_mode = "write" if mode in ("create", "unlink") else mode
+            records.check_access_rights(access_mode)
+            records.check_access_rule(access_mode)
diff --git a/fieldservice_mobile/models/res_config_settings.py b/fieldservice_mobile/models/res_config_settings.py
new file mode 100644
index 000000000..6a4ccad3f
--- /dev/null
+++ b/fieldservice_mobile/models/res_config_settings.py
@@ -0,0 +1,18 @@
+# Copyright (C) 2020 Open Source Integrators
+# Copyright (C) 2020 Serpent Consulting Services Pvt. Ltd.
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from odoo import fields, models
+
+
+class ResConfigSettings(models.TransientModel):
+    _inherit = "res.config.settings"
+
+    fsm_allow_portal_view_move_qty = fields.Boolean(
+        string="Allow portal user to view stock move quantities",
+        config_parameter="fieldservice_mobile.fsm_allow_portal_view_move_qty",
+    )
+    fsm_allow_portal_update_move_qty = fields.Boolean(
+        string="Allow portal user update of stock move quantities",
+        config_parameter="fieldservice_mobile.fsm_allow_portal_update_move_qty",
+    )
diff --git a/fieldservice_mobile/models/res_users.py b/fieldservice_mobile/models/res_users.py
new file mode 100644
index 000000000..b21eba128
--- /dev/null
+++ b/fieldservice_mobile/models/res_users.py
@@ -0,0 +1,27 @@
+# Copyright (C) 2020 Open Source Integrators
+# Copyright (C) 2020 Serpent Consulting Services Pvt. Ltd.
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from odoo import api, models
+
+
+class Users(models.Model):
+    _inherit = "res.users"
+
+    @api.model
+    def get_portal_config_values(self, config_parameters=False):
+        if not config_parameters:
+            config_parameters = []
+        params_dict = {}
+        group_params = [
+            "fieldservice_mobile.fsm_allow_portal_view_move_qty",
+            "fieldservice_mobile.fsm_allow_portal_update_move_qty",
+            "fieldservice_mobile.fsm_allow_portal_validate_move_qty",
+            "fieldservice_sale_order_line.fsm_allow_portal_view_sol_qty",
+            "fieldservice_sale_order_line.fsm_allow_portal_update_sol_qty",
+        ]
+        for config_param in config_parameters:
+            if config_param in group_params:
+                params = self.env["ir.config_parameter"].sudo()
+                params_dict.update({config_param: bool(params.get_param(config_param))})
+        return params_dict
diff --git a/fieldservice_mobile/security/ir.model.access.csv b/fieldservice_mobile/security/ir.model.access.csv
new file mode 100644
index 000000000..eb8c94400
--- /dev/null
+++ b/fieldservice_mobile/security/ir.model.access.csv
@@ -0,0 +1,27 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_res_territory_portal,access.res.territory.portal,base_territory.model_res_territory,base.group_portal,1,0,0,0
+access_res_branch_portal,access.res.branch.portal,base_territory.model_res_branch,base.group_portal,1,0,0,0
+access_res_district_portal,access.res.district.portal,base_territory.model_res_district,base.group_portal,1,0,0,0
+access_res_region_portal,access.res.region.portal,base_territory.model_res_region,base.group_portal,1,0,0,0
+access_fsm_stage_portal,access.fsm.stage.portal,fieldservice.model_fsm_stage,base.group_portal,1,0,0,0
+access_fsm_tag_portal,access.fsm.tag.portal,fieldservice.model_fsm_tag,base.group_portal,1,0,0,0
+access_fsm_person_portal,access.fsm.person.portal,fieldservice.model_fsm_person,base.group_portal,1,1,0,0
+access_fsm_location_portal,access.fsm.location.portal,fieldservice.model_fsm_location,base.group_portal,1,0,0,0
+access_fsm_order_portal,access.fsm.order.portal,fieldservice.model_fsm_order,base.group_portal,1,1,0,0
+access_fsm_equipment_portal,access.fsm.equipment.portal,fieldservice.model_fsm_equipment,base.group_portal,1,0,0,0
+access_fsm_category_portal,access.fsm.category.portal,fieldservice.model_fsm_category,base.group_portal,1,0,0,0
+access_fsm_template_portal,access.fsm.template.portal,fieldservice.model_fsm_template,base.group_portal,1,0,0,0
+access_fsm_team_portal,access.fsm.team.portal,fieldservice.model_fsm_team,base.group_portal,1,0,0,0
+access_fsm_location_person_portal,access.fsm.location.person.portal,fieldservice.model_fsm_location_person,base.group_portal,1,0,0,0
+access_fsm_order_type_portal,access.fsm.order.type.portal,fieldservice.model_fsm_order_type,base.group_portal,1,0,0,0
+access_fsm_stage_history_fsm_user,fsm.stage.history.user,model_fsm_stage_history,fieldservice.group_fsm_user,1,1,1,0
+access_fsm_stage_history_fsm_manager,fsm.stage.history.manager,model_fsm_stage_history,fieldservice.group_fsm_manager,1,1,1,1
+access_fsm_stage_history_portal,fsm.stage.history.portal,model_fsm_stage_history,base.group_portal,1,1,1,0
+stock.access_stock_move_line_portal,stock.move.line portal,stock.model_stock_move_line,base.group_portal,1,0,1,0
+access_stock_location_portal,access.stock.location.portal,stock.model_stock_location,base.group_portal,1,0,0,0
+access_stock_warehouse_portal,access.stock.warehouse.portal,stock.model_stock_warehouse,base.group_portal,1,0,0,0
+access_account_analytic_line_portal,access.account.analytic.line.portal,analytic.model_account_analytic_line,base.group_portal,1,0,0,0
+access_stock_picking_type_portal,access.stock.picking.type.portal,stock.model_stock_picking_type,base.group_portal,1,0,0,0
+access_fsm_vehicle_portal,access.fsm.vehicle.portal,fieldservice_vehicle.model_fsm_vehicle,base.group_portal,1,0,0,0
+access_maintenance_equipment_portal,access.maintenance.equipment.portal,maintenance.model_maintenance_equipment,base.group_portal,1,0,0,0
+access_ir_attachment_portal,access.ir.attachment.portal,base.model_ir_attachment,base.group_portal,1,0,0,0
diff --git a/fieldservice_mobile/security/ir_rule.xml b/fieldservice_mobile/security/ir_rule.xml
new file mode 100644
index 000000000..15cd94e2c
--- /dev/null
+++ b/fieldservice_mobile/security/ir_rule.xml
@@ -0,0 +1,16 @@
+<odoo noupdate="1">
+
+    <record id="portal_partner_comp_rule" model="ir.rule">
+        <field name="name">Portal Partner multi-company</field>
+        <field name="model_id" ref="base.model_res_partner" />
+        <field name="global" eval="True" />
+        <field
+            name="domain_force"
+        >['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
+        <field name="groups" eval="[(4, ref('base.group_portal'))]" />
+        <field name="perm_create" eval="False" />
+        <field name="perm_write" eval="False" />
+        <field name="perm_unlink" eval="False" />
+    </record>
+
+</odoo>
diff --git a/fieldservice_mobile/static/description/icon.png b/fieldservice_mobile/static/description/icon.png
new file mode 100644
index 000000000..955674d8f
Binary files /dev/null and b/fieldservice_mobile/static/description/icon.png differ
diff --git a/fieldservice_mobile/views/fsm_order_view.xml b/fieldservice_mobile/views/fsm_order_view.xml
new file mode 100644
index 000000000..0878feedf
--- /dev/null
+++ b/fieldservice_mobile/views/fsm_order_view.xml
@@ -0,0 +1,38 @@
+<odoo>
+
+    <record id="view_fsm_order_view_form_inherit_mobile" model="ir.ui.view">
+        <field name="name">view.fsm.order.inherit.mobile</field>
+        <field name="model">fsm.order</field>
+        <field name="inherit_id" ref="fieldservice.fsm_order_form" />
+        <field name="arch" type="xml">
+            <xpath expr="//field[@name='stage_id']" position="attributes">
+                <attribute name="domain">[('stage_type', '=', 'order'),
+                                          ('team_ids', 'in', (team_id, False)),
+                                          ('is_display_in_odoo', '=', True)]</attribute>
+            </xpath>
+            <field name="duration" position="attributes">
+                <attribute name="widget">float_time</attribute>
+            </field>
+            <xpath
+                expr="//notebook/page[@name='execution_page']/group"
+                position="after"
+            >
+                <group string="Stages History">
+                    <field
+                        name="fsm_stage_history_ids"
+                        nolabel="1"
+                        readonly="1"
+                    >
+                        <tree editable="bottom">
+                            <field name="start_datetime" required="1" />
+                            <field name="stage_id" required="1" />
+                            <field name="duration" widget="float_time" />
+                            <field name="total_duration" widget="float_time" />
+                        </tree>
+                    </field>
+                </group>
+            </xpath>
+        </field>
+    </record>
+
+</odoo>
diff --git a/fieldservice_mobile/views/fsm_stage_view.xml b/fieldservice_mobile/views/fsm_stage_view.xml
new file mode 100644
index 000000000..d4bdee192
--- /dev/null
+++ b/fieldservice_mobile/views/fsm_stage_view.xml
@@ -0,0 +1,15 @@
+<odoo>
+
+    <record id="fsm_stage_form_view_inherit_mobile" model="ir.ui.view">
+        <field name="name">fsm.stage.form.inherit.mobile</field>
+        <field name="model">fsm.stage</field>
+        <field name="inherit_id" ref="fieldservice.fsm_stage_form_view" />
+        <field name="arch" type="xml">
+            <field name="is_default" position="after">
+                <field name="is_display_in_mobile" />
+                <field name="is_display_in_odoo" />
+            </field>
+        </field>
+    </record>
+
+</odoo>
diff --git a/fieldservice_mobile/views/res_config_settings.xml b/fieldservice_mobile/views/res_config_settings.xml
new file mode 100644
index 000000000..b15c8f4fc
--- /dev/null
+++ b/fieldservice_mobile/views/res_config_settings.xml
@@ -0,0 +1,45 @@
+<odoo>
+
+    <record id="res_config_settings_view_form_mobile" model="ir.ui.view">
+        <field name="name">res.config.settings.view.form.fsm.mobile</field>
+        <field name="model">res.config.settings</field>
+        <field name="priority" eval="40" />
+        <field
+            name="inherit_id"
+            ref="fieldservice.res_config_settings_view_form"
+        />
+        <field name="arch" type="xml">
+            <div id="orders" position="inside">
+                <div class="col-xs-12 col-md-6 o_setting_box">
+                    <div class="o_setting_left_pane">
+                        <field name="fsm_allow_portal_view_move_qty" />
+                    </div>
+                    <div class="o_setting_right_pane">
+                        <label
+                            for="fsm_allow_portal_view_move_qty"
+                            string="Allow portal user to view stock move quantities"
+                        />
+                        <div class="text-muted">
+                            Allow portal user to view stock move quantities
+                        </div>
+                    </div>
+                </div>
+                <div class="col-xs-12 col-md-6 o_setting_box">
+                    <div class="o_setting_left_pane">
+                        <field name="fsm_allow_portal_update_move_qty" />
+                    </div>
+                    <div class="o_setting_right_pane">
+                        <label
+                            for="fsm_allow_portal_update_move_qty"
+                            string="Allow portal user update of stock move quantities"
+                        />
+                        <div class="text-muted">
+                            Allow portal user update of stock move quantities
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </field>
+    </record>
+
+</odoo>
diff --git a/fieldservice_sign/README.rst b/fieldservice_sign/README.rst
new file mode 100644
index 000000000..1c752e52e
--- /dev/null
+++ b/fieldservice_sign/README.rst
@@ -0,0 +1,31 @@
+.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
+   :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+   :alt: License: LGPL-3
+
+=======================
+Field Service Signature
+=======================
+
+This module will provide Signature tab and link in FSM order.
+
+Usage
+=====
+
+* Go to Sign << Template
+* Click on Send a Request or UPLOAD A PDF TEMPLATE button
+* Create a Template and during send the request select FSM order
+
+Signature related to orders will be linked in perticular order Signature Tab.
+
+Credits
+=======
+
+* Open Source Integrators <https://opensourceintegrators.com>
+* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
+
+Contributors
+~~~~~~~~~~~~
+
+* Wolfgang Hall <whall@opensourceintegrators.com>
+* Maxime Chambreuil <mchambreuil@opensourceintegrators.com>
+* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
diff --git a/fieldservice_sign/__init__.py b/fieldservice_sign/__init__.py
new file mode 100644
index 000000000..4d7a49b5e
--- /dev/null
+++ b/fieldservice_sign/__init__.py
@@ -0,0 +1,4 @@
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from . import models
+from . import wizard
diff --git a/fieldservice_sign/__manifest__.py b/fieldservice_sign/__manifest__.py
new file mode 100644
index 000000000..544b53ab7
--- /dev/null
+++ b/fieldservice_sign/__manifest__.py
@@ -0,0 +1,23 @@
+# Copyright (C) 2019 Open Source Integrators
+# Copyright (C) 2019 Serpent Consulting Services Pvt. Ltd.
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+{
+    "name": "Field Service Signature",
+    "summary": "This module will provide signature link from FSM order.",
+    "license": "AGPL-3",
+    "version": "14.0.1.0.0",
+    "category": "Field Service",
+    "author": "Open Source Integrators",
+    "website": "https://github.com/ursais/osi-addons",
+    "depends": ["fieldservice", "sign"],
+    "data": [
+        "security/ir.model.access.csv",
+        "views/fsm_order.xml",
+        "views/sign_request.xml",
+        "wizard/sign_send_request_views.xml",
+    ],
+    "development_status": "Beta",
+    "maintainers": ["wolfhall", "max3903"],
+    "installable": True,
+}
diff --git a/fieldservice_sign/models/__init__.py b/fieldservice_sign/models/__init__.py
new file mode 100644
index 000000000..8e00c6e9d
--- /dev/null
+++ b/fieldservice_sign/models/__init__.py
@@ -0,0 +1,4 @@
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from . import fsm_order
+from . import sign_request
diff --git a/fieldservice_sign/models/fsm_order.py b/fieldservice_sign/models/fsm_order.py
new file mode 100644
index 000000000..39bd215d6
--- /dev/null
+++ b/fieldservice_sign/models/fsm_order.py
@@ -0,0 +1,13 @@
+# Copyright (C) 2019 Open Source Integrators
+# Copyright (C) 2019 Serpent Consulting Services Pvt. Ltd.
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from odoo import fields, models
+
+
+class FSMOrder(models.Model):
+    _inherit = "fsm.order"
+
+    sign_request_ids = fields.One2many(
+        "sign.request", "fsm_order_id", string="Requested Signatures"
+    )
diff --git a/fieldservice_sign/models/sign_request.py b/fieldservice_sign/models/sign_request.py
new file mode 100644
index 000000000..ba498f25e
--- /dev/null
+++ b/fieldservice_sign/models/sign_request.py
@@ -0,0 +1,28 @@
+# Copyright (C) 2019 Open Source Integrators
+# Copyright (C) 2019 Serpent Consulting Services Pvt. Ltd.
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from werkzeug.urls import url_join
+
+from odoo import api, fields, models
+
+
+class SignRequest(models.Model):
+    _inherit = "sign.request"
+
+    fsm_order_id = fields.Many2one("fsm.order", "FSM Order")
+    url_link = fields.Char(compute="_compute_url_link", string="URL Link", store=True)
+
+    @api.depends("request_item_ids")
+    def _compute_url_link(self):
+        for signer in self.request_item_ids:
+            base_url = self.env["ir.config_parameter"].get_param("web.base.url")
+            url_link = url_join(
+                base_url,
+                "sign/document/%(request_id)s/%(access_token)s"
+                % {
+                    "request_id": signer.sign_request_id.id,
+                    "access_token": signer.access_token,
+                },
+            )
+            self.url_link = url_link
diff --git a/fieldservice_sign/security/ir.model.access.csv b/fieldservice_sign/security/ir.model.access.csv
new file mode 100644
index 000000000..e8171a02a
--- /dev/null
+++ b/fieldservice_sign/security/ir.model.access.csv
@@ -0,0 +1,4 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_sign_request_manager,access.sign.request.manager,model_sign_request,fieldservice.group_fsm_manager,1,1,1,1
+access_sign_request_portal,access.sign.request.portal,model_sign_request,base.group_portal,1,0,0,0
+access_sign_request_item_portal,access.sign.request.item.portal,sign.model_sign_request_item,base.group_portal,1,0,0,0
diff --git a/fieldservice_sign/static/description/icon.png b/fieldservice_sign/static/description/icon.png
new file mode 100644
index 000000000..955674d8f
Binary files /dev/null and b/fieldservice_sign/static/description/icon.png differ
diff --git a/fieldservice_sign/static/description/index.html b/fieldservice_sign/static/description/index.html
new file mode 100644
index 000000000..457ac7ac1
--- /dev/null
+++ b/fieldservice_sign/static/description/index.html
@@ -0,0 +1,432 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.14: http://docutils.sourceforge.net/" />
+<title>Field Service Signature</title>
+<style type="text/css">
+
+/*
+:Author: David Goodger (goodger@python.org)
+:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
+:Copyright: This stylesheet has been placed in the public domain.
+
+Default cascading style sheet for the HTML output of Docutils.
+
+See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
+customize this style sheet.
+*/
+
+/* used to remove borders from tables and images */
+.borderless, table.borderless td, table.borderless th {
+  border: 0 }
+
+table.borderless td, table.borderless th {
+  /* Override padding for "table.docutils td" with "! important".
+     The right padding separates the table cells. */
+  padding: 0 0.5em 0 0 ! important }
+
+.first {
+  /* Override more specific margin styles with "! important". */
+  margin-top: 0 ! important }
+
+.last, .with-subtitle {
+  margin-bottom: 0 ! important }
+
+.hidden {
+  display: none }
+
+.subscript {
+  vertical-align: sub;
+  font-size: smaller }
+
+.superscript {
+  vertical-align: super;
+  font-size: smaller }
+
+a.toc-backref {
+  text-decoration: none ;
+  color: black }
+
+blockquote.epigraph {
+  margin: 2em 5em ; }
+
+dl.docutils dd {
+  margin-bottom: 0.5em }
+
+object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
+  overflow: hidden;
+}
+
+/* Uncomment (and remove this text!) to get bold-faced definition list terms
+dl.docutils dt {
+  font-weight: bold }
+*/
+
+div.abstract {
+  margin: 2em 5em }
+
+div.abstract p.topic-title {
+  font-weight: bold ;
+  text-align: center }
+
+div.admonition, div.attention, div.caution, div.danger, div.error,
+div.hint, div.important, div.note, div.tip, div.warning {
+  margin: 2em ;
+  border: medium outset ;
+  padding: 1em }
+
+div.admonition p.admonition-title, div.hint p.admonition-title,
+div.important p.admonition-title, div.note p.admonition-title,
+div.tip p.admonition-title {
+  font-weight: bold ;
+  font-family: sans-serif }
+
+div.attention p.admonition-title, div.caution p.admonition-title,
+div.danger p.admonition-title, div.error p.admonition-title,
+div.warning p.admonition-title, .code .error {
+  color: red ;
+  font-weight: bold ;
+  font-family: sans-serif }
+
+/* Uncomment (and remove this text!) to get reduced vertical space in
+   compound paragraphs.
+div.compound .compound-first, div.compound .compound-middle {
+  margin-bottom: 0.5em }
+
+div.compound .compound-last, div.compound .compound-middle {
+  margin-top: 0.5em }
+*/
+
+div.dedication {
+  margin: 2em 5em ;
+  text-align: center ;
+  font-style: italic }
+
+div.dedication p.topic-title {
+  font-weight: bold ;
+  font-style: normal }
+
+div.figure {
+  margin-left: 2em ;
+  margin-right: 2em }
+
+div.footer, div.header {
+  clear: both;
+  font-size: smaller }
+
+div.line-block {
+  display: block ;
+  margin-top: 1em ;
+  margin-bottom: 1em }
+
+div.line-block div.line-block {
+  margin-top: 0 ;
+  margin-bottom: 0 ;
+  margin-left: 1.5em }
+
+div.sidebar {
+  margin: 0 0 0.5em 1em ;
+  border: medium outset ;
+  padding: 1em ;
+  background-color: #ffffee ;
+  width: 40% ;
+  float: right ;
+  clear: right }
+
+div.sidebar p.rubric {
+  font-family: sans-serif ;
+  font-size: medium }
+
+div.system-messages {
+  margin: 5em }
+
+div.system-messages h1 {
+  color: red }
+
+div.system-message {
+  border: medium outset ;
+  padding: 1em }
+
+div.system-message p.system-message-title {
+  color: red ;
+  font-weight: bold }
+
+div.topic {
+  margin: 2em }
+
+h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
+h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
+  margin-top: 0.4em }
+
+h1.title {
+  text-align: center }
+
+h2.subtitle {
+  text-align: center }
+
+hr.docutils {
+  width: 75% }
+
+img.align-left, .figure.align-left, object.align-left, table.align-left {
+  clear: left ;
+  float: left ;
+  margin-right: 1em }
+
+img.align-right, .figure.align-right, object.align-right, table.align-right {
+  clear: right ;
+  float: right ;
+  margin-left: 1em }
+
+img.align-center, .figure.align-center, object.align-center {
+  display: block;
+  margin-left: auto;
+  margin-right: auto;
+}
+
+table.align-center {
+  margin-left: auto;
+  margin-right: auto;
+}
+
+.align-left {
+  text-align: left }
+
+.align-center {
+  clear: both ;
+  text-align: center }
+
+.align-right {
+  text-align: right }
+
+/* reset inner alignment in figures */
+div.align-right {
+  text-align: inherit }
+
+/* div.align-center * { */
+/*   text-align: left } */
+
+.align-top    {
+  vertical-align: top }
+
+.align-middle {
+  vertical-align: middle }
+
+.align-bottom {
+  vertical-align: bottom }
+
+ol.simple, ul.simple {
+  margin-bottom: 1em }
+
+ol.arabic {
+  list-style: decimal }
+
+ol.loweralpha {
+  list-style: lower-alpha }
+
+ol.upperalpha {
+  list-style: upper-alpha }
+
+ol.lowerroman {
+  list-style: lower-roman }
+
+ol.upperroman {
+  list-style: upper-roman }
+
+p.attribution {
+  text-align: right ;
+  margin-left: 50% }
+
+p.caption {
+  font-style: italic }
+
+p.credits {
+  font-style: italic ;
+  font-size: smaller }
+
+p.label {
+  white-space: nowrap }
+
+p.rubric {
+  font-weight: bold ;
+  font-size: larger ;
+  color: maroon ;
+  text-align: center }
+
+p.sidebar-title {
+  font-family: sans-serif ;
+  font-weight: bold ;
+  font-size: larger }
+
+p.sidebar-subtitle {
+  font-family: sans-serif ;
+  font-weight: bold }
+
+p.topic-title {
+  font-weight: bold }
+
+pre.address {
+  margin-bottom: 0 ;
+  margin-top: 0 ;
+  font: inherit }
+
+pre.literal-block, pre.doctest-block, pre.math, pre.code {
+  margin-left: 2em ;
+  margin-right: 2em }
+
+pre.code .ln { color: grey; } /* line numbers */
+pre.code, code { background-color: #eeeeee }
+pre.code .comment, code .comment { color: #5C6576 }
+pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
+pre.code .literal.string, code .literal.string { color: #0C5404 }
+pre.code .name.builtin, code .name.builtin { color: #352B84 }
+pre.code .deleted, code .deleted { background-color: #DEB0A1}
+pre.code .inserted, code .inserted { background-color: #A3D289}
+
+span.classifier {
+  font-family: sans-serif ;
+  font-style: oblique }
+
+span.classifier-delimiter {
+  font-family: sans-serif ;
+  font-weight: bold }
+
+span.interpreted {
+  font-family: sans-serif }
+
+span.option {
+  white-space: nowrap }
+
+span.pre {
+  white-space: pre }
+
+span.problematic {
+  color: red }
+
+span.section-subtitle {
+  /* font-size relative to parent (h1..h6 element) */
+  font-size: 80% }
+
+table.citation {
+  border-left: solid 1px gray;
+  margin-left: 1px }
+
+table.docinfo {
+  margin: 2em 4em }
+
+table.docutils {
+  margin-top: 0.5em ;
+  margin-bottom: 0.5em }
+
+table.footnote {
+  border-left: solid 1px black;
+  margin-left: 1px }
+
+table.docutils td, table.docutils th,
+table.docinfo td, table.docinfo th {
+  padding-left: 0.5em ;
+  padding-right: 0.5em ;
+  vertical-align: top }
+
+table.docutils th.field-name, table.docinfo th.docinfo-name {
+  font-weight: bold ;
+  text-align: left ;
+  white-space: nowrap ;
+  padding-left: 0 }
+
+/* "booktabs" style (no vertical lines) */
+table.docutils.booktabs {
+  border: 0px;
+  border-top: 2px solid;
+  border-bottom: 2px solid;
+  border-collapse: collapse;
+}
+table.docutils.booktabs * {
+  border: 0px;
+}
+table.docutils.booktabs th {
+  border-bottom: thin solid;
+  text-align: left;
+}
+
+h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
+h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
+  font-size: 100% }
+
+ul.auto-toc {
+  list-style-type: none }
+
+</style>
+</head>
+<body>
+<div class="document" id="field-service-signature">
+<h1 class="title">Field Service Signature</h1>
+
+<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!! This file is generated by oca-gen-addon-readme !!
+!! changes will be overwritten.                   !!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
+<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/field-service/tree/13.0/fieldservice_sign"><img alt="OCA/field-service" src="https://img.shields.io/badge/github-OCA%2Ffield--service-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/field-service-13-0/field-service-13-0-fieldservice_sign"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/264/13.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
+<p>This module will provide signature link from FSM order.</p>
+<p><strong>Table of contents</strong></p>
+<div class="contents local topic" id="contents">
+<ul class="simple">
+<li><a class="reference internal" href="#bug-tracker" id="id1">Bug Tracker</a></li>
+<li><a class="reference internal" href="#credits" id="id2">Credits</a><ul>
+<li><a class="reference internal" href="#authors" id="id3">Authors</a></li>
+<li><a class="reference internal" href="#contributors" id="id4">Contributors</a></li>
+<li><a class="reference internal" href="#other-credits" id="id5">Other credits</a></li>
+<li><a class="reference internal" href="#maintainers" id="id6">Maintainers</a></li>
+</ul>
+</li>
+</ul>
+</div>
+<div class="section" id="bug-tracker">
+<h1><a class="toc-backref" href="#id1">Bug Tracker</a></h1>
+<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/field-service/issues">GitHub Issues</a>.
+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
+<a class="reference external" href="https://github.com/OCA/field-service/issues/new?body=module:%20fieldservice_sign%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
+<p>Do not contact contributors directly about support or help with technical issues.</p>
+</div>
+<div class="section" id="credits">
+<h1><a class="toc-backref" href="#id2">Credits</a></h1>
+<div class="section" id="authors">
+<h2><a class="toc-backref" href="#id3">Authors</a></h2>
+<ul class="simple">
+<li>Open Source Integrators</li>
+</ul>
+</div>
+<div class="section" id="contributors">
+<h2><a class="toc-backref" href="#id4">Contributors</a></h2>
+<ul class="simple">
+<li>Wolfgang Hall &lt;<a class="reference external" href="mailto:whall&#64;opensourceintegrators.com">whall&#64;opensourceintegrators.com</a>&gt;</li>
+<li>Maxime Chambreuil &lt;<a class="reference external" href="mailto:mchambreuil&#64;opensourceintegrators.com">mchambreuil&#64;opensourceintegrators.com</a>&gt;</li>
+<li>Serpent Consulting Services Pvt. Ltd. &lt;<a class="reference external" href="mailto:support&#64;serpentcs.com">support&#64;serpentcs.com</a>&gt;</li>
+</ul>
+</div>
+<div class="section" id="other-credits">
+<h2><a class="toc-backref" href="#id5">Other credits</a></h2>
+<p>The development of this module has been financially supported by:</p>
+<ul class="simple">
+<li>Open Source Integrators &lt;<a class="reference external" href="https://opensourceintegrators.com">https://opensourceintegrators.com</a>&gt;</li>
+<li>Serpent Consulting Services Pvt. Ltd. &lt;<a class="reference external" href="mailto:support&#64;serpentcs.com">support&#64;serpentcs.com</a>&gt;</li>
+</ul>
+</div>
+<div class="section" id="maintainers">
+<h2><a class="toc-backref" href="#id6">Maintainers</a></h2>
+<p>This module is maintained by the OCA.</p>
+<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
+<p>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.</p>
+<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainers</a>:</p>
+<p><a class="reference external" href="https://github.com/wolfhall"><img alt="wolfhall" src="https://github.com/wolfhall.png?size=40px" /></a> <a class="reference external" href="https://github.com/max3903"><img alt="max3903" src="https://github.com/max3903.png?size=40px" /></a></p>
+<p>This module is part of the <a class="reference external" href="https://github.com/OCA/field-service/tree/13.0/fieldservice_sign">OCA/field-service</a> project on GitHub.</p>
+<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
+</div>
+</div>
+</div>
+</body>
+</html>
diff --git a/fieldservice_sign/views/fsm_order.xml b/fieldservice_sign/views/fsm_order.xml
new file mode 100644
index 000000000..a811b1eae
--- /dev/null
+++ b/fieldservice_sign/views/fsm_order.xml
@@ -0,0 +1,15 @@
+<odoo>
+
+    <record id="view_fsm_order_form_inherit_sign" model="ir.ui.view">
+        <field name="model">fsm.order</field>
+        <field name="inherit_id" ref="fieldservice.fsm_order_form" />
+        <field name="arch" type="xml">
+            <notebook position="inside">
+                <page name="signature" string="Signed Documents">
+                    <field name="sign_request_ids" />
+                </page>
+            </notebook>
+        </field>
+    </record>
+
+</odoo>
diff --git a/fieldservice_sign/views/sign_request.xml b/fieldservice_sign/views/sign_request.xml
new file mode 100644
index 000000000..88c0f0338
--- /dev/null
+++ b/fieldservice_sign/views/sign_request.xml
@@ -0,0 +1,17 @@
+<odoo>
+
+    <record id="sign_request_view_form_inherit" model="ir.ui.view">
+        <field name="name">sign.request.form</field>
+        <field name="model">sign.request</field>
+        <field name="inherit_id" ref="sign.sign_request_view_form" />
+        <field name="arch" type="xml">
+            <field name="request_item_ids" position="before">
+                <group>
+                    <field name="fsm_order_id" />
+                    <field name="url_link" widget="url" />
+                </group>
+            </field>
+        </field>
+    </record>
+
+</odoo>
diff --git a/fieldservice_sign/wizard/__init__.py b/fieldservice_sign/wizard/__init__.py
new file mode 100644
index 000000000..433d2cfcc
--- /dev/null
+++ b/fieldservice_sign/wizard/__init__.py
@@ -0,0 +1,3 @@
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from . import sign_send_request
diff --git a/fieldservice_sign/wizard/sign_send_request.py b/fieldservice_sign/wizard/sign_send_request.py
new file mode 100644
index 000000000..72dbc7512
--- /dev/null
+++ b/fieldservice_sign/wizard/sign_send_request.py
@@ -0,0 +1,19 @@
+# Copyright (C) 2019 Open Source Integrators
+# Copyright (C) 2019 Serpent Consulting Services Pvt. Ltd.
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+
+from odoo import fields, models
+
+
+class SignSendRequest(models.TransientModel):
+    _inherit = "sign.send.request"
+
+    fsm_order_id = fields.Many2one("fsm.order", "FSM Order")
+
+    def send_request(self):
+        res = super(SignSendRequest, self).send_request()
+        if res.get("context") and self.fsm_order_id:
+            request = self.env["sign.request"].browse(res.get("context").get("id"))
+            request.fsm_order_id = self.fsm_order_id.id
+        return res
diff --git a/fieldservice_sign/wizard/sign_send_request_views.xml b/fieldservice_sign/wizard/sign_send_request_views.xml
new file mode 100644
index 000000000..3a8b3165d
--- /dev/null
+++ b/fieldservice_sign/wizard/sign_send_request_views.xml
@@ -0,0 +1,14 @@
+<odoo>
+
+    <record id="sign_send_request_view_form_inherit" model="ir.ui.view">
+        <field name="name">sign.send.request.view.form</field>
+        <field name="model">sign.send.request</field>
+        <field name="inherit_id" ref="sign.sign_send_request_view_form" />
+        <field name="arch" type="xml">
+            <field name="signer_id" position="after">
+                <field name="fsm_order_id" />
+            </field>
+        </field>
+    </record>
+
+</odoo>
diff --git a/fieldservice_tracking/README.rst b/fieldservice_tracking/README.rst
new file mode 100644
index 000000000..44e9d0706
--- /dev/null
+++ b/fieldservice_tracking/README.rst
@@ -0,0 +1,21 @@
+.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
+   :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+   :alt: License: LGPL-3
+
+======================
+Field Service Tracking
+======================
+
+This module will add tracking functionality in Fieldservice.
+
+Credits
+=======
+
+* Open Source Integrators <https://opensourceintegrators.com>
+* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
+
+Contributors
+~~~~~~~~~~~~
+
+* Wolfgang Hall <whall@opensourceintegrators.com>
+* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
diff --git a/fieldservice_tracking/__init__.py b/fieldservice_tracking/__init__.py
new file mode 100644
index 000000000..02179fb04
--- /dev/null
+++ b/fieldservice_tracking/__init__.py
@@ -0,0 +1,2 @@
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+from . import models
diff --git a/fieldservice_tracking/__manifest__.py b/fieldservice_tracking/__manifest__.py
new file mode 100644
index 000000000..1d50d299d
--- /dev/null
+++ b/fieldservice_tracking/__manifest__.py
@@ -0,0 +1,27 @@
+# Copyright (C) 2021 Open Source Integrators
+# Copyright (C) 2021 Serpent Consulting Services Pvt. Ltd.
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+{
+    "name": "Field Service Tracking",
+    "summary": "This module will add tracking functionality in Fieldservice.",
+    "license": "AGPL-3",
+    "version": "14.0.1.0.0",
+    "category": "Field Service",
+    "author": "Open Source Integrators",
+    "website": "https://github.com/ursais/osi-addons",
+    "depends": [
+        "fieldservice_substatus",
+        "uom",
+    ],
+    "data": [
+        "security/fsm_tracking_group.xml",
+        "security/ir.model.access.csv",
+        "views/fsm_person_view.xml",
+        "views/fsm_stage_view.xml",
+    ],
+    "installable": True,
+    "development_status": "Beta",
+    "maintainers": [
+        "wolfhall",
+    ],
+}
diff --git a/fieldservice_tracking/models/__init__.py b/fieldservice_tracking/models/__init__.py
new file mode 100644
index 000000000..096d26710
--- /dev/null
+++ b/fieldservice_tracking/models/__init__.py
@@ -0,0 +1,4 @@
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+from . import fsm_person
+from . import fsm_tracking
+from . import fsm_stage
diff --git a/fieldservice_tracking/models/fsm_person.py b/fieldservice_tracking/models/fsm_person.py
new file mode 100644
index 000000000..cf22cb8a4
--- /dev/null
+++ b/fieldservice_tracking/models/fsm_person.py
@@ -0,0 +1,34 @@
+# Copyright (C) 2021 Open Source Integrators
+# Copyright (C) 2021 Serpent Consulting Services Pvt. Ltd.
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+from odoo import fields, models
+
+
+class FsmPerson(models.Model):
+    _inherit = "fsm.person"
+
+    worker_allow_tracking = fields.Boolean("Worker Allow Tracking")
+    track_lat = fields.Float("Last known latitude", digits=(16, 5))
+    track_long = fields.Float("Last known longitude", digits=(16, 5))
+    # track_shape = fields.Char('Last known location')
+    loc_rad = fields.Float("Last known location accuracy radius", digits=(16, 5))
+    loc_time = fields.Datetime("Last location ping")
+    rad_uom = fields.Many2one("uom.uom", "Unit of measure")
+
+    # only visible to dispatchers
+    match_rad = fields.Integer("Max allowed distance")
+    track_intv_coarse = fields.Integer("Time in seconds")
+    fence_rad = fields.Integer("Distance to Destination")
+    route_stage = fields.Selection(
+        [
+            ("out", "Out"),
+            ("checkin", "Check-in"),
+            ("enroute", "Enroute"),
+            ("jobstart", "Job Start"),
+            ("working", "Working"),
+            ("jobstop", "Job Stop"),
+            ("checkout", "Check-out"),
+            ("break", "Break"),
+        ],
+        string="Route Stage",
+    )
diff --git a/fieldservice_tracking/models/fsm_stage.py b/fieldservice_tracking/models/fsm_stage.py
new file mode 100644
index 000000000..c396e81f8
--- /dev/null
+++ b/fieldservice_tracking/models/fsm_stage.py
@@ -0,0 +1,14 @@
+# Copyright (C) 2021 Open Source Integrators
+# Copyright (C) 2021 Serpent Consulting Services Pvt. Ltd.
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+from odoo import fields, models
+
+
+class FSMStage(models.Model):
+    _inherit = "fsm.stage"
+
+    start_tracking = fields.Boolean("Start Tracking")
+    stop_tracking = fields.Boolean("Stop Tracking")
+    notify_customer = fields.Boolean("Notify Customer")
+    notify_dispatcher = fields.Boolean("Notify Dispatcher")
+    distance_to_next_stop = fields.Boolean("Compare Distance to next stop")
diff --git a/fieldservice_tracking/models/fsm_tracking.py b/fieldservice_tracking/models/fsm_tracking.py
new file mode 100644
index 000000000..2493d5d20
--- /dev/null
+++ b/fieldservice_tracking/models/fsm_tracking.py
@@ -0,0 +1,20 @@
+# Copyright (C) 2021 Open Source Integrators
+# Copyright (C) 2021 Serpent Consulting Services Pvt. Ltd.
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+from odoo import fields, models
+
+
+class FsmTracking(models.Model):
+    _name = "fsm.tracking"
+    _description = "Fsm Tracking"
+
+    partner_id = fields.Many2one("fsm.person")
+    order_id = fields.Many2one("fsm.order")
+    latitude = fields.Float("Latitude")
+    longitude = fields.Float("Longitude")
+    # shape = fields.Char('Shape')
+    timestamp = fields.Datetime()
+    accuracy = fields.Float("Accuracy Radius")
+    route_stage = fields.Char("Route stage")
+    last_loc_age = fields.Integer("Time in seconds from last known tracking")
+    substatus = fields.Char("Order Substatus")
diff --git a/fieldservice_tracking/security/fsm_tracking_group.xml b/fieldservice_tracking/security/fsm_tracking_group.xml
new file mode 100644
index 000000000..f3887c8e6
--- /dev/null
+++ b/fieldservice_tracking/security/fsm_tracking_group.xml
@@ -0,0 +1,7 @@
+<odoo>
+
+    <record id="group_fsm_tracking_dispatcher" model="res.groups">
+        <field name="name">FSM Tracking Dispatcher</field>
+    </record>
+
+</odoo>
diff --git a/fieldservice_tracking/security/ir.model.access.csv b/fieldservice_tracking/security/ir.model.access.csv
new file mode 100644
index 000000000..6ca6e2453
--- /dev/null
+++ b/fieldservice_tracking/security/ir.model.access.csv
@@ -0,0 +1,4 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_fsm_tracking_user,fsm.tracking.user,model_fsm_tracking,fieldservice.group_fsm_user,1,1,1,0
+access_fsm_tracking_manager,fsm.tracking.manager,model_fsm_tracking,fieldservice.group_fsm_manager,1,1,1,1
+access_fsm_tracking_dispatcher,fsm.tracking.dispatcher,model_fsm_tracking,fieldservice_tracking.group_fsm_tracking_dispatcher,1,1,1,0
diff --git a/fieldservice_tracking/views/fsm_person_view.xml b/fieldservice_tracking/views/fsm_person_view.xml
new file mode 100644
index 000000000..35922f28e
--- /dev/null
+++ b/fieldservice_tracking/views/fsm_person_view.xml
@@ -0,0 +1,35 @@
+<odoo>
+    <record id="fieldservice_fsm_person_form_inherit" model="ir.ui.view">
+        <field name="name">fieldservice.fsm.person.form.inherit</field>
+        <field name="model">fsm.person</field>
+        <field name="inherit_id" ref="fieldservice.fsm_person_form" />
+        <field name="arch" type="xml">
+            <xpath expr="/form/sheet/notebook" position="inside">
+                <page name="fsm_tracking" string="Field Service Tracking">
+                    <group string="Last Update">
+                        <group>
+                            <field name="worker_allow_tracking" />
+                            <field name="loc_time" />
+                            <field name="rad_uom" />
+                            <!-- <field name="track_shape"/> -->
+                        </group>
+                        <group>
+                            <field name="track_lat" />
+                            <field name="track_long" />
+                            <field name="loc_rad" />
+                        </group>
+                    </group>
+                    <group
+                        col="4"
+                        groups="fieldservice_tracking.group_fsm_tracking_dispatcher"
+                    >
+                        <field name="match_rad" />
+                        <field name="track_intv_coarse" />
+                        <field name="fence_rad" />
+                        <field name="route_stage" />
+                    </group>
+                </page>
+            </xpath>
+        </field>
+    </record>
+</odoo>
diff --git a/fieldservice_tracking/views/fsm_stage_view.xml b/fieldservice_tracking/views/fsm_stage_view.xml
new file mode 100644
index 000000000..308828ffe
--- /dev/null
+++ b/fieldservice_tracking/views/fsm_stage_view.xml
@@ -0,0 +1,18 @@
+<odoo>
+
+    <record id="fsm_stage_form_view_inherit_tracking" model="ir.ui.view">
+        <field name="name">fsm.stage.form.inherit.tracking</field>
+        <field name="model">fsm.stage</field>
+        <field name="inherit_id" ref="fieldservice.fsm_stage_form_view" />
+        <field name="arch" type="xml">
+            <field name="is_default" position="after">
+                <field name="start_tracking" />
+                <field name="stop_tracking" />
+                <field name="notify_customer" />
+                <field name="notify_dispatcher" />
+                <field name="distance_to_next_stop" />
+            </field>
+        </field>
+    </record>
+
+</odoo>
diff --git a/helpdesk_delivery/README.rst b/helpdesk_delivery/README.rst
new file mode 100644
index 000000000..a772fef1c
--- /dev/null
+++ b/helpdesk_delivery/README.rst
@@ -0,0 +1,29 @@
+.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
+   :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+   :alt: License: LGPL-3
+
+===================
+Helpdesk - Delivery
+===================
+
+This module allows users to specify a delivery carrier on Helpdesk Tickets
+
+Usage
+=====
+
+* Go to Helpdesk
+* Create or select a ticket
+* On the Inventory Tab select a carrier
+
+To close a ticket, all the related service orders must be closed.
+
+Credits
+=======
+
+* Steven Campbell <scampbell@opensourceintegrators.com>
+* Freni Patel <fpatel@opensourceintegrators.com>
+
+Contributors
+------------
+
+* Open Source Integrators <contact@opensourceintegrators.com>
diff --git a/helpdesk_delivery/__init__.py b/helpdesk_delivery/__init__.py
new file mode 100644
index 000000000..ff8dc3cb9
--- /dev/null
+++ b/helpdesk_delivery/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import models
diff --git a/helpdesk_delivery/__manifest__.py b/helpdesk_delivery/__manifest__.py
new file mode 100644
index 000000000..3e1d1b344
--- /dev/null
+++ b/helpdesk_delivery/__manifest__.py
@@ -0,0 +1,23 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+{
+    "name": "Helpdesk - Delivery",
+    "summary": "Select delivery methods and carriers on Helpdesk Tickets",
+    "version": "14.0.1.0.0",
+    "category": "Helpdesk",
+    "author": "Open Source Integrators",
+    "website": "https://github.com/ursais/osi-addons",
+    "depends": [
+        "osi_helpdesk_stock",
+        "delivery",
+    ],
+    "data": [
+        "views/helpdesk_ticket.xml",
+    ],
+    "installable": True,
+    "auto_install": True,
+    "license": "LGPL-3",
+    "development_status": "Beta",
+    "maintainers": ["max3903", "osi-scampbell"],
+}
diff --git a/helpdesk_delivery/models/__init__.py b/helpdesk_delivery/models/__init__.py
new file mode 100644
index 000000000..39d7f534d
--- /dev/null
+++ b/helpdesk_delivery/models/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import helpdesk_ticket, stock_request, stock_move, stock_rule
diff --git a/helpdesk_delivery/models/helpdesk_ticket.py b/helpdesk_delivery/models/helpdesk_ticket.py
new file mode 100644
index 000000000..39988765c
--- /dev/null
+++ b/helpdesk_delivery/models/helpdesk_ticket.py
@@ -0,0 +1,10 @@
+# Copyright (C) 2021, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import fields, models
+
+
+class HelpdeskTicket(models.Model):
+    _inherit = "helpdesk.ticket"
+
+    carrier_id = fields.Many2one("delivery.carrier", string="Delivery Method")
diff --git a/helpdesk_delivery/models/stock_move.py b/helpdesk_delivery/models/stock_move.py
new file mode 100644
index 000000000..df3efbfe7
--- /dev/null
+++ b/helpdesk_delivery/models/stock_move.py
@@ -0,0 +1,16 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import fields, models
+
+
+class StockMove(models.Model):
+    _inherit = "stock.move"
+
+    helpdesk_ticket_id = fields.Many2one("helpdesk.ticket", string="Helpdesk Ticket")
+
+    def _get_new_picking_values(self):
+        vals = super(StockMove, self)._get_new_picking_values()
+        if not vals.get("carrier_id", False):
+            vals["carrier_id"] = self.helpdesk_ticket_id.carrier_id.id
+        return vals
diff --git a/helpdesk_delivery/models/stock_request.py b/helpdesk_delivery/models/stock_request.py
new file mode 100644
index 000000000..8e7098f76
--- /dev/null
+++ b/helpdesk_delivery/models/stock_request.py
@@ -0,0 +1,31 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import fields, models
+
+
+class StockRequest(models.Model):
+    _inherit = "stock.request"
+
+    carrier_id = fields.Many2one("delivery.carrier", string="Delivery Method")
+
+    def _prepare_procurement_values(self, group_id=False):
+        res = super()._prepare_procurement_values(group_id=group_id)
+        if not res.get("carrier_id", False):
+            res.update(
+                {
+                    "carrier_id": self.helpdesk_ticket_id.carrier_id.id or False,
+                }
+            )
+        return res
+
+    def _prepare_procurement_group_values(self):
+        if self.helpdesk_ticket_id:
+            order = self.env["helpdesk.ticket"].browse(self.helpdesk_ticket_id.id)
+            return {
+                "name": order.name,
+                "helpdesk_ticket_id": order.id,
+                "move_type": "direct",
+            }
+        else:
+            return {}
diff --git a/helpdesk_delivery/models/stock_rule.py b/helpdesk_delivery/models/stock_rule.py
new file mode 100644
index 000000000..198fdfa6b
--- /dev/null
+++ b/helpdesk_delivery/models/stock_rule.py
@@ -0,0 +1,31 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from odoo import models
+
+
+class StockRule(models.Model):
+    _inherit = "stock.rule"
+
+    def _get_stock_move_values(
+        self,
+        product_id,
+        product_qty,
+        product_uom,
+        location_id,
+        name,
+        origin,
+        company_id,
+        values,
+    ):
+        vals = super()._get_stock_move_values(
+            product_id,
+            product_qty,
+            product_uom,
+            location_id,
+            name,
+            origin,
+            company_id,
+            values,
+        )
+        vals.update({"helpdesk_ticket_id": values.get("helpdesk_ticket_id")})
+        return vals
diff --git a/helpdesk_delivery/static/description/icon.png b/helpdesk_delivery/static/description/icon.png
new file mode 100644
index 000000000..84791119f
Binary files /dev/null and b/helpdesk_delivery/static/description/icon.png differ
diff --git a/helpdesk_delivery/static/description/index.html b/helpdesk_delivery/static/description/index.html
new file mode 100644
index 000000000..59589f511
--- /dev/null
+++ b/helpdesk_delivery/static/description/index.html
@@ -0,0 +1,464 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils 0.15.1: http://docutils.sourceforge.net/" />
+<title>Field Service - Delivery</title>
+<style type="text/css">
+
+/*
+:Author: David Goodger (goodger@python.org)
+:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
+:Copyright: This stylesheet has been placed in the public domain.
+
+Default cascading style sheet for the HTML output of Docutils.
+
+See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
+customize this style sheet.
+*/
+
+/* used to remove borders from tables and images */
+.borderless, table.borderless td, table.borderless th {
+  border: 0 }
+
+table.borderless td, table.borderless th {
+  /* Override padding for "table.docutils td" with "! important".
+     The right padding separates the table cells. */
+  padding: 0 0.5em 0 0 ! important }
+
+.first {
+  /* Override more specific margin styles with "! important". */
+  margin-top: 0 ! important }
+
+.last, .with-subtitle {
+  margin-bottom: 0 ! important }
+
+.hidden {
+  display: none }
+
+.subscript {
+  vertical-align: sub;
+  font-size: smaller }
+
+.superscript {
+  vertical-align: super;
+  font-size: smaller }
+
+a.toc-backref {
+  text-decoration: none ;
+  color: black }
+
+blockquote.epigraph {
+  margin: 2em 5em ; }
+
+dl.docutils dd {
+  margin-bottom: 0.5em }
+
+object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
+  overflow: hidden;
+}
+
+/* Uncomment (and remove this text!) to get bold-faced definition list terms
+dl.docutils dt {
+  font-weight: bold }
+*/
+
+div.abstract {
+  margin: 2em 5em }
+
+div.abstract p.topic-title {
+  font-weight: bold ;
+  text-align: center }
+
+div.admonition, div.attention, div.caution, div.danger, div.error,
+div.hint, div.important, div.note, div.tip, div.warning {
+  margin: 2em ;
+  border: medium outset ;
+  padding: 1em }
+
+div.admonition p.admonition-title, div.hint p.admonition-title,
+div.important p.admonition-title, div.note p.admonition-title,
+div.tip p.admonition-title {
+  font-weight: bold ;
+  font-family: sans-serif }
+
+div.attention p.admonition-title, div.caution p.admonition-title,
+div.danger p.admonition-title, div.error p.admonition-title,
+div.warning p.admonition-title, .code .error {
+  color: red ;
+  font-weight: bold ;
+  font-family: sans-serif }
+
+/* Uncomment (and remove this text!) to get reduced vertical space in
+   compound paragraphs.
+div.compound .compound-first, div.compound .compound-middle {
+  margin-bottom: 0.5em }
+
+div.compound .compound-last, div.compound .compound-middle {
+  margin-top: 0.5em }
+*/
+
+div.dedication {
+  margin: 2em 5em ;
+  text-align: center ;
+  font-style: italic }
+
+div.dedication p.topic-title {
+  font-weight: bold ;
+  font-style: normal }
+
+div.figure {
+  margin-left: 2em ;
+  margin-right: 2em }
+
+div.footer, div.header {
+  clear: both;
+  font-size: smaller }
+
+div.line-block {
+  display: block ;
+  margin-top: 1em ;
+  margin-bottom: 1em }
+
+div.line-block div.line-block {
+  margin-top: 0 ;
+  margin-bottom: 0 ;
+  margin-left: 1.5em }
+
+div.sidebar {
+  margin: 0 0 0.5em 1em ;
+  border: medium outset ;
+  padding: 1em ;
+  background-color: #ffffee ;
+  width: 40% ;
+  float: right ;
+  clear: right }
+
+div.sidebar p.rubric {
+  font-family: sans-serif ;
+  font-size: medium }
+
+div.system-messages {
+  margin: 5em }
+
+div.system-messages h1 {
+  color: red }
+
+div.system-message {
+  border: medium outset ;
+  padding: 1em }
+
+div.system-message p.system-message-title {
+  color: red ;
+  font-weight: bold }
+
+div.topic {
+  margin: 2em }
+
+h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
+h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
+  margin-top: 0.4em }
+
+h1.title {
+  text-align: center }
+
+h2.subtitle {
+  text-align: center }
+
+hr.docutils {
+  width: 75% }
+
+img.align-left, .figure.align-left, object.align-left, table.align-left {
+  clear: left ;
+  float: left ;
+  margin-right: 1em }
+
+img.align-right, .figure.align-right, object.align-right, table.align-right {
+  clear: right ;
+  float: right ;
+  margin-left: 1em }
+
+img.align-center, .figure.align-center, object.align-center {
+  display: block;
+  margin-left: auto;
+  margin-right: auto;
+}
+
+table.align-center {
+  margin-left: auto;
+  margin-right: auto;
+}
+
+.align-left {
+  text-align: left }
+
+.align-center {
+  clear: both ;
+  text-align: center }
+
+.align-right {
+  text-align: right }
+
+/* reset inner alignment in figures */
+div.align-right {
+  text-align: inherit }
+
+/* div.align-center * { */
+/*   text-align: left } */
+
+.align-top    {
+  vertical-align: top }
+
+.align-middle {
+  vertical-align: middle }
+
+.align-bottom {
+  vertical-align: bottom }
+
+ol.simple, ul.simple {
+  margin-bottom: 1em }
+
+ol.arabic {
+  list-style: decimal }
+
+ol.loweralpha {
+  list-style: lower-alpha }
+
+ol.upperalpha {
+  list-style: upper-alpha }
+
+ol.lowerroman {
+  list-style: lower-roman }
+
+ol.upperroman {
+  list-style: upper-roman }
+
+p.attribution {
+  text-align: right ;
+  margin-left: 50% }
+
+p.caption {
+  font-style: italic }
+
+p.credits {
+  font-style: italic ;
+  font-size: smaller }
+
+p.label {
+  white-space: nowrap }
+
+p.rubric {
+  font-weight: bold ;
+  font-size: larger ;
+  color: maroon ;
+  text-align: center }
+
+p.sidebar-title {
+  font-family: sans-serif ;
+  font-weight: bold ;
+  font-size: larger }
+
+p.sidebar-subtitle {
+  font-family: sans-serif ;
+  font-weight: bold }
+
+p.topic-title {
+  font-weight: bold }
+
+pre.address {
+  margin-bottom: 0 ;
+  margin-top: 0 ;
+  font: inherit }
+
+pre.literal-block, pre.doctest-block, pre.math, pre.code {
+  margin-left: 2em ;
+  margin-right: 2em }
+
+pre.code .ln { color: grey; } /* line numbers */
+pre.code, code { background-color: #eeeeee }
+pre.code .comment, code .comment { color: #5C6576 }
+pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
+pre.code .literal.string, code .literal.string { color: #0C5404 }
+pre.code .name.builtin, code .name.builtin { color: #352B84 }
+pre.code .deleted, code .deleted { background-color: #DEB0A1}
+pre.code .inserted, code .inserted { background-color: #A3D289}
+
+span.classifier {
+  font-family: sans-serif ;
+  font-style: oblique }
+
+span.classifier-delimiter {
+  font-family: sans-serif ;
+  font-weight: bold }
+
+span.interpreted {
+  font-family: sans-serif }
+
+span.option {
+  white-space: nowrap }
+
+span.pre {
+  white-space: pre }
+
+span.problematic {
+  color: red }
+
+span.section-subtitle {
+  /* font-size relative to parent (h1..h6 element) */
+  font-size: 80% }
+
+table.citation {
+  border-left: solid 1px gray;
+  margin-left: 1px }
+
+table.docinfo {
+  margin: 2em 4em }
+
+table.docutils {
+  margin-top: 0.5em ;
+  margin-bottom: 0.5em }
+
+table.footnote {
+  border-left: solid 1px black;
+  margin-left: 1px }
+
+table.docutils td, table.docutils th,
+table.docinfo td, table.docinfo th {
+  padding-left: 0.5em ;
+  padding-right: 0.5em ;
+  vertical-align: top }
+
+table.docutils th.field-name, table.docinfo th.docinfo-name {
+  font-weight: bold ;
+  text-align: left ;
+  white-space: nowrap ;
+  padding-left: 0 }
+
+/* "booktabs" style (no vertical lines) */
+table.docutils.booktabs {
+  border: 0px;
+  border-top: 2px solid;
+  border-bottom: 2px solid;
+  border-collapse: collapse;
+}
+table.docutils.booktabs * {
+  border: 0px;
+}
+table.docutils.booktabs th {
+  border-bottom: thin solid;
+  text-align: left;
+}
+
+h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
+h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
+  font-size: 100% }
+
+ul.auto-toc {
+  list-style-type: none }
+
+</style>
+</head>
+<body>
+<div class="document" id="field-service-delivery">
+<h1 class="title">Field Service - Delivery</h1>
+
+<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!! This file is generated by oca-gen-addon-readme !!
+!! changes will be overwritten.                   !!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
+<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/field-service/tree/12.0/fieldservice_delivery"><img alt="OCA/field-service" src="https://img.shields.io/badge/github-OCA%2Ffield--service-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/field-service-12-0/field-service-12-0-fieldservice_delivery"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/264/12.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
+<p>This module is an add-on for the Field Service application in Odoo.
+It provides delivery capabilities on the field service orders.</p>
+<p><strong>Table of contents</strong></p>
+<div class="contents local topic" id="contents">
+<ul class="simple">
+<li><a class="reference internal" href="#installation" id="id1">Installation</a></li>
+<li><a class="reference internal" href="#configuration" id="id2">Configuration</a></li>
+<li><a class="reference internal" href="#usage" id="id3">Usage</a></li>
+<li><a class="reference internal" href="#known-issues-roadmap" id="id4">Known issues / Roadmap</a></li>
+<li><a class="reference internal" href="#bug-tracker" id="id5">Bug Tracker</a></li>
+<li><a class="reference internal" href="#credits" id="id6">Credits</a><ul>
+<li><a class="reference internal" href="#authors" id="id7">Authors</a></li>
+<li><a class="reference internal" href="#contributors" id="id8">Contributors</a></li>
+<li><a class="reference internal" href="#other-credits" id="id9">Other credits</a></li>
+<li><a class="reference internal" href="#maintainers" id="id10">Maintainers</a></li>
+</ul>
+</li>
+</ul>
+</div>
+<div class="section" id="installation">
+<h1><a class="toc-backref" href="#id1">Installation</a></h1>
+<p>To install Field Service and have the mapping features, you need to install GeoEngine.</p>
+<p>Please refer to the installation instructions available at:
+<a class="reference external" href="https://github.com/OCA/geospatial/tree/12.0/base_geoengine">https://github.com/OCA/geospatial/tree/12.0/base_geoengine</a></p>
+</div>
+<div class="section" id="configuration">
+<h1><a class="toc-backref" href="#id2">Configuration</a></h1>
+<p>To configure this module, you need to:</p>
+<ul class="simple">
+<li>Go to Inventory &gt; Configuration &gt; Delivery Methods</li>
+<li>Review the existing delivery methods or create new ones</li>
+</ul>
+</div>
+<div class="section" id="usage">
+<h1><a class="toc-backref" href="#id3">Usage</a></h1>
+<p>To use this module, you need to:</p>
+<ul class="simple">
+<li>Create a new service order</li>
+<li>Under the Inventory tab, select the warehouse, the delivery method and add
+products with quantity</li>
+<li>Confirm the order to create the delivery orders with the selected method</li>
+</ul>
+</div>
+<div class="section" id="known-issues-roadmap">
+<h1><a class="toc-backref" href="#id4">Known issues / Roadmap</a></h1>
+<p>The roadmap of the Field Service application is documented on
+<a class="reference external" href="https://github.com/OCA/field-service/issues/1">Github</a>.</p>
+</div>
+<div class="section" id="bug-tracker">
+<h1><a class="toc-backref" href="#id5">Bug Tracker</a></h1>
+<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/field-service/issues">GitHub Issues</a>.
+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
+<a class="reference external" href="https://github.com/OCA/field-service/issues/new?body=module:%20fieldservice_delivery%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
+<p>Do not contact contributors directly about support or help with technical issues.</p>
+</div>
+<div class="section" id="credits">
+<h1><a class="toc-backref" href="#id6">Credits</a></h1>
+<div class="section" id="authors">
+<h2><a class="toc-backref" href="#id7">Authors</a></h2>
+<ul class="simple">
+<li>Open Source Integrators</li>
+</ul>
+</div>
+<div class="section" id="contributors">
+<h2><a class="toc-backref" href="#id8">Contributors</a></h2>
+<ul class="simple">
+<li>Maxime Chambreuil &lt;<a class="reference external" href="mailto:mchambreuil&#64;opensourceintegrators.com">mchambreuil&#64;opensourceintegrators.com</a>&gt;</li>
+<li>Serpent Consulting Services Pvt. Ltd. &lt;<a class="reference external" href="mailto:support&#64;serpentcs.com">support&#64;serpentcs.com</a>&gt;</li>
+</ul>
+</div>
+<div class="section" id="other-credits">
+<h2><a class="toc-backref" href="#id9">Other credits</a></h2>
+<p>The development of this module has been financially supported by:</p>
+<ul class="simple">
+<li>Open Source Integrators &lt;<a class="reference external" href="https://opensourceintegrators.com">https://opensourceintegrators.com</a>&gt;</li>
+</ul>
+</div>
+<div class="section" id="maintainers">
+<h2><a class="toc-backref" href="#id10">Maintainers</a></h2>
+<p>This module is maintained by the OCA.</p>
+<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
+<p>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.</p>
+<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainer</a>:</p>
+<p><a class="reference external" href="https://github.com/max3903"><img alt="max3903" src="https://github.com/max3903.png?size=40px" /></a></p>
+<p>This module is part of the <a class="reference external" href="https://github.com/OCA/field-service/tree/12.0/fieldservice_delivery">OCA/field-service</a> project on GitHub.</p>
+<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
+</div>
+</div>
+</div>
+</body>
+</html>
diff --git a/helpdesk_delivery/views/helpdesk_ticket.xml b/helpdesk_delivery/views/helpdesk_ticket.xml
new file mode 100644
index 000000000..79dcba8e2
--- /dev/null
+++ b/helpdesk_delivery/views/helpdesk_ticket.xml
@@ -0,0 +1,17 @@
+<odoo>
+
+    <record id="helpdesk_ticket_form_delivery" model="ir.ui.view">
+        <field name="name">helpdesk.ticket.form.stock</field>
+        <field name="model">helpdesk.ticket</field>
+        <field
+            name="inherit_id"
+            ref="osi_helpdesk_stock.view_helpdesk_ticket_form_inherit_stock"
+        />
+        <field name="arch" type="xml">
+            <xpath expr="//group[@id='stock-right']" position="inside">
+                <field name="carrier_id" />
+            </xpath>
+        </field>
+    </record>
+
+</odoo>
diff --git a/helpdesk_fieldservice/README.rst b/helpdesk_fieldservice/README.rst
new file mode 100644
index 000000000..c0373424b
--- /dev/null
+++ b/helpdesk_fieldservice/README.rst
@@ -0,0 +1,33 @@
+.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
+   :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+   :alt: License: LGPL-3
+
+========================
+Helpdesk - Field Service
+========================
+
+This module allows the helpdesk user to track the status of related service
+requests.
+
+Usage
+=====
+
+* Go to Helpdesk
+* Create or select a ticket
+* In the "Service Requests" tab, you can create service requests for the FSM team
+
+To close a ticket, all the related service orders must be closed.
+
+Credits
+=======
+
+* Bhavesh Odedra <bodedra@opensourceintegrators.com>
+* Raphael Lee <rlee@opensourceintegrators.com>
+* Freni Patel <fpatel@opensourceintegrators.com>
+
+Contributors
+------------
+
+* Open Source Integrators <contact@opensourceintegrators.com>
+* Pavlov Media
+* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
diff --git a/helpdesk_fieldservice/__init__.py b/helpdesk_fieldservice/__init__.py
new file mode 100644
index 000000000..6a0b7163b
--- /dev/null
+++ b/helpdesk_fieldservice/__init__.py
@@ -0,0 +1,6 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# Copyright (C) 2021 Pavlov Media
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import models
+from . import wizard
diff --git a/helpdesk_fieldservice/__manifest__.py b/helpdesk_fieldservice/__manifest__.py
new file mode 100644
index 000000000..027595790
--- /dev/null
+++ b/helpdesk_fieldservice/__manifest__.py
@@ -0,0 +1,23 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# Copyright (C) 2021 Pavlov Media
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+{
+    "name": "Helpdesk - Field Service",
+    "summary": "Create service requests from a ticket",
+    "version": "14.0.1.0.0",
+    "license": "LGPL-3",
+    "author": "Open Source Integrators, Pavlov Media",
+    "category": "Helpdesk",
+    "website": "https://github.com/ursais/osi-addons",
+    "depends": ["helpdesk", "fieldservice"],
+    "data": [
+        "security/ir.model.access.csv",
+        "views/helpdesk_ticket_views.xml",
+        "views/fsm_location_views.xml",
+        "views/fsm_order_views.xml",
+        "views/res_partner.xml",
+        "wizard/fsm_order_close_wizard.xml",
+    ],
+    "maintainers": ["max3903", "osi-scampbell"],
+    "installable": True,
+}
diff --git a/helpdesk_fieldservice/i18n/es.po b/helpdesk_fieldservice/i18n/es.po
new file mode 100644
index 000000000..70099732a
--- /dev/null
+++ b/helpdesk_fieldservice/i18n/es.po
@@ -0,0 +1,204 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# 	* helpdesk_fieldservice
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 12.0+e\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2020-04-08 20:18+0000\n"
+"PO-Revision-Date: 2020-04-08 16:17-0400\n"
+"Last-Translator: Nelson Ramírez  <nramirez@konos.cl>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: \n"
+"Language: es\n"
+"X-Generator: Poedit 2.3\n"
+
+#. module: helpdesk_fieldservice
+#: model:ir.model.fields,field_description:helpdesk_fieldservice.field_fsm_location__ticket_count
+msgid "# Tickets"
+msgstr "Tickets"
+
+#. module: helpdesk_fieldservice
+#: model:ir.model.fields,field_description:helpdesk_fieldservice.field_helpdesk_ticket__all_orders_closed
+msgid "All Orders Closed"
+msgstr "Todas las Ordenes Cerrados"
+
+#. module: helpdesk_fieldservice
+#: model_terms:ir.ui.view,arch_db:helpdesk_fieldservice.fsm_order_close_wizard_view_form
+msgid "Cancel"
+msgstr "Cancelar"
+
+#. module: helpdesk_fieldservice
+#: code:addons/helpdesk_fieldservice/models/fsm_order.py:20
+#, python-format
+msgid "Cannot move to Complete until 'Actual End' is filled in"
+msgstr "No se puede pasar a Completado hasta que se rellene el \"Fin real\""
+
+#. module: helpdesk_fieldservice
+#: code:addons/helpdesk_fieldservice/models/fsm_order.py:23
+#, python-format
+msgid "Cannot move to Complete until 'Resolution' is filled in"
+msgstr "No se puede pasar a Completar hasta que se rellene la \"Resolución\""
+
+#. module: helpdesk_fieldservice
+#: model_terms:ir.ui.view,arch_db:helpdesk_fieldservice.fsm_order_close_wizard_view_form
+msgid "Close Ticket"
+msgstr "Cerrar Ticket"
+
+#. module: helpdesk_fieldservice
+#: model_terms:ir.ui.view,arch_db:helpdesk_fieldservice.helpdesk_ticket_search_closed_orders
+msgid "Closed FSM Orders"
+msgstr "Ordenes de FSM Cerradas"
+
+#. module: helpdesk_fieldservice
+#: model_terms:ir.ui.view,arch_db:helpdesk_fieldservice.helpdesk_ticket_view_service_request_form
+msgid "Create FSM Order"
+msgstr "Crear Orden de FSM"
+
+#. module: helpdesk_fieldservice
+#: model_terms:ir.actions.act_window,help:helpdesk_fieldservice.action_fsm_location_ticket
+msgid "Create Helpdesk Tickets"
+msgstr "Crear Ticket de Asistencia"
+
+#. module: helpdesk_fieldservice
+#: model:ir.model.fields,field_description:helpdesk_fieldservice.field_fsm_order_close_wizard__create_uid
+msgid "Created by"
+msgstr "Creado por"
+
+#. module: helpdesk_fieldservice
+#: model:ir.model.fields,field_description:helpdesk_fieldservice.field_fsm_order_close_wizard__create_date
+msgid "Created on"
+msgstr "Creado el"
+
+#. module: helpdesk_fieldservice
+#: model_terms:ir.ui.view,arch_db:helpdesk_fieldservice.helpdesk_ticket_view_service_request_form
+msgid "Description"
+msgstr "Descripción"
+
+#. module: helpdesk_fieldservice
+#: model_terms:ir.ui.view,arch_db:helpdesk_fieldservice.helpdesk_ticket_view_service_request_form
+msgid "Description of the ticket..."
+msgstr "Descripción del ticket..."
+
+#. module: helpdesk_fieldservice
+#: model:ir.model.fields,field_description:helpdesk_fieldservice.field_fsm_order_close_wizard__display_name
+msgid "Display Name"
+msgstr "Nombre a mostrar"
+
+#. module: helpdesk_fieldservice
+#: model:ir.model,name:helpdesk_fieldservice.model_fsm_order_close_wizard
+msgid "FSM Close - Option to Close Ticket"
+msgstr "Cerrar FSM - Opción para Cerrar Ticket"
+
+#. module: helpdesk_fieldservice
+#: model:ir.model.fields,field_description:helpdesk_fieldservice.field_helpdesk_ticket__fsm_location_id
+msgid "FSM Location"
+msgstr "Ubicación FSM"
+
+#. module: helpdesk_fieldservice
+#: model:ir.model,name:helpdesk_fieldservice.model_fsm_location
+msgid "Field Service Location"
+msgstr "Ubicación de Servicio de Campo"
+
+#. module: helpdesk_fieldservice
+#: model:ir.model,name:helpdesk_fieldservice.model_fsm_order
+msgid "Field Service Order"
+msgstr "Pedido de Servicio de Campo"
+
+#. module: helpdesk_fieldservice
+#: model:ir.model.fields,field_description:helpdesk_fieldservice.field_fsm_order_close_wizard__team_id
+msgid "Helpdesk Team"
+msgstr "Equipo de Helpdesk"
+
+#. module: helpdesk_fieldservice
+#: model:ir.model,name:helpdesk_fieldservice.model_helpdesk_ticket
+msgid "Helpdesk Ticket"
+msgstr "Ticket del Servicio de Asistencia"
+
+#. module: helpdesk_fieldservice
+#: model:ir.actions.act_window,name:helpdesk_fieldservice.action_fsm_location_ticket
+msgid "Helpdesk Tickets"
+msgstr "Tiquetes de Servicio de Asistencia"
+
+#. module: helpdesk_fieldservice
+#: model:ir.model.fields,field_description:helpdesk_fieldservice.field_fsm_order_close_wizard__id
+msgid "ID"
+msgstr "ID (identificación)"
+
+#. module: helpdesk_fieldservice
+#: model:ir.model.fields,field_description:helpdesk_fieldservice.field_fsm_order_close_wizard____last_update
+msgid "Last Modified on"
+msgstr "Última modificación en"
+
+#. module: helpdesk_fieldservice
+#: model:ir.model.fields,field_description:helpdesk_fieldservice.field_fsm_order_close_wizard__write_uid
+msgid "Last Updated by"
+msgstr "Última actualización por"
+
+#. module: helpdesk_fieldservice
+#: model:ir.model.fields,field_description:helpdesk_fieldservice.field_fsm_order_close_wizard__write_date
+msgid "Last Updated on"
+msgstr "Última actualización el"
+
+#. module: helpdesk_fieldservice
+#: model:ir.ui.menu,name:helpdesk_fieldservice.menu_helpdesk_op
+msgid "Operations"
+msgstr "Operaciones"
+
+#. module: helpdesk_fieldservice
+#: code:addons/helpdesk_fieldservice/models/helpdesk_ticket.py:32
+#, python-format
+msgid "Please complete all service orders related to this ticket to close it."
+msgstr "Por favor complete todos los pedidos de servicio relacionados con este boleto para cerrarlo."
+
+#. module: helpdesk_fieldservice
+#: model:ir.model.fields,field_description:helpdesk_fieldservice.field_fsm_order_close_wizard__resolution
+msgid "Resolution"
+msgstr "Resolución"
+
+#. module: helpdesk_fieldservice
+#: model:ir.model.fields,field_description:helpdesk_fieldservice.field_helpdesk_ticket__fsm_order_ids
+#: model:ir.ui.menu,name:helpdesk_fieldservice.menu_helpdesk_fsm_order
+#: model_terms:ir.ui.view,arch_db:helpdesk_fieldservice.helpdesk_ticket_view_service_request_form
+msgid "Service Orders"
+msgstr "Ordenes de Servicio"
+
+#. module: helpdesk_fieldservice
+#: model:ir.model.fields,field_description:helpdesk_fieldservice.field_fsm_order_close_wizard__stage_id
+msgid "Stage"
+msgstr "Etapa"
+
+#. module: helpdesk_fieldservice
+#: model_terms:ir.ui.view,arch_db:helpdesk_fieldservice.fsm_order_close_wizard_view_form
+msgid "There is an open Ticket, would you like to update the related ticket?"
+msgstr "Hay un ticket abierto, ¿le gustaría actualizar el ticket relacionado?"
+
+#. module: helpdesk_fieldservice
+#: model:ir.model.fields,field_description:helpdesk_fieldservice.field_fsm_order__ticket_id
+#: model:ir.model.fields,field_description:helpdesk_fieldservice.field_fsm_order_close_wizard__ticket_id
+msgid "Ticket"
+msgstr "Ticket"
+
+#. module: helpdesk_fieldservice
+#: model_terms:ir.ui.view,arch_db:helpdesk_fieldservice.fsm_order_close_wizard_view_form
+msgid "Ticket Resolution"
+msgstr "Resolución de Ticket"
+
+#. module: helpdesk_fieldservice
+#: model_terms:ir.ui.view,arch_db:helpdesk_fieldservice.fsm_order_close_wizard_view_form
+msgid "Ticket Stage"
+msgstr "Etapa del Ticket"
+
+#. module: helpdesk_fieldservice
+#: model_terms:ir.ui.view,arch_db:helpdesk_fieldservice.view_fsm_location_ticket_form
+msgid "Tickets"
+msgstr "Tickets"
+
+#. module: helpdesk_fieldservice
+#: model_terms:ir.ui.view,arch_db:helpdesk_fieldservice.helpdesk_ticket_view_service_request_form
+msgid "View FSM Order"
+msgstr "Ver Orden FSM"
diff --git a/helpdesk_fieldservice/models/__init__.py b/helpdesk_fieldservice/models/__init__.py
new file mode 100644
index 000000000..dcf2baaf1
--- /dev/null
+++ b/helpdesk_fieldservice/models/__init__.py
@@ -0,0 +1,7 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# Copyright (C) 2021 Pavlov Media
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import fsm_location
+from . import fsm_order
+from . import helpdesk_ticket
diff --git a/helpdesk_fieldservice/models/fsm_location.py b/helpdesk_fieldservice/models/fsm_location.py
new file mode 100644
index 000000000..e01a03970
--- /dev/null
+++ b/helpdesk_fieldservice/models/fsm_location.py
@@ -0,0 +1,37 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import fields, models
+
+
+class FSMLocation(models.Model):
+    _inherit = "fsm.location"
+
+    ticket_count = fields.Integer(compute="_compute_ticket_count", string="# Tickets")
+
+    def _compute_ticket_count(self):
+        for location in self:
+            location.ticket_count = self.env["helpdesk.ticket"].search_count(
+                [("fsm_location_id", "=", location.id)]
+            )
+
+    def action_view_ticket(self):
+        for location in self:
+            ticket_ids = self.env["helpdesk.ticket"].search(
+                [("fsm_location_id", "=", location.id)]
+            )
+            action = self.env.ref(
+                "helpdesk_fieldservice.action_fsm_location_ticket"
+            ).read()[0]
+            action["context"] = {}
+            if len(ticket_ids) == 1:
+                action["views"] = [
+                    (self.env.ref("helpdesk.helpdesk_ticket_view_form").id, "form")
+                ]
+                action["res_id"] = ticket_ids.ids[0]
+            else:
+                action["domain"] = [("id", "in", ticket_ids.ids)]
+                action["context"].update(
+                    {"search_default_is_open": 1, "default_fsm_location_id": self.id}
+                )
+            return action
diff --git a/helpdesk_fieldservice/models/fsm_order.py b/helpdesk_fieldservice/models/fsm_order.py
new file mode 100644
index 000000000..58c56f1bf
--- /dev/null
+++ b/helpdesk_fieldservice/models/fsm_order.py
@@ -0,0 +1,65 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import _, fields, models
+from odoo.exceptions import ValidationError
+
+
+class FSMOrder(models.Model):
+    _inherit = "fsm.order"
+
+    ticket_id = fields.Many2one("helpdesk.ticket", string="Ticket", tracking=True)
+
+    def action_complete(self):
+        if not self.date_end:
+            raise ValidationError(
+                _("Cannot move to Complete " + "until 'Actual End' is filled in")
+            )
+        if not self.resolution:
+            raise ValidationError(
+                _("Cannot move to Complete " + "until 'Resolution' is filled in")
+            )
+        res = super().action_complete()
+        if self.ticket_id:
+            open_fsm_orders_count = self.env["fsm.order"].search_count(
+                [
+                    ("ticket_id", "=", self.ticket_id.id),
+                    ("stage_id.is_closed", "=", False),
+                ]
+            )
+            if self.ticket_id.stage_id.is_close:
+                return res
+            elif open_fsm_orders_count == 0:
+                view_id = self.env.ref(
+                    "helpdesk_fieldservice.fsm_order_close_wizard_view_form"
+                ).id
+                return {
+                    "view_id": view_id,
+                    "view_type": "form",
+                    "view_mode": "form",
+                    "res_model": "fsm.order.close.wizard",
+                    "type": "ir.actions.act_window",
+                    "target": "new",
+                    "context": {
+                        "default_ticket_id": self.ticket_id.id,
+                        "default_team_id": self.ticket_id.team_id.id,
+                        "default_resolution": self.resolution,
+                    },
+                }
+            else:
+                return res
+        else:
+            return res
+
+    def action_view_order(self):
+        """
+        This function returns an action that displays a full FSM Order
+        form when viewing an FSM Order from a ticket.
+        """
+        action = self.env.ref("fieldservice.action_fsm_operation_order").read()[0]
+        order = self.env["fsm.order"].search([("id", "=", self.id)])
+        action["views"] = [
+            (self.env.ref("fieldservice." + "fsm_order_form").id, "form")
+        ]
+        action["res_id"] = order.id
+        return action
diff --git a/helpdesk_fieldservice/models/helpdesk_ticket.py b/helpdesk_fieldservice/models/helpdesk_ticket.py
new file mode 100644
index 000000000..3ac311edf
--- /dev/null
+++ b/helpdesk_fieldservice/models/helpdesk_ticket.py
@@ -0,0 +1,96 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# Copyright (C) 2021 Pavlov Media
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import _, api, fields, models
+from odoo.exceptions import ValidationError
+
+
+class HelpdeskTicket(models.Model):
+    _inherit = "helpdesk.ticket"
+
+    fsm_order_ids = fields.One2many("fsm.order", "ticket_id", string="Service Orders")
+    fsm_location_id = fields.Many2one("fsm.location", string="FSM Location")
+
+    all_orders_closed = fields.Boolean(compute="_compute_all_closed", store=True)
+
+    @api.depends("fsm_order_ids", "stage_id", "fsm_order_ids.stage_id")
+    def _compute_all_closed(self):
+        for ticket in self:
+            ticket.all_orders_closed = True
+            if ticket.fsm_order_ids:
+                for order in ticket.fsm_order_ids:
+                    if order.stage_id.name not in ["Closed", "Cancelled"]:
+                        ticket.all_orders_closed = False
+            else:
+                ticket.all_orders_closed = False
+
+    def write(self, vals):
+        if "stage_id" in vals:
+            ticket_stage = self.env["helpdesk.stage"].browse(vals.get("stage_id"))
+            if ticket_stage.is_close:
+                for ticket in self:
+                    if ticket.fsm_order_ids:
+                        open_orders = ticket.fsm_order_ids.filtered(
+                            lambda x: x.stage_id.is_closed
+                        )
+                        if open_orders and len(open_orders.ids) != len(
+                            ticket.fsm_order_ids
+                        ):
+                            raise ValidationError(
+                                _(
+                                    "Please complete all service orders "
+                                    "related to this ticket to close it."
+                                )
+                            )
+        return super(HelpdeskTicket, self).write(vals)
+
+    def _location_contact_fill(self, loc):
+        """loc is a boolean that lets us know if this is coming from the
+        partner onchange or the location onchange"""
+        if loc:
+            if self.fsm_location_id and self.partner_id:
+                if self.partner_id.service_location_id != self.fsm_location_id:
+                    self.partner_id = False
+        else:
+            if self.partner_id:
+                if not self.fsm_location_id:
+                    self.fsm_location_id = self.partner_id.service_location_id
+
+    @api.onchange("fsm_location_id")
+    def _onchange_fsm_location_id_partner(self):
+        if self.fsm_location_id:
+            self._location_contact_fill(True)
+            if self.fsm_location_id and not self.partner_id:
+                return {
+                    "domain": {
+                        "partner_id": [
+                            ("service_location_id", "=", self.fsm_location_id.name)
+                        ]
+                    }
+                }
+        else:
+            return {"domain": {"partner_id": [("id", "!=", None)]}}
+
+    @api.onchange("partner_id")
+    def _onchange_partner_id_location(self):
+        if self.partner_id:
+            self._location_contact_fill(False)
+
+    def action_create_order(self):
+        """
+        This function returns an action that displays a full FSM Order
+        form when creating an FSM Order from a ticket.
+        """
+        action = self.env.ref("fieldservice.action_fsm_operation_order")
+        result = action.read()[0]
+        # override the context to get rid of the default filtering
+        result["context"] = {
+            "default_ticket_id": self.id,
+            "default_priority": self.priority,
+            "default_location_id": self.fsm_location_id.id,
+            "default_origin": self.name,
+        }
+        res = self.env.ref("fieldservice.fsm_order_form", False)
+        result["views"] = [(res and res.id or False, "form")]
+        return result
diff --git a/helpdesk_fieldservice/security/ir.model.access.csv b/helpdesk_fieldservice/security/ir.model.access.csv
new file mode 100644
index 000000000..db56838b0
--- /dev/null
+++ b/helpdesk_fieldservice/security/ir.model.access.csv
@@ -0,0 +1,3 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_helpdesk_ticket_fsm_user,helpdesk.ticket.fsm.user,model_helpdesk_ticket,fieldservice.group_fsm_user,1,0,0,0
+access_fsm_order_close_wizard,access_fsm_order_close_wizard,model_fsm_order_close_wizard,base.group_user,1,1,1,1
diff --git a/helpdesk_fieldservice/static/description/icon.png b/helpdesk_fieldservice/static/description/icon.png
new file mode 100644
index 000000000..955674d8f
Binary files /dev/null and b/helpdesk_fieldservice/static/description/icon.png differ
diff --git a/helpdesk_fieldservice/static/src/scss/helpdesk_column.scss b/helpdesk_fieldservice/static/src/scss/helpdesk_column.scss
new file mode 100644
index 000000000..87abf58ee
--- /dev/null
+++ b/helpdesk_fieldservice/static/src/scss/helpdesk_column.scss
@@ -0,0 +1,6 @@
+.helpdesk_column {
+    width: 100% !important;
+    color: white;
+    background-color: $o-brand-primary;
+    text-transform: uppercase;
+}
diff --git a/helpdesk_fieldservice/views/fsm_location_views.xml b/helpdesk_fieldservice/views/fsm_location_views.xml
new file mode 100644
index 000000000..55a2e2484
--- /dev/null
+++ b/helpdesk_fieldservice/views/fsm_location_views.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<odoo>
+
+    <record id="action_fsm_location_ticket" model="ir.actions.act_window">
+        <field name="name">Helpdesk Tickets</field>
+        <field name="type">ir.actions.act_window</field>
+        <field name="res_model">helpdesk.ticket</field>
+        <field name="view_mode">tree,form</field>
+        <field name="domain">[('fsm_location_id', '=', active_id)]</field>
+        <field name="help" type="html">
+            <p class="oe_view_nocontent_create">
+                Create Helpdesk Tickets
+            </p>
+        </field>
+    </record>
+
+    <!-- FieldService Location Form View -->
+    <record id="view_fsm_location_ticket_form" model="ir.ui.view">
+        <field name="name">view.fsm.location.ticket.form</field>
+        <field name="model">fsm.location</field>
+        <field name="inherit_id" ref="fieldservice.fsm_location_form_view" />
+        <field name="arch" type="xml">
+            <div class="oe_button_box" position="inside">
+                <button
+                    name="action_view_ticket"
+                    type="object"
+                    class="oe_stat_button"
+                    icon="fa-edit"
+                >
+                    <field
+                        name="ticket_count"
+                        widget="statinfo"
+                        string="Tickets"
+                    />
+                </button>
+            </div>
+        </field>
+    </record>
+
+</odoo>
diff --git a/helpdesk_fieldservice/views/fsm_order_views.xml b/helpdesk_fieldservice/views/fsm_order_views.xml
new file mode 100644
index 000000000..557e9f4de
--- /dev/null
+++ b/helpdesk_fieldservice/views/fsm_order_views.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<odoo>
+
+    <!-- FieldService Order Form View -->
+    <record id="view_fsm_order_ticket_form" model="ir.ui.view">
+        <field name="name">view.fsm.order.ticket.form</field>
+        <field name="model">fsm.order</field>
+        <field name="inherit_id" ref="fieldservice.fsm_order_form" />
+        <field name="arch" type="xml">
+            <field name="template_id" position="after">
+                <field name="ticket_id" />
+            </field>
+        </field>
+    </record>
+
+</odoo>
diff --git a/helpdesk_fieldservice/views/helpdesk_ticket_views.xml b/helpdesk_fieldservice/views/helpdesk_ticket_views.xml
new file mode 100644
index 000000000..827a2986a
--- /dev/null
+++ b/helpdesk_fieldservice/views/helpdesk_ticket_views.xml
@@ -0,0 +1,160 @@
+<!-- Copyright 2021 Open Source Integrators
+     Copyright (C) 2021 Pavlov Media
+     License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
+<odoo>
+    <template
+        id="shrink_tree_column"
+        name="helpdesk assets"
+        inherit_id="web.assets_backend"
+    >
+        <xpath expr="." position="inside">
+            <link
+                rel="stylesheet"
+                type="text/scss"
+                href="/helpdesk_fieldservice/static/src/scss/helpdesk_column.scss"
+            />
+        </xpath>
+    </template>
+
+    <!-- Helpdesk Ticket Form View -->
+    <record id="helpdesk_ticket_view_service_request_form" model="ir.ui.view">
+        <field name="name">helpdesk.ticket.service.request.form</field>
+        <field name="model">helpdesk.ticket</field>
+        <field name="inherit_id" ref="helpdesk.helpdesk_ticket_view_form" />
+        <field name="arch" type="xml">
+            <field name="description" position="after">
+                <notebook name="helpdesk_fieldservice_book">
+                    <page
+                        name="helpdesk_service_order_page"
+                        string="Service Orders"
+                    >
+                        <button
+                            name="action_create_order"
+                            string="Create FSM Order"
+                            type="object"
+                            class="oe_highlight"
+                        />
+                        <field name="fsm_order_ids">
+                            <tree create="false">
+                                <field
+                                    name="name"
+                                    style="pointer-events:none;"
+                                />
+                                <field
+                                    name="location_id"
+                                    style="pointer-events:none;"
+                                />
+                                <button
+                                    name="action_view_order"
+                                    string="View FSM Order"
+                                    type="object"
+                                    class="helpdesk_column"
+                                />
+                                <field
+                                    name="stage_id"
+                                    style="pointer-events:none;"
+                                />
+                                <field
+                                    name="person_id"
+                                    style="pointer-events:none;"
+                                />
+                                <field
+                                    name="scheduled_date_start"
+                                    style="pointer-events:none;"
+                                />
+                                <field
+                                    name="scheduled_date_end"
+                                    style="pointer-events:none;"
+                                />
+                                <field
+                                    name="scheduled_duration"
+                                    style="pointer-events:none;"
+                                />
+                            </tree>
+                        </field>
+                    </page>
+                </notebook>
+            </field>
+            <field name="partner_id" position="before">
+                <field name="fsm_location_id" />
+                <field name="all_orders_closed" invisible="1" />
+            </field>
+        </field>
+    </record>
+
+    <record id="helpdesk_ticket_search_closed_orders" model="ir.ui.view">
+        <field name="name">helpdesk.ticket.service.form.logic</field>
+        <field name="model">helpdesk.ticket</field>
+        <field name="inherit_id" ref="helpdesk.helpdesk_tickets_view_search" />
+        <field name="arch" type="xml">
+            <filter name="is_close" position="after">
+                <filter
+                    string="Closed FSM Orders"
+                    domain="[('stage_id.is_close', '=', False), ('all_orders_closed', '=', True)]"
+                    name="closed_fsm_order"
+                />
+            </filter>
+        </field>
+    </record>
+
+    <record id="helpdesk_ticket_view_form_logic" model="ir.ui.view">
+        <field name="name">helpdesk.ticket.service.form.logic</field>
+        <field name="model">helpdesk.ticket</field>
+        <field name="inherit_id" ref="helpdesk.helpdesk_ticket_view_form" />
+        <field name="arch" type="xml">
+            <field name="partner_name" position="attributes">
+                <attribute name="invisible">True</attribute>
+            </field>
+            <field name="partner_email" position="replace">
+                <field
+                    name="partner_email"
+                    attrs="{'invisible': [('partner_id','=',False)]}"
+                />
+            </field>
+        </field>
+    </record>
+
+    <record id="helpdesk_ticket_tree_view_location" model="ir.ui.view">
+        <field name="name">helpdesk.ticket.tree.location</field>
+        <field name="model">helpdesk.ticket</field>
+        <field name="inherit_id" ref="helpdesk.helpdesk_tickets_view_tree" />
+        <field name="arch" type="xml">
+            <field name="partner_id" position="after">
+                <field name="fsm_location_id" />
+            </field>
+        </field>
+    </record>
+
+    <record id="helpdesk_ticket_search_view_location" model="ir.ui.view">
+        <field name="name">helpdesk.ticket.search.location</field>
+        <field name="model">helpdesk.ticket</field>
+        <field name="inherit_id" ref="helpdesk.helpdesk_tickets_view_search" />
+        <field name="arch" type="xml">
+            <field name="partner_id" position="after">
+                <field name="fsm_location_id" />
+            </field>
+        </field>
+    </record>
+
+    <menuitem
+        id="menu_helpdesk_op"
+        name="Operations"
+        parent="helpdesk.menu_helpdesk_root"
+        sequence="10"
+    />
+
+    <menuitem
+        id="menu_helpdesk_fsm_order"
+        name="Service Orders"
+        action="fieldservice.action_fsm_dash_order"
+        parent="menu_helpdesk_op"
+        sequence="20"
+    />
+
+    <menuitem
+        id="helpdesk.helpdesk_ticket_menu_main"
+        name="All Tickets"
+        parent="menu_helpdesk_op"
+    />
+
+</odoo>
diff --git a/helpdesk_fieldservice/views/res_partner.xml b/helpdesk_fieldservice/views/res_partner.xml
new file mode 100644
index 000000000..769b18b8f
--- /dev/null
+++ b/helpdesk_fieldservice/views/res_partner.xml
@@ -0,0 +1,19 @@
+<odoo>
+
+    <record id="res_partner_form_ticket_context" model="ir.ui.view">
+        <field name="name">res.partner.form.ticket.context</field>
+        <field name="model">res.partner</field>
+        <field
+            name="inherit_id"
+            ref="helpdesk.view_partner_form_inherit_helpdesk"
+        />
+        <field name="arch" type="xml">
+            <button name="action_open_helpdesk_ticket" position="attributes">
+                <attribute
+                    name="context"
+                >{'default_partner_id': id, 'default_fsm_location_id': service_location_id}</attribute>
+            </button>
+        </field>
+    </record>
+
+</odoo>
diff --git a/helpdesk_fieldservice/wizard/__init__.py b/helpdesk_fieldservice/wizard/__init__.py
new file mode 100644
index 000000000..3c1f35278
--- /dev/null
+++ b/helpdesk_fieldservice/wizard/__init__.py
@@ -0,0 +1,5 @@
+# Copyright (C) 2021 Pavlov Media
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from . import fsm_order_close_wizard
diff --git a/helpdesk_fieldservice/wizard/fsm_order_close_wizard.py b/helpdesk_fieldservice/wizard/fsm_order_close_wizard.py
new file mode 100644
index 000000000..793d9a1a3
--- /dev/null
+++ b/helpdesk_fieldservice/wizard/fsm_order_close_wizard.py
@@ -0,0 +1,23 @@
+# Copyright (C) 2021 Pavlov Media
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from odoo import fields, models
+
+
+class FSMOrderCloseWizard(models.TransientModel):
+    _name = "fsm.order.close.wizard"
+    _description = "FSM Close - Option to Close Ticket"
+
+    resolution = fields.Text(string="Resolution")
+    team_id = fields.Many2one("helpdesk.team", string="Helpdesk Team")
+    stage_id = fields.Many2one("helpdesk.stage", string="Stage")
+    ticket_id = fields.Many2one("helpdesk.ticket", string="Ticket")
+
+    def action_close_ticket(self):
+        for record in self:
+            if not record.ticket_id.stage_id.is_close:
+                record.ticket_id.write(
+                    {"resolution": record.resolution, "stage_id": record.stage_id.id}
+                )
+        return {"type": "ir.actions.client", "tag": "reload"}
diff --git a/helpdesk_fieldservice/wizard/fsm_order_close_wizard.xml b/helpdesk_fieldservice/wizard/fsm_order_close_wizard.xml
new file mode 100644
index 000000000..3d2adb2fc
--- /dev/null
+++ b/helpdesk_fieldservice/wizard/fsm_order_close_wizard.xml
@@ -0,0 +1,47 @@
+<!-- Copyright (C) 2021 Pavlov Media
+     Copyright (C) 2021 - TODAY, Open Source Integrators
+     License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
+<odoo>
+    <record id="fsm_order_close_wizard_view_form" model="ir.ui.view">
+        <field name="name">fsm.order.close.wizard.form</field>
+        <field name="model">fsm.order.close.wizard</field>
+        <field name="arch" type="xml">
+            <form>
+                <div
+                >There is an open Ticket, would you like to update the related ticket?
+              </div>
+                <group>
+                    <field invisible="1" name="team_id" />
+                    <field invisible="1" name="ticket_id" />
+                    <field
+                        domain="[('team_ids', '=', team_id)]"
+                        name="stage_id"
+                        options="{'no_create': True, 'no_open': True, 'no_create_edit': True}"
+                        required="1"
+                        string="Ticket Stage"
+                    />
+                </group>
+                <group>
+                    <field
+                        name="resolution"
+                        required="1"
+                        string="Ticket Resolution"
+                    />
+                </group>
+                <footer>
+                    <button
+                        class="oe_highlight"
+                        name="action_close_ticket"
+                        string="Close Ticket"
+                        type="object"
+                    />
+                    <button
+                        class="btn-default"
+                        special="cancel"
+                        string="Cancel"
+                    />
+                </footer>
+            </form>
+        </field>
+    </record>
+</odoo>
diff --git a/helpdesk_operating_unit/README.rst b/helpdesk_operating_unit/README.rst
new file mode 100644
index 000000000..21cd7854d
--- /dev/null
+++ b/helpdesk_operating_unit/README.rst
@@ -0,0 +1,21 @@
+**This file is going to be generated by oca-gen-addon-readme.**
+
+*Manual changes will be overwritten.*
+
+Please provide content in the ``readme`` directory:
+
+* **DESCRIPTION.rst** (required)
+* INSTALL.rst (optional)
+* CONFIGURE.rst (optional)
+* **USAGE.rst** (optional, highly recommended)
+* DEVELOP.rst (optional)
+* ROADMAP.rst (optional)
+* HISTORY.rst (optional, recommended)
+* **CONTRIBUTORS.rst** (optional, highly recommended)
+* CREDITS.rst (optional)
+
+Content of this README will also be drawn from the addon manifest,
+from keys such as name, authors, maintainers, development_status,
+and license.
+
+A good, one sentence summary in the manifest is also highly recommended.
diff --git a/helpdesk_operating_unit/__init__.py b/helpdesk_operating_unit/__init__.py
new file mode 100644
index 000000000..133f68732
--- /dev/null
+++ b/helpdesk_operating_unit/__init__.py
@@ -0,0 +1,2 @@
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
+from . import models
diff --git a/helpdesk_operating_unit/__manifest__.py b/helpdesk_operating_unit/__manifest__.py
new file mode 100644
index 000000000..9ef3ae9b1
--- /dev/null
+++ b/helpdesk_operating_unit/__manifest__.py
@@ -0,0 +1,25 @@
+# Copyright (C) 2021 Open Source Integrators
+# Copyright (C) 2021 Serpent Consulting Services
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).
+{
+    "name": "Helpdesk Ticket with Operating Units",
+    "summary": """
+        This module adds operating unit information to Helpdesk tickets.""",
+    "version": "14.0.1.0.0",
+    "author": "Open Source Integrators, "
+    "Serpent Consulting Services Pvt. Ltd.,"
+    "Odoo Community Association (OCA)",
+    "website": "https://github.com/ursais/osi-addons",
+    "category": "Helpdesk",
+    "depends": ["operating_unit", "helpdesk"],
+    "license": "LGPL-3",
+    "data": [
+        "security/helpdesk_security.xml",
+        "views/helpdesk_ticket.xml",
+    ],
+    "installable": True,
+    "development_status": "Beta",
+    "maintainers": [
+        "max3903",
+    ],
+}
diff --git a/helpdesk_operating_unit/models/__init__.py b/helpdesk_operating_unit/models/__init__.py
new file mode 100644
index 000000000..c4ab901fc
--- /dev/null
+++ b/helpdesk_operating_unit/models/__init__.py
@@ -0,0 +1,2 @@
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
+from . import helpdesk_ticket
diff --git a/helpdesk_operating_unit/models/helpdesk_ticket.py b/helpdesk_operating_unit/models/helpdesk_ticket.py
new file mode 100644
index 000000000..a44082a5f
--- /dev/null
+++ b/helpdesk_operating_unit/models/helpdesk_ticket.py
@@ -0,0 +1,16 @@
+# Copyright (C) 2021 Open Source Integrators
+# Copyright (C) 2021 Serpent Consulting Services
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).
+from odoo import fields, models
+
+
+class HelpdeskTicket(models.Model):
+    _inherit = "helpdesk.ticket"
+
+    operating_unit_id = fields.Many2one(
+        comodel_name="operating.unit",
+        string="Operating Unit",
+        default=lambda self: self.env["res.users"].operating_unit_default_get(
+            self._uid
+        ),
+    )
diff --git a/helpdesk_operating_unit/readme/CONTRIBUTORS.rst b/helpdesk_operating_unit/readme/CONTRIBUTORS.rst
new file mode 100644
index 000000000..713654d40
--- /dev/null
+++ b/helpdesk_operating_unit/readme/CONTRIBUTORS.rst
@@ -0,0 +1,3 @@
+* Nikul Chaudhary <nikul.chaudhary.serpentcs@gmail.com>
+* Maxime Chambreuil <mchambreuil@opensourceintegrators.com>
+* Freni Patel <fpatel@opensourceintegrators.com>
diff --git a/helpdesk_operating_unit/readme/CREDITS.rst b/helpdesk_operating_unit/readme/CREDITS.rst
new file mode 100644
index 000000000..df037ca3c
--- /dev/null
+++ b/helpdesk_operating_unit/readme/CREDITS.rst
@@ -0,0 +1,2 @@
+* Open Source Integrators
+* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
diff --git a/helpdesk_operating_unit/readme/DESCRIPTION.rst b/helpdesk_operating_unit/readme/DESCRIPTION.rst
new file mode 100644
index 000000000..dd05ba0fc
--- /dev/null
+++ b/helpdesk_operating_unit/readme/DESCRIPTION.rst
@@ -0,0 +1,1 @@
+This module adds operating unit information to Helpdesk tickets.
diff --git a/helpdesk_operating_unit/readme/USAGE.rst b/helpdesk_operating_unit/readme/USAGE.rst
new file mode 100644
index 000000000..911ce6a95
--- /dev/null
+++ b/helpdesk_operating_unit/readme/USAGE.rst
@@ -0,0 +1,3 @@
+* Go to Helpdesk > Operations > All Tickets
+* You only see the tickets of your operating units
+* Create a new ticket. It is assigned to your default operating unit.
diff --git a/helpdesk_operating_unit/security/helpdesk_security.xml b/helpdesk_operating_unit/security/helpdesk_security.xml
new file mode 100644
index 000000000..67dc6b28b
--- /dev/null
+++ b/helpdesk_operating_unit/security/helpdesk_security.xml
@@ -0,0 +1,21 @@
+<odoo>
+
+    <!-- Copyright (C) 2019 Open Source Integrators
+    Copyright (C) 2019 Serpent Consulting Services
+    License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). -->
+
+    <record id="ir_rule_helpdesk_ticket_operating_unit" model="ir.rule">
+        <field name="model_id" ref="helpdesk.model_helpdesk_ticket" />
+        <field
+            name="domain_force"
+        >['|', ('operating_unit_id','=',False), ('operating_unit_id','in',user.operating_unit_ids.ids)]
+        </field>
+        <field name="name">Helpdesk Operating Unit</field>
+        <field name="global" eval="True" />
+        <field eval="0" name="perm_unlink" />
+        <field eval="0" name="perm_write" />
+        <field eval="1" name="perm_read" />
+        <field eval="0" name="perm_create" />
+    </record>
+
+</odoo>
diff --git a/helpdesk_operating_unit/views/helpdesk_ticket.xml b/helpdesk_operating_unit/views/helpdesk_ticket.xml
new file mode 100644
index 000000000..52b198963
--- /dev/null
+++ b/helpdesk_operating_unit/views/helpdesk_ticket.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<odoo>
+    <!-- Copyright (C) 2019 Open Source Integrators
+    Copyright (C) 2019 Serpent Consulting Services
+    License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). -->
+
+    <record id="view_helpdesk_ticket_view_form_inherit" model="ir.ui.view">
+        <field name="name">helpdesk.ticket.form</field>
+        <field name="model">helpdesk.ticket</field>
+        <field name="inherit_id" ref="helpdesk.helpdesk_ticket_view_form" />
+        <field name="arch" type="xml">
+            <field name="user_id" position="after">
+                <field name="operating_unit_id" />
+            </field>
+        </field>
+    </record>
+
+    <record id="helpdesk_ticket_group_by_ou" model="ir.ui.view">
+        <field name="name">helpdesk.ticket.group.by.ou</field>
+        <field name="model">helpdesk.ticket</field>
+        <field name="inherit_id" ref="helpdesk.helpdesk_tickets_view_search" />
+        <field name="arch" type="xml">
+            <filter name="stage" position="after">
+                <filter
+                    string="Operating Unit"
+                    name="operating_unit_grouped"
+                    domain="[]"
+                    context="{'group_by':'operating_unit_id'}"
+                    groups="operating_unit.group_multi_operating_unit"
+                />
+            </filter>
+        </field>
+    </record>
+
+</odoo>
diff --git a/helpdesk_phone/README.rst b/helpdesk_phone/README.rst
new file mode 100644
index 000000000..9cff947ce
--- /dev/null
+++ b/helpdesk_phone/README.rst
@@ -0,0 +1,30 @@
+.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
+   :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+   :alt: License: LGPL-3
+
+==============
+Helpdesk Phone
+==============
+
+This module adds a phone number field on the helpdesk ticket related to the selected customer.  
+
+=====
+Usage
+=====
+
+* Create or edit a helpdesk ticket
+* Select a customer with a phone number
+* The phone number is displayed on the ticket
+
+=======
+Credits
+=======
+
+* Steven Campbell <scampbell@opensourceintegrators.com>
+* Freni Patel <fpatel@opensourceintegrators.com>
+
+Contributors
+------------
+
+* Open Source Integrators <contact@opensourceintegrators.com>
+* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
diff --git a/helpdesk_phone/__init__.py b/helpdesk_phone/__init__.py
new file mode 100644
index 000000000..47d2b2851
--- /dev/null
+++ b/helpdesk_phone/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import models
diff --git a/helpdesk_phone/__manifest__.py b/helpdesk_phone/__manifest__.py
new file mode 100644
index 000000000..c995a311e
--- /dev/null
+++ b/helpdesk_phone/__manifest__.py
@@ -0,0 +1,21 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+{
+    "name": "Helpdesk Phone",
+    "summary": "Display the customer phone number on Helpdesk ticket",
+    "version": "14.0.1.0.0",
+    "category": "Helpdesk",
+    "author": "Open Source Integrators",
+    "website": "https://github.com/ursais/osi-addons",
+    "depends": [
+        "helpdesk",
+    ],
+    "data": ["views/helpdesk_phone.xml"],
+    "installable": True,
+    "license": "LGPL-3",
+    "development_status": "Beta",
+    "maintainers": [
+        "wolfhall",
+        "max3903",
+    ],
+}
diff --git a/helpdesk_phone/i18n/es.po b/helpdesk_phone/i18n/es.po
new file mode 100644
index 000000000..bfa838f41
--- /dev/null
+++ b/helpdesk_phone/i18n/es.po
@@ -0,0 +1,28 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# 	* helpdesk_phone
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 12.0+e-20191022\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2020-02-18 17:06+0000\n"
+"PO-Revision-Date: 2020-02-18 14:07-0300\n"
+"Last-Translator: Nelson Ramírez  <nramirez@konos.cl>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: \n"
+"Language: es\n"
+"X-Generator: Poedit 2.2.4\n"
+
+#. module: helpdesk_phone
+#: model:ir.model,name:helpdesk_phone.model_helpdesk_ticket
+msgid "Helpdesk Ticket"
+msgstr "Tiquete del Servicio de Asistencia"
+
+#. module: helpdesk_phone
+#: model:ir.model.fields,field_description:helpdesk_phone.field_helpdesk_ticket__partner_phone
+msgid "Phone"
+msgstr "Teléfono"
diff --git a/helpdesk_phone/i18n/es_CL.po b/helpdesk_phone/i18n/es_CL.po
new file mode 100644
index 000000000..ac5428bdb
--- /dev/null
+++ b/helpdesk_phone/i18n/es_CL.po
@@ -0,0 +1,28 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# 	* helpdesk_phone
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 12.0+e-20191022\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2020-02-18 17:04+0000\n"
+"PO-Revision-Date: 2020-02-18 14:04-0300\n"
+"Last-Translator: Nelson Ramírez  <nramirez@konos.cl>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: \n"
+"Language: es\n"
+"X-Generator: Poedit 2.2.4\n"
+
+#. module: helpdesk_phone
+#: model:ir.model,name:helpdesk_phone.model_helpdesk_ticket
+msgid "Helpdesk Ticket"
+msgstr "Ticket Helpdesk"
+
+#. module: helpdesk_phone
+#: model:ir.model.fields,field_description:helpdesk_phone.field_helpdesk_ticket__partner_phone
+msgid "Phone"
+msgstr "Teléfono"
diff --git a/helpdesk_phone/models/__init__.py b/helpdesk_phone/models/__init__.py
new file mode 100644
index 000000000..2c98cdadf
--- /dev/null
+++ b/helpdesk_phone/models/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import helpdesk_phone
diff --git a/helpdesk_phone/models/helpdesk_phone.py b/helpdesk_phone/models/helpdesk_phone.py
new file mode 100644
index 000000000..95b863f02
--- /dev/null
+++ b/helpdesk_phone/models/helpdesk_phone.py
@@ -0,0 +1,10 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import fields, models
+
+
+class HelpdeskPhone(models.Model):
+    _inherit = "helpdesk.ticket"
+
+    partner_phone = fields.Char(related="partner_id.phone", string="Phone")
diff --git a/helpdesk_phone/static/description/icon.png b/helpdesk_phone/static/description/icon.png
new file mode 100644
index 000000000..84791119f
Binary files /dev/null and b/helpdesk_phone/static/description/icon.png differ
diff --git a/helpdesk_phone/views/helpdesk_phone.xml b/helpdesk_phone/views/helpdesk_phone.xml
new file mode 100644
index 000000000..0f07dc1df
--- /dev/null
+++ b/helpdesk_phone/views/helpdesk_phone.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<odoo>
+
+    <!-- Helpdesk Phone Form Extension-->
+    <record id="helpdesk_phone_form_inherit_ticket" model="ir.ui.view">
+        <field name="name">helpdesk.phone.form.ticket</field>
+        <field name="model">helpdesk.ticket</field>
+        <field name="inherit_id" ref="helpdesk.helpdesk_ticket_view_form" />
+        <field name="arch" type="xml">
+            <field name="partner_email" position="after">
+                <field name="partner_phone" widget="phone" readonly="1" />
+            </field>
+        </field>
+    </record>
+</odoo>
diff --git a/helpdesk_resolution/README.rst b/helpdesk_resolution/README.rst
new file mode 100644
index 000000000..9a56a8e17
--- /dev/null
+++ b/helpdesk_resolution/README.rst
@@ -0,0 +1,28 @@
+.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
+   :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+   :alt: License: LGPL-3
+
+===================
+Helpdesk Resolution
+===================
+
+This module allows the helpdesk user to store the resolution of a ticket.
+
+=====
+Usage
+=====
+
+* Create or edit a helpdesk ticket
+* Fill in the resolution field
+
+=======
+Credits
+=======
+
+* Maxime Chambreuil <mchambreuil@opensourceintegrators.com>
+
+Contributors
+------------
+
+* Open Source Integrators <contact@opensourceintegrators.com>
+* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
diff --git a/helpdesk_resolution/__init__.py b/helpdesk_resolution/__init__.py
new file mode 100644
index 000000000..7d768b54b
--- /dev/null
+++ b/helpdesk_resolution/__init__.py
@@ -0,0 +1,3 @@
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import models
diff --git a/helpdesk_resolution/__manifest__.py b/helpdesk_resolution/__manifest__.py
new file mode 100644
index 000000000..44618c588
--- /dev/null
+++ b/helpdesk_resolution/__manifest__.py
@@ -0,0 +1,20 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+{
+    "name": "Helpdesk Resolution",
+    "summary": "Keep the resolution of Helpdesk tickets",
+    "version": "14.0.1.0.0",
+    "category": "Helpdesk",
+    "author": "Open Source Integrators",
+    "website": "https://github.com/ursais/osi-addons",
+    "depends": [
+        "helpdesk",
+    ],
+    "data": ["views/helpdesk_ticket.xml"],
+    "installable": True,
+    "license": "LGPL-3",
+    "development_status": "Beta",
+    "maintainers": [
+        "max3903",
+    ],
+}
diff --git a/helpdesk_resolution/models/__init__.py b/helpdesk_resolution/models/__init__.py
new file mode 100644
index 000000000..51a7b174c
--- /dev/null
+++ b/helpdesk_resolution/models/__init__.py
@@ -0,0 +1,3 @@
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import helpdesk_ticket
diff --git a/helpdesk_resolution/models/helpdesk_ticket.py b/helpdesk_resolution/models/helpdesk_ticket.py
new file mode 100644
index 000000000..76123727c
--- /dev/null
+++ b/helpdesk_resolution/models/helpdesk_ticket.py
@@ -0,0 +1,12 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import fields, models
+
+
+class HelpdeskTicket(models.Model):
+    _inherit = "helpdesk.ticket"
+
+    resolution = fields.Text(
+        string="Resolution", placeholder="Resolution of the ticket..."
+    )
diff --git a/helpdesk_resolution/static/description/icon.png b/helpdesk_resolution/static/description/icon.png
new file mode 100644
index 000000000..84791119f
Binary files /dev/null and b/helpdesk_resolution/static/description/icon.png differ
diff --git a/helpdesk_resolution/views/helpdesk_ticket.xml b/helpdesk_resolution/views/helpdesk_ticket.xml
new file mode 100644
index 000000000..0c8439b03
--- /dev/null
+++ b/helpdesk_resolution/views/helpdesk_ticket.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<odoo>
+
+    <!-- Helpdesk Ticket with Resolution-->
+    <record id="helpdesk_ticket_form_resolution" model="ir.ui.view">
+        <field name="name">helpdesk.ticket.form.resolution</field>
+        <field name="model">helpdesk.ticket</field>
+        <field name="inherit_id" ref="helpdesk.helpdesk_ticket_view_form" />
+        <field name="arch" type="xml">
+            <field name="description" position="after">
+                <separator string="Resolution" />
+                <field name="resolution" />
+            </field>
+        </field>
+    </record>
+</odoo>
diff --git a/helpdesk_scope/README.rst b/helpdesk_scope/README.rst
new file mode 100644
index 000000000..4ff5716f5
--- /dev/null
+++ b/helpdesk_scope/README.rst
@@ -0,0 +1,36 @@
+.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
+   :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+   :alt: License: LGPL-3
+
+==============
+Helpdesk Scope
+==============
+
+Odoo Helpdesk App provides 2 ways to categorize tickets: the type (question or issue) and tags. 
+Tags are defined by the user and a ticket can have multiple tags. The SLA are related to the type of a ticket.
+
+For some organizations, the type and its SLA depends on the scope of the ticket: for example a ticket related to an outage 
+(type) needs to be solved within 2 days (SLA) if it impacts a single home (smaller scope) or 4 hours if it 
+impacts a street (larger scope). The SLA differs based on the scope.
+
+This module allows you to manage scopes and their types and SLA, as well as define the scope on the ticket. 
+
+
+Usage
+=====
+
+* Create a ticket
+* Select the helpdesk team. The scope list will be filtered based on the team.
+* Select the scope. The type will be filtered based on the scope.
+
+Credits
+=======
+
+* Steven Campbell <scampbell@opensourceintegrators.com>
+* Freni Patel <fpatel@opensourceintegrators.com>
+
+Contributors
+------------
+
+* Open Source Integrators <contact@opensourceintegrators.com>
+* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
diff --git a/helpdesk_scope/__init__.py b/helpdesk_scope/__init__.py
new file mode 100644
index 000000000..ccff08628
--- /dev/null
+++ b/helpdesk_scope/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import models
diff --git a/helpdesk_scope/__manifest__.py b/helpdesk_scope/__manifest__.py
new file mode 100644
index 000000000..8015dc1a7
--- /dev/null
+++ b/helpdesk_scope/__manifest__.py
@@ -0,0 +1,27 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+{
+    "name": "Helpdesk Scope",
+    "summary": "Improve Helpdesk by assigneing scope",
+    "version": "14.0.1.0.0",
+    "category": "Helpdesk",
+    "author": "Open Source Integrators",
+    "website": "https://github.com/ursais/osi-addons",
+    "depends": [
+        "helpdesk",
+    ],
+    "data": [
+        "security/ir.model.access.csv",
+        "views/helpdesk_scope.xml",
+        "views/helpdesk_ticket.xml",
+        "views/helpdesk_ticket_type.xml",
+        "views/helpdesk_team.xml",
+    ],
+    "installable": True,
+    "license": "LGPL-3",
+    "development_status": "Beta",
+    "maintainers": [
+        "wolfhall",
+        "max3903",
+    ],
+}
diff --git a/helpdesk_scope/models/__init__.py b/helpdesk_scope/models/__init__.py
new file mode 100644
index 000000000..bca531c31
--- /dev/null
+++ b/helpdesk_scope/models/__init__.py
@@ -0,0 +1,9 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import (
+    helpdesk_scope,
+    helpdesk_ticket,
+    helpdesk_ticket_type,
+    helpdesk_team,
+)
diff --git a/helpdesk_scope/models/helpdesk_scope.py b/helpdesk_scope/models/helpdesk_scope.py
new file mode 100644
index 000000000..c3e058149
--- /dev/null
+++ b/helpdesk_scope/models/helpdesk_scope.py
@@ -0,0 +1,20 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import fields, models
+
+
+class HelpdeskScope(models.Model):
+    _name = "helpdesk.scope"
+    _order = "sequence"
+    _description = "Helpdesk Scope"
+
+    name = fields.Char(string="Name", required=True)
+    description = fields.Text(string="Description")
+    sequence = fields.Integer(
+        required=True,
+        default=lambda self: self.env["ir.sequence"].next_by_code("helpdesk.scope")
+        or 0,
+    )
+    team_ids = fields.Many2many("helpdesk.team", string="Teams")
+    active = fields.Boolean("Active", default=True)
diff --git a/helpdesk_scope/models/helpdesk_team.py b/helpdesk_scope/models/helpdesk_team.py
new file mode 100644
index 000000000..e36222e9b
--- /dev/null
+++ b/helpdesk_scope/models/helpdesk_team.py
@@ -0,0 +1,12 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import fields, models
+
+
+class HelpdeskTeam(models.Model):
+    _inherit = "helpdesk.team"
+    _description = "Helpdesk Team"
+
+    use_scope = fields.Boolean("Scopes")
+    scope_ids = fields.Many2many("helpdesk.scope", string="Scopes")
diff --git a/helpdesk_scope/models/helpdesk_ticket.py b/helpdesk_scope/models/helpdesk_ticket.py
new file mode 100644
index 000000000..2a21947b4
--- /dev/null
+++ b/helpdesk_scope/models/helpdesk_ticket.py
@@ -0,0 +1,15 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import api, fields, models
+
+
+class HelpdeskTicket(models.Model):
+    _inherit = "helpdesk.ticket"
+
+    scope_id = fields.Many2one("helpdesk.scope", string="Scope", tracking=True)
+
+    @api.onchange("team_id")
+    def onchange_team_id(self):
+        if self.team_id not in self.scope_id.team_ids:
+            self.scope_id = False
diff --git a/helpdesk_scope/models/helpdesk_ticket_type.py b/helpdesk_scope/models/helpdesk_ticket_type.py
new file mode 100644
index 000000000..f402fae10
--- /dev/null
+++ b/helpdesk_scope/models/helpdesk_ticket_type.py
@@ -0,0 +1,10 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import fields, models
+
+
+class HelpdeskTicketType(models.Model):
+    _inherit = "helpdesk.ticket.type"
+
+    scope_ids = fields.Many2many("helpdesk.scope", string="Scopes")
diff --git a/helpdesk_scope/security/ir.model.access.csv b/helpdesk_scope/security/ir.model.access.csv
new file mode 100644
index 000000000..e384e30b7
--- /dev/null
+++ b/helpdesk_scope/security/ir.model.access.csv
@@ -0,0 +1,3 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_helpdesk_scope_helpdesk_user,helpdesk.scope.user,model_helpdesk_scope,helpdesk.group_helpdesk_user,1,0,0,0
+access_helpdesk_scope_helpdesk_manager,helpdesk.scope.manager,model_helpdesk_scope,helpdesk.group_helpdesk_manager,1,1,1,1
diff --git a/helpdesk_scope/static/description/icon.png b/helpdesk_scope/static/description/icon.png
new file mode 100644
index 000000000..84791119f
Binary files /dev/null and b/helpdesk_scope/static/description/icon.png differ
diff --git a/helpdesk_scope/views/helpdesk_scope.xml b/helpdesk_scope/views/helpdesk_scope.xml
new file mode 100644
index 000000000..518905439
--- /dev/null
+++ b/helpdesk_scope/views/helpdesk_scope.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<odoo>
+    <!-- Sequences-->
+    <record id="helpdesk_scope_seq" model="ir.sequence">
+      <field name="name">Helpdesk Scope Sequence</field>
+      <field name="code">helpdesk.scope</field>
+      <field name="prefix">0</field>
+      <field name="padding">1</field>
+    </record>
+
+    <!-- Helpdesk Scope -->
+    <record id="helpdesk_scope_tree_view" model="ir.ui.view">
+        <field name="name">Ticket Scopes</field>
+        <field name="model">helpdesk.scope</field>
+        <field name="arch" type="xml">
+            <tree editable="top" string="Helpdesk Scopes">
+                <field name="sequence" widget="handle" />
+                <field name="name" />
+                <field name="description" />
+                <field name="team_ids" widget="many2many_tags" />
+                <field name="active" />
+            </tree>
+        </field>
+    </record>
+
+    <record id="helpdesk_scope_from_view" model="ir.ui.view">
+        <field name="name">Ticket Scopes From</field>
+        <field name="model">helpdesk.scope</field>
+        <field name="arch" type="xml">
+             <form string="Helpdesk Scopes">
+                 <group col="4">
+                    <field name="name" />
+                    <field name="team_ids" widget="many2many_tags" />
+                </group>
+                <group>
+                    <field name="description" />
+                </group>
+            </form>
+        </field>
+    </record>
+
+    <record id="action_helpdesk_scope" model="ir.actions.act_window">
+        <field name="name">Helpdesk Scopes</field>
+        <field name="res_model">helpdesk.scope</field>
+        <field name="view_id" ref="helpdesk_scope_tree_view" />
+        <field name="view_mode">tree</field>
+        <field name="help" type="html">
+            <p class="oe_view_nocontent_create">
+                Create a helpdesk scope.
+            </p>
+            <p>
+                Module not yet enabled.
+            </p>
+        </field>
+    </record>
+
+    <menuitem
+        id="menu_ticket_scope"
+        name="Ticket Scopes"
+        action="action_helpdesk_scope"
+        parent="helpdesk.helpdesk_menu_config"
+        sequence="1"
+    />
+
+</odoo>
diff --git a/helpdesk_scope/views/helpdesk_team.xml b/helpdesk_scope/views/helpdesk_team.xml
new file mode 100644
index 000000000..d4e814f20
--- /dev/null
+++ b/helpdesk_scope/views/helpdesk_team.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<odoo>
+
+    <!-- Helpdesk Ticket Team Extension-->
+    <record id="helpdesk_ticket_team_extension_scope" model="ir.ui.view">
+        <field name="name">helpdesk.ticket.team.scope</field>
+        <field name="model">helpdesk.team</field>
+        <field name="inherit_id" ref="helpdesk.helpdesk_team_view_form" />
+        <field name="arch" type="xml">
+            <xpath expr="//div[@id='sla']" position="after">
+                <div class="col-md-6 o_setting_box" id="scope">
+                    <div class="o_setting_left_pane">
+                        <field name="use_scope" />
+                    </div>
+                    <div class="o_setting_right_pane">
+                        <label for="use_scope" />
+                        <div class="text-muted">
+                            Set up your Scopes
+                        </div>
+                        <div
+                            attrs="{'invisible': [('use_scope', '=', False)]}"
+                            class="mt16"
+                        >
+                            <label for="scope_ids" />
+                            <field name="scope_ids" widget="many2many_tags" />
+                        </div>
+                    </div>
+                </div>
+            </xpath>
+        </field>
+    </record>
+
+</odoo>
diff --git a/helpdesk_scope/views/helpdesk_ticket.xml b/helpdesk_scope/views/helpdesk_ticket.xml
new file mode 100644
index 000000000..a1f4916c0
--- /dev/null
+++ b/helpdesk_scope/views/helpdesk_ticket.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<odoo>
+
+    <!-- Helpdesk Ticket Scope Form Extension-->
+    <record id="helpdesk_ticket_form_extension_scope" model="ir.ui.view">
+        <field name="name">helpdesk.ticket.form.scope</field>
+        <field name="model">helpdesk.ticket</field>
+        <field name="inherit_id" ref="helpdesk.helpdesk_ticket_view_form" />
+        <field name="arch" type="xml">
+            <field name="priority" position="before">
+                <field name="scope_id" domain="[('team_ids', '=', team_id)]" />
+            </field>
+            <field name="ticket_type_id" position="attributes">
+                <attribute
+                    name="domain"
+                >[('scope_ids', '=', scope_id)]</attribute>
+            </field>
+        </field>
+    </record>
+</odoo>
diff --git a/helpdesk_scope/views/helpdesk_ticket_type.xml b/helpdesk_scope/views/helpdesk_ticket_type.xml
new file mode 100644
index 000000000..24a672d79
--- /dev/null
+++ b/helpdesk_scope/views/helpdesk_ticket_type.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<odoo>
+
+    <!-- Helpdesk Ticket Type Tree Extension-->
+    <record id="helpdesk_ticket_type_tree_extension_scope" model="ir.ui.view">
+        <field name="name">helpdesk.ticket.type.tree.scope</field>
+        <field name="model">helpdesk.ticket.type</field>
+        <field
+            name="inherit_id"
+            ref="helpdesk.helpdesk_ticket_type_view_tree"
+        />
+        <field name="arch" type="xml">
+            <field name="name" position="after">
+                <field name="scope_ids" widget="many2many_tags" />
+            </field>
+        </field>
+    </record>
+</odoo>
diff --git a/helpdesk_stage_server_action/README.rst b/helpdesk_stage_server_action/README.rst
new file mode 100644
index 000000000..8b7c5322d
--- /dev/null
+++ b/helpdesk_stage_server_action/README.rst
@@ -0,0 +1,114 @@
+==============================
+Helpdesk - Stage Server Action
+==============================
+
+.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   !! 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%2Ffield--service-lightgray.png?logo=github
+    :target: https://github.com/OCA/field-service/tree/12.0/fieldservice_skill
+    :alt: OCA/field-service
+.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
+    :target: https://translation.odoo-community.org/projects/field-service-12-0/field-service-12-0-fieldservice_skill
+    :alt: Translate me on Weblate
+.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
+    :target: https://runbot.odoo-community.org/runbot/264/12.0
+    :alt: Try me on Runbot
+
+|badge1| |badge2| |badge3| |badge4| |badge5| 
+
+
+
+**Table of contents**
+
+.. contents::
+   :local:
+
+Installation
+============
+
+To install Field Service and have the mapping features, you need to install GeoEngine.
+
+Please refer to the installation instructions available at:
+https://github.com/OCA/geospatial/tree/12.0/base_geoengine
+
+Configuration
+=============
+
+To configure this module, you need to:
+Helpdesk > Configuration > Stage
+Assign an Action to a Helpdesk Stage
+
+Usage
+=====
+
+Coming soon...
+
+
+Known issues / Roadmap
+======================
+
+The roadmap of the Field Service application is documented on
+`Github <https://github.com/OCA/field-service/issues/1>`_.
+
+Bug Tracker
+===========
+
+Bugs are tracked on `GitHub Issues <https://github.com/OCA/field-service/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 <https://github.com/OCA/field-service/issues/new?body=module:%20fieldservice_skill%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
+
+Do not contact contributors directly about support or help with technical issues.
+
+Credits
+=======
+
+Authors
+~~~~~~~
+
+* Open Source Integrators
+
+Contributors
+~~~~~~~~~~~~
+
+* Wolfgang Hall <whall@opensourceintegrators.com>
+* Maxime Chambreuil <mchambreuil@opensourceintegrators.com>
+* Steve Campbell <scampbell@opensourceintegrators.com>
+* Freni Patel <fpatel@opensourceintegrators.com>
+
+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-osi-scampbell| image:: https://github.com/osi-scampbell.png?size=40px
+    :target: https://github.com/osi-scampbell
+    :alt: osi-scampbell
+.. |maintainer-max3903| image:: https://github.com/max3903.png?size=40px
+    :target: https://github.com/max3903
+    :alt: max3903
+
+Current `maintainers <https://odoo-community.org/page/maintainer-role>`__:
+
+|maintainer-osi-scampbell| |maintainer-max3903| 
+
+This module is part of the `OCA/field-service <https://github.com/OCA/field-service/tree/12.0/fieldservice_skill>`_ project on GitHub.
+
+You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/helpdesk_stage_server_action/__init__.py b/helpdesk_stage_server_action/__init__.py
new file mode 100644
index 000000000..1ae95437a
--- /dev/null
+++ b/helpdesk_stage_server_action/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from . import models
diff --git a/helpdesk_stage_server_action/__manifest__.py b/helpdesk_stage_server_action/__manifest__.py
new file mode 100644
index 000000000..aa2cd28cc
--- /dev/null
+++ b/helpdesk_stage_server_action/__manifest__.py
@@ -0,0 +1,25 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+{
+    "name": "Helpdesk Stage Server Action",
+    "summary": "Add Server Actions based on Helpdesk Stage",
+    "version": "14.0.1.0.0",
+    "category": "Helpdesk",
+    "author": "Open Source Integrators",
+    "website": "https://github.com/ursais/osi-addons",
+    "depends": ["helpdesk", "base_automation"],
+    "data": [
+        "data/ir_servers_action.xml",
+        "data/base_automation.xml",
+        "data/helpdesk_stage.xml",
+        "views/helpdesk_stage.xml",
+    ],
+    "installable": True,
+    "license": "LGPL-3",
+    "development_status": "Beta",
+    "maintainers": [
+        "wolfhall",
+        "osi-scampbell",
+        "max3903",
+    ],
+}
diff --git a/helpdesk_stage_server_action/data/base_automation.xml b/helpdesk_stage_server_action/data/base_automation.xml
new file mode 100644
index 000000000..03c7a689a
--- /dev/null
+++ b/helpdesk_stage_server_action/data/base_automation.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<odoo>
+        <record
+        id="helpdesk_ticket_email_sender_create"
+        model="base.automation"
+    >
+            <field name="name">Helpdesk Ticket Email Sender Create</field>
+            <field name="model_id" ref="helpdesk.model_helpdesk_ticket" />
+            <field name="trigger">on_create</field>
+            <field name="active" eval="True" />
+            <field name="state">multi</field>
+            <field
+            name="child_ids"
+            eval="[(6, 0, [
+                    ref('helpdesk_ticket_parent_new')])
+                ]"
+        />
+        </record>
+
+        <record
+        id="helpdesk_ticket_email_sender_update"
+        model="base.automation"
+    >
+            <field name="name">Helpdesk Ticket Email Sender Update</field>
+            <field name="model_id" ref="helpdesk.model_helpdesk_ticket" />
+            <field name="trigger">on_change</field>
+            <field name="active" eval="True" />
+            <field name="state">multi</field>
+            <field
+            name="child_ids"
+            eval="[(6, 0, [
+                    ref('helpdesk_ticket_parent_monitoring'),
+                    ref('helpdesk_ticket_parent_solved'),
+                    ref('helpdesk_ticket_parent_canceled')])
+                ]"
+        />
+        </record>
+</odoo>
diff --git a/helpdesk_stage_server_action/data/helpdesk_stage.xml b/helpdesk_stage_server_action/data/helpdesk_stage.xml
new file mode 100644
index 000000000..ebda4c2e1
--- /dev/null
+++ b/helpdesk_stage_server_action/data/helpdesk_stage.xml
@@ -0,0 +1,19 @@
+<odoo>
+
+    <record id="helpdesk.stage_new" model="helpdesk.stage">
+        <field name="action_id" ref="helpdesk_ticket_parent_new" />
+    </record>
+
+    <record id="helpdesk.stage_in_progress" model="helpdesk.stage">
+        <field name="action_id" ref="helpdesk_ticket_parent_monitoring" />
+    </record>
+
+    <record id="helpdesk.stage_solved" model="helpdesk.stage">
+        <field name="action_id" ref="helpdesk_ticket_parent_solved" />
+    </record>
+
+    <record id="helpdesk.stage_cancelled" model="helpdesk.stage">
+        <field name="action_id" ref="helpdesk_ticket_parent_canceled" />
+    </record>
+
+</odoo>
diff --git a/helpdesk_stage_server_action/data/ir_servers_action.xml b/helpdesk_stage_server_action/data/ir_servers_action.xml
new file mode 100644
index 000000000..9caae5aa1
--- /dev/null
+++ b/helpdesk_stage_server_action/data/ir_servers_action.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<odoo>
+        <record id="helpdesk_ticket_parent_new" model="ir.actions.server">
+            <field name="name">Helpdesk Ticket Parent New</field>
+            <field name="model_id" ref="helpdesk.model_helpdesk_ticket" />
+            <field name="state">multi</field>
+        </record>
+
+        <record
+        id="helpdesk_ticket_parent_monitoring"
+        model="ir.actions.server"
+    >
+            <field name="name">Helpdesk Ticket Parent Monitoring</field>
+            <field name="model_id" ref="helpdesk.model_helpdesk_ticket" />
+            <field name="state">multi</field>
+        </record>
+
+        <record id="helpdesk_ticket_parent_solved" model="ir.actions.server">
+            <field name="name">Helpdesk Ticket Parent Solved</field>
+            <field name="model_id" ref="helpdesk.model_helpdesk_ticket" />
+            <field name="state">multi</field>
+        </record>
+
+        <record id="helpdesk_ticket_parent_canceled" model="ir.actions.server">
+            <field name="name">Helpdesk Ticket Parent Canceled</field>
+            <field name="model_id" ref="helpdesk.model_helpdesk_ticket" />
+            <field name="state">multi</field>
+        </record>
+</odoo>
diff --git a/helpdesk_stage_server_action/models/__init__.py b/helpdesk_stage_server_action/models/__init__.py
new file mode 100644
index 000000000..b6485f510
--- /dev/null
+++ b/helpdesk_stage_server_action/models/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from . import helpdesk_stage
diff --git a/helpdesk_stage_server_action/models/helpdesk_stage.py b/helpdesk_stage_server_action/models/helpdesk_stage.py
new file mode 100644
index 000000000..18d13fbdf
--- /dev/null
+++ b/helpdesk_stage_server_action/models/helpdesk_stage.py
@@ -0,0 +1,10 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from odoo import fields, models
+
+
+class HelpdeskStage(models.Model):
+    _inherit = "helpdesk.stage"
+
+    action_id = fields.Many2one("ir.actions.server", string="Action Id")
diff --git a/helpdesk_stage_server_action/static/description/icon.png b/helpdesk_stage_server_action/static/description/icon.png
new file mode 100644
index 000000000..84791119f
Binary files /dev/null and b/helpdesk_stage_server_action/static/description/icon.png differ
diff --git a/helpdesk_stage_server_action/views/helpdesk_stage.xml b/helpdesk_stage_server_action/views/helpdesk_stage.xml
new file mode 100644
index 000000000..1102bb93f
--- /dev/null
+++ b/helpdesk_stage_server_action/views/helpdesk_stage.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<odoo>
+
+    <!-- Fieldservice Stage Form View-->
+    <record id="helpdesk_server_action_stage_form_view" model="ir.ui.view">
+        <field name="name">helpdesk.server.action.stage.form</field>
+        <field name="model">helpdesk.stage</field>
+        <field name="inherit_id" ref="helpdesk.helpdesk_stage_view_form" />
+        <field name="arch" type="xml">
+            <field name="template_id" position="after">
+                <field name="action_id" />
+            </field>
+        </field>
+    </record>
+</odoo>
diff --git a/helpdesk_team_assigned_tickets/README.rst b/helpdesk_team_assigned_tickets/README.rst
new file mode 100644
index 000000000..be2ee5972
--- /dev/null
+++ b/helpdesk_team_assigned_tickets/README.rst
@@ -0,0 +1,33 @@
+.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
+   :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+   :alt: License: LGPL-3
+
+==============================
+Helpdesk Team Assigned Tickets
+==============================
+
+This module adds a field that counts the number of assigned tickets for a helpdesk team 
+and places the link under the field that counts the number of unassigned tickets. Also 
+adds search filter to filter for assigned tickets.  
+
+=====
+Usage
+=====
+
+* Create or edit a helpdesk ticket
+* Assign team to ticket
+* Assign user to ticket
+* Go to main kanban for helpdesk
+* The number of assigned tickets for that team should increase by 1
+
+=======
+Credits
+=======
+
+* Steven Campbell <scampbell@opensourceintegrators.com>
+* Freni Patel <fpatel@opensourceintegrators.com>
+
+Contributors
+------------
+
+* Open Source Integrators <contact@opensourceintegrators.com>
diff --git a/helpdesk_team_assigned_tickets/__init__.py b/helpdesk_team_assigned_tickets/__init__.py
new file mode 100644
index 000000000..47d2b2851
--- /dev/null
+++ b/helpdesk_team_assigned_tickets/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import models
diff --git a/helpdesk_team_assigned_tickets/__manifest__.py b/helpdesk_team_assigned_tickets/__manifest__.py
new file mode 100644
index 000000000..f5e17737d
--- /dev/null
+++ b/helpdesk_team_assigned_tickets/__manifest__.py
@@ -0,0 +1,16 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+{
+    "name": "Helpdesk Team Assigned Tickets",
+    "summary": "Display the number of Sssigned tickets on a Kanban Cards",
+    "version": "14.0.1.0.0",
+    "category": "Helpdesk",
+    "author": "Open Source Integrators",
+    "website": "https://github.com/ursais/osi-addons",
+    "depends": ["helpdesk"],
+    "data": ["views/helpdesk_team.xml"],
+    "installable": True,
+    "license": "LGPL-3",
+    "development_status": "Beta",
+    "maintainers": ["wolfhall", "max3903", "osi-scampbell"],
+}
diff --git a/helpdesk_team_assigned_tickets/models/__init__.py b/helpdesk_team_assigned_tickets/models/__init__.py
new file mode 100644
index 000000000..9d4e49fa8
--- /dev/null
+++ b/helpdesk_team_assigned_tickets/models/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import helpdesk
diff --git a/helpdesk_team_assigned_tickets/models/helpdesk.py b/helpdesk_team_assigned_tickets/models/helpdesk.py
new file mode 100644
index 000000000..b0bedf00f
--- /dev/null
+++ b/helpdesk_team_assigned_tickets/models/helpdesk.py
@@ -0,0 +1,28 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import fields, models
+
+
+class HelpdeskTeam(models.Model):
+    _inherit = "helpdesk.team"
+
+    assigned_tickets = fields.Integer(
+        string="Active Tickets", compute="_compute_assigned_tickets"
+    )
+
+    def _compute_assigned_tickets(self):
+        ticket_data = self.env["helpdesk.ticket"].read_group(
+            [
+                ("user_id", "!=", False),
+                ("team_id", "in", self.ids),
+                ("stage_id.is_close", "!=", True),
+            ],
+            ["team_id"],
+            ["team_id"],
+        )
+        mapped_data = {
+            data["team_id"][0]: data["team_id_count"] for data in ticket_data
+        }
+        for team in self:
+            team.assigned_tickets = mapped_data.get(team.id, 0)
diff --git a/helpdesk_team_assigned_tickets/static/description/icon.png b/helpdesk_team_assigned_tickets/static/description/icon.png
new file mode 100644
index 000000000..84791119f
Binary files /dev/null and b/helpdesk_team_assigned_tickets/static/description/icon.png differ
diff --git a/helpdesk_team_assigned_tickets/views/helpdesk_team.xml b/helpdesk_team_assigned_tickets/views/helpdesk_team.xml
new file mode 100644
index 000000000..83670cc77
--- /dev/null
+++ b/helpdesk_team_assigned_tickets/views/helpdesk_team.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<odoo>
+
+    <record id="helpdesk_ticket_action_assigned" model="ir.actions.act_window">
+        <field name="name">Tickets</field>
+        <field name="res_model">helpdesk.ticket</field>
+        <field name="view_mode">kanban,tree,form,activity</field>
+        <field name="context">{'search_default_team_id': active_id,
+            'search_default_assigned': True}
+        </field>
+        <field
+            name="search_view_id"
+            ref="helpdesk.helpdesk_tickets_view_search"
+        />
+        <field name="help" type="html">
+            <p class="o_view_nocontent_smiling_face">
+                Create a new ticket
+            </p>
+        </field>
+    </record>
+
+    <!-- Helpdesk Ticket Team Extension-->
+    <record id="helpdesk_ticket_team_extension_unassigned" model="ir.ui.view">
+        <field name="name">helpdesk.ticket.team.unassigned</field>
+        <field name="model">helpdesk.team</field>
+        <field name="inherit_id" ref="helpdesk.helpdesk_team_view_kanban" />
+        <field name="arch" type="xml">
+            <field name="unassigned_tickets" position="after">
+                <field name="assigned_tickets" />
+            </field>
+            <xpath
+                expr="//div[hasclass('o_kanban_primary_right')]/div[2]"
+                position="after"
+            >
+                <div class="mb4">
+                    <a
+                        name="%(helpdesk_team_assigned_tickets.helpdesk_ticket_action_assigned)d"
+                        type="action"
+                        context="{'search_default_team_id': active_id, 'default_team_id': active_id}"
+                    >
+                        <t t-esc="record.assigned_tickets.raw_value" />
+                        Assigned Tickets
+                    </a>
+                </div>
+            </xpath>
+        </field>
+    </record>
+
+    <record id="helpdesk_ticket_view_search_assign" model="ir.ui.view">
+        <field name="name">helpdesk.ticket.search.assign</field>
+        <field name="model">helpdesk.ticket</field>
+        <field name="inherit_id" ref="helpdesk.helpdesk_tickets_view_search" />
+        <field name="arch" type="xml">
+            <xpath expr="//filter[@name='unassigned']" position="before">
+                <filter
+                    string="Assigned Tickets"
+                    domain="[('user_id','!=',False)]"
+                    name="assigned"
+                />
+            </xpath>
+        </field>
+    </record>
+
+    <record id="helpdesk_ticket_active_id" model="ir.ui.view">
+        <field name="name">helpdesk.ticket.active.id</field>
+        <field name="model">helpdesk.ticket</field>
+        <field name="inherit_id" ref="helpdesk.helpdesk_ticket_view_form" />
+        <field name="arch" type="xml">
+            <field name="stage_id" position="attributes">
+                <attribute name="context">{'active_id': id, 'active_ids': [id],
+                    'active_model': 'helpdesk.ticket'}
+                </attribute>
+            </field>
+        </field>
+    </record>
+
+</odoo>
diff --git a/helpdesk_ticket_parent/README.rst b/helpdesk_ticket_parent/README.rst
new file mode 100644
index 000000000..8433d98d5
--- /dev/null
+++ b/helpdesk_ticket_parent/README.rst
@@ -0,0 +1,40 @@
+.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
+   :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+   :alt: License: LGPL-3
+
+========================
+Helpdesk - Parent Ticket
+========================
+
+Odoo Helpdesk does not allow to relate tickets with each others.
+
+Helpdesk teams need a way to track several individual issues under one parent
+ticket. This type of ticket is usually created during troubleshooting when an
+agent (Levels II and II) detects that the issue is further away from the
+end-user who reported it and it is affecting or will potentially impact other
+end-users or dependent products/services.
+
+This module allows the helpdesk user to set a parent-children relationship
+between helpdesk tickets.
+
+Usage
+=====
+
+* Go to Helpdesk
+* Create or select a ticket
+* Set his parent
+* Go to the parent to see all his children
+* In the search view, use the Parents filter to get the list of tickets whose
+  parent is not set. Use the Children one to get the ones whose parent is set.
+
+Credits
+=======
+
+* Steve Campbell <scampbell@opensourceintegrators.com>
+* Freni Patel <fpatel@opensourceintegrators.com>
+
+Contributors
+------------
+
+* Open Source Integrators <https://www.opensourceintegrators.com>
+* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
diff --git a/helpdesk_ticket_parent/__init__.py b/helpdesk_ticket_parent/__init__.py
new file mode 100644
index 000000000..7d768b54b
--- /dev/null
+++ b/helpdesk_ticket_parent/__init__.py
@@ -0,0 +1,3 @@
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import models
diff --git a/helpdesk_ticket_parent/__manifest__.py b/helpdesk_ticket_parent/__manifest__.py
new file mode 100644
index 000000000..836f7f8f4
--- /dev/null
+++ b/helpdesk_ticket_parent/__manifest__.py
@@ -0,0 +1,16 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+{
+    "name": "Helpdesk Ticket Parent",
+    "summary": "Add Parent/Child relationship to Helpdesk Ticket",
+    "version": "14.0.1.0.0",
+    "category": "Helpdesk",
+    "author": "Open Source Integrators",
+    "website": "https://github.com/ursais/osi-addons",
+    "depends": ["helpdesk_timesheet"],
+    "data": ["views/helpdesk_ticket.xml"],
+    "installable": True,
+    "license": "LGPL-3",
+    "development_status": "Beta",
+    "maintainers": ["wolfhall", "max3903", "osi-scampbell"],
+}
diff --git a/helpdesk_ticket_parent/models/__init__.py b/helpdesk_ticket_parent/models/__init__.py
new file mode 100644
index 000000000..51a7b174c
--- /dev/null
+++ b/helpdesk_ticket_parent/models/__init__.py
@@ -0,0 +1,3 @@
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import helpdesk_ticket
diff --git a/helpdesk_ticket_parent/models/helpdesk_ticket.py b/helpdesk_ticket_parent/models/helpdesk_ticket.py
new file mode 100644
index 000000000..49c1bc0d1
--- /dev/null
+++ b/helpdesk_ticket_parent/models/helpdesk_ticket.py
@@ -0,0 +1,11 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import fields, models
+
+
+class HelpdeskTicket(models.Model):
+    _inherit = "helpdesk.ticket"
+
+    parent_id = fields.Many2one("helpdesk.ticket", string="Parent")
+    child_ids = fields.One2many("helpdesk.ticket", "parent_id", string="Children")
diff --git a/helpdesk_ticket_parent/static/description/icon.png b/helpdesk_ticket_parent/static/description/icon.png
new file mode 100644
index 000000000..84791119f
Binary files /dev/null and b/helpdesk_ticket_parent/static/description/icon.png differ
diff --git a/helpdesk_ticket_parent/views/helpdesk_ticket.xml b/helpdesk_ticket_parent/views/helpdesk_ticket.xml
new file mode 100644
index 000000000..615f2326f
--- /dev/null
+++ b/helpdesk_ticket_parent/views/helpdesk_ticket.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<odoo>
+
+    <!-- Helpdesk Ticket Form Extension-->
+    <record id="helpdesk_ticket_form_parent" model="ir.ui.view">
+        <field name="name">helpdesk.ticket.form.parent</field>
+        <field name="model">helpdesk.ticket</field>
+        <field
+            name="inherit_id"
+            ref="helpdesk_timesheet.helpdesk_ticket_view_form_inherit_helpdesk_timesheet"
+        />
+        <field name="arch" type="xml">
+            <xpath expr="//notebook" postition="inside" sequence="20">
+                <page string="Children">
+                    <field name="child_ids">
+                        <tree>
+                            <field name="name" />
+                            <field name="partner_id" />
+                            <field name="user_id" />
+                            <field name="priority" />
+                            <field name="stage_id" />
+                        </tree>
+                    </field>
+                </page>
+            </xpath>
+            <field name="tag_ids" position="after">
+                <field name="parent_id" />
+            </field>
+        </field>
+    </record>
+
+    <record id="helpdesk_tickets_view_search_parent_child" model="ir.ui.view">
+        <field name="name">helpdesk.ticket.select.parent.child</field>
+        <field name="model">helpdesk.ticket</field>
+        <field name="inherit_id" ref="helpdesk.helpdesk_tickets_view_search" />
+        <field name="arch" type="xml">
+            <xpath expr="//group/filter[@name='stage']" position="after">
+                <filter
+                    string="Parents"
+                    name='parents'
+                    domain="[('parent_id', '=', False)]"
+                />
+                <filter
+                    string="Children"
+                    name='children'
+                    domain="[('parent_id', '!=', False)]"
+                />
+            </xpath>
+        </field>
+    </record>
+
+</odoo>
diff --git a/helpdesk_ticket_to_task/README.rst b/helpdesk_ticket_to_task/README.rst
new file mode 100644
index 000000000..fbd45f75f
--- /dev/null
+++ b/helpdesk_ticket_to_task/README.rst
@@ -0,0 +1,26 @@
+.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
+   :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+   :alt: License: LGPL-3
+
+=======================
+Helpdesk Ticket to Task
+=======================
+
+This module will improve Ticket and Task functionality.
+
+Usage
+=====
+
+* Users allow to add multiple tasks for one Ticket.
+* Users allow to add multiple tickets for one Task.
+
+Credits
+=======
+
+* Bhavesh Odedra <bodedra@opensourceintegrators.com>
+
+Contributors
+------------
+
+* Open Source Integrators <contact@opensourceintegrators.com>
+* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
diff --git a/helpdesk_ticket_to_task/__init__.py b/helpdesk_ticket_to_task/__init__.py
new file mode 100644
index 000000000..47d2b2851
--- /dev/null
+++ b/helpdesk_ticket_to_task/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import models
diff --git a/helpdesk_ticket_to_task/__manifest__.py b/helpdesk_ticket_to_task/__manifest__.py
new file mode 100644
index 000000000..19e99150a
--- /dev/null
+++ b/helpdesk_ticket_to_task/__manifest__.py
@@ -0,0 +1,23 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+{
+    "name": "Tickets to multiple tasks relationships",
+    "summary": "Tickets to multiple tasks relationships",
+    "version": "14.0.1.0.0",
+    "license": "LGPL-3",
+    "author": "Open Source Integrators, Odoo Community Association (OCA)",
+    "category": "Helpdesk",
+    "website": "https://github.com/ursais/osi-addons",
+    "depends": [
+        "helpdesk",
+        "helpdesk_timesheet",
+    ],
+    "data": [
+        "security/ir.model.access.csv",
+        "views/helpdesk_ticket_views.xml",
+        "views/project_task_views.xml",
+    ],
+    "maintainers": ["Open Source Integrators"],
+    "installable": True,
+}
diff --git a/helpdesk_ticket_to_task/models/__init__.py b/helpdesk_ticket_to_task/models/__init__.py
new file mode 100644
index 000000000..237934e36
--- /dev/null
+++ b/helpdesk_ticket_to_task/models/__init__.py
@@ -0,0 +1,5 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import helpdesk_ticket
+from . import project_task
diff --git a/helpdesk_ticket_to_task/models/helpdesk_ticket.py b/helpdesk_ticket_to_task/models/helpdesk_ticket.py
new file mode 100644
index 000000000..a76c70477
--- /dev/null
+++ b/helpdesk_ticket_to_task/models/helpdesk_ticket.py
@@ -0,0 +1,41 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import fields, models
+
+
+class HelpdeskTicket(models.Model):
+    _inherit = "helpdesk.ticket"
+
+    helpdesk_ticket_task_line = fields.One2many(
+        "helpdesk.ticket.task",
+        "ticket_id",
+        string="Ticket Tasks",
+    )
+
+
+class HelpdeskTicketTask(models.Model):
+    _name = "helpdesk.ticket.task"
+    _description = "Helpdesk Ticket Task"
+
+    ticket_id = fields.Many2one(
+        "helpdesk.ticket",
+        string="Ticket",
+    )
+    project_id = fields.Many2one(related="ticket_id.project_id", string="Project")
+    task_id = fields.Many2one(
+        "project.task",
+        string="Task",
+    )
+    user_id = fields.Many2one(
+        related="task_id.user_id",
+        string="Assigned to",
+    )
+    planned_hours = fields.Float(
+        string="Planned Hours",
+        related="task_id.planned_hours",
+    )
+    effective_hours = fields.Float(
+        string="Actual Hours",
+        related="task_id.effective_hours",
+    )
diff --git a/helpdesk_ticket_to_task/models/project_task.py b/helpdesk_ticket_to_task/models/project_task.py
new file mode 100644
index 000000000..acbca6b10
--- /dev/null
+++ b/helpdesk_ticket_to_task/models/project_task.py
@@ -0,0 +1,30 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import fields, models
+
+
+class ProjectTask(models.Model):
+    _inherit = "project.task"
+
+    project_task_ticket_line = fields.One2many(
+        "project.task.ticket",
+        "task_id",
+        string="Task Tickets",
+    )
+
+
+class ProjectTaskTicket(models.Model):
+    _name = "project.task.ticket"
+    _description = "Project Task Ticket"
+
+    task_id = fields.Many2one(
+        "project.task",
+        string="Task",
+    )
+    ticket_id = fields.Many2one(
+        "helpdesk.ticket",
+        string="Ticket",
+    )
+    project_id = fields.Many2one(related="task_id.project_id", string="Project")
+    user_id = fields.Many2one(related="ticket_id.user_id", string="Assigned to")
diff --git a/helpdesk_ticket_to_task/security/ir.model.access.csv b/helpdesk_ticket_to_task/security/ir.model.access.csv
new file mode 100644
index 000000000..f5cbe6b1b
--- /dev/null
+++ b/helpdesk_ticket_to_task/security/ir.model.access.csv
@@ -0,0 +1,9 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_project_task_ticket_user,access_project_task_ticket,model_project_task_ticket,helpdesk.group_helpdesk_user,1,1,1,1
+access_helpdesk_ticket_task_user,access_helpdesk_ticket_task,model_helpdesk_ticket_task,helpdesk.group_helpdesk_user,1,1,1,1
+access_project_task_ticket_manager,access_project_task_ticket,model_project_task_ticket,project.group_project_manager,1,1,1,1
+access_helpdesk_ticket_task_manager,access_helpdesk_ticket_task,model_helpdesk_ticket_task,project.group_project_manager,1,1,1,1
+access_project_task_ticket_helpdeskuser,access_project_task_ticket,model_project_task_ticket,project.group_project_user,1,1,1,1
+access_helpdesk_ticket_task_helpdeskuser,access_helpdesk_ticket_task,model_helpdesk_ticket_task,project.group_project_user,1,1,1,1
+access_project_task_ticket_helpdeskmanager,access_project_task_ticket,model_project_task_ticket,helpdesk.group_helpdesk_manager,1,1,1,1
+access_helpdesk_ticket_task_helpdeskmanager,access_helpdesk_ticket_task,model_helpdesk_ticket_task,helpdesk.group_helpdesk_manager,1,1,1,1
diff --git a/helpdesk_ticket_to_task/static/description/icon.png b/helpdesk_ticket_to_task/static/description/icon.png
new file mode 100644
index 000000000..84791119f
Binary files /dev/null and b/helpdesk_ticket_to_task/static/description/icon.png differ
diff --git a/helpdesk_ticket_to_task/views/helpdesk_ticket_views.xml b/helpdesk_ticket_to_task/views/helpdesk_ticket_views.xml
new file mode 100644
index 000000000..213f1cd9c
--- /dev/null
+++ b/helpdesk_ticket_to_task/views/helpdesk_ticket_views.xml
@@ -0,0 +1,42 @@
+<odoo>
+<!-- Copyright 2021 Open Source Integrators
+     License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
+
+    <!-- Helpdesk Ticket Form View -->
+    <record id="helpdesk_ticket_view_project_tasks_form" model="ir.ui.view">
+        <field name="name">helpdesk.ticket.project.tasks.form</field>
+        <field name="model">helpdesk.ticket</field>
+        <field
+            name="inherit_id"
+            ref="helpdesk_timesheet.helpdesk_ticket_view_form_inherit_helpdesk_timesheet"
+        />
+        <field name="arch" type="xml">
+            <page position="after">
+                <page string="Tasks">
+                    <field name="helpdesk_ticket_task_line">
+                        <tree editable="bottom">
+                            <field
+                                name="task_id"
+                                context="{'default_project_id': parent.project_id}"
+                            />
+                            <field name="user_id" readonly="1" />
+                            <field
+                                name="planned_hours"
+                                widget="float_time"
+                                readonly="1"
+                            />
+                            <field
+                                name="effective_hours"
+                                widget="float_time"
+                                readonly="1"
+                            />
+                        </tree>
+                    </field>
+                </page>
+            </page>
+            <field name="task_id" position="attributes">
+                <attribute name="invisible">1</attribute>
+            </field>
+        </field>
+    </record>
+</odoo>
diff --git a/helpdesk_ticket_to_task/views/project_task_views.xml b/helpdesk_ticket_to_task/views/project_task_views.xml
new file mode 100644
index 000000000..7ca47886a
--- /dev/null
+++ b/helpdesk_ticket_to_task/views/project_task_views.xml
@@ -0,0 +1,26 @@
+<odoo>
+<!-- Copyright 2021 Open Source Integrators
+     License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
+
+    <!-- Tasks Form View -->
+    <record id="view_project_tasks_ticket_form" model="ir.ui.view">
+        <field name="name">project.task</field>
+        <field name="model">project.task</field>
+        <field name="inherit_id" ref="project.view_task_form2" />
+        <field name="arch" type="xml">
+            <page position="after">
+                <page string="Tickets">
+                    <field name="project_task_ticket_line">
+                        <tree editable="bottom">
+                            <field
+                                name="ticket_id"
+                                context="{'default_project_id': parent.project_id}"
+                            />
+                            <field name="user_id" readonly="1" />
+                        </tree>
+                    </field>
+                </page>
+            </page>
+        </field>
+    </record>
+</odoo>
diff --git a/helpdesk_ticket_type_default_priority/README.rst b/helpdesk_ticket_type_default_priority/README.rst
new file mode 100644
index 000000000..19099c0c6
--- /dev/null
+++ b/helpdesk_ticket_type_default_priority/README.rst
@@ -0,0 +1,33 @@
+.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
+   :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+   :alt: License: LGPL-3
+
+=====================================
+Helpdesk Ticket Type Default Priority
+=====================================
+
+This module allows you to set a default priority on the ticket based on its type.
+
+Configuration
+=============
+
+* Go to Helpdesk > Configuration > Ticket Types
+* Create or edit a type to set the default priority
+
+Usage
+=====
+
+* Create a ticket
+* Select the type
+* The priority is automatically set based on the selected type
+
+Credits
+=======
+
+* Maxime Chambreuil <mchambreuil@opensourceintegrators.com>
+
+Contributors
+------------
+
+* Open Source Integrators <http://www.opensourceintegrators.com>
+* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
diff --git a/helpdesk_ticket_type_default_priority/__init__.py b/helpdesk_ticket_type_default_priority/__init__.py
new file mode 100644
index 000000000..47d2b2851
--- /dev/null
+++ b/helpdesk_ticket_type_default_priority/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import models
diff --git a/helpdesk_ticket_type_default_priority/__manifest__.py b/helpdesk_ticket_type_default_priority/__manifest__.py
new file mode 100644
index 000000000..b65093b7a
--- /dev/null
+++ b/helpdesk_ticket_type_default_priority/__manifest__.py
@@ -0,0 +1,23 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+{
+    "name": "Helpdesk Ticket Type Default Priority",
+    "summary": "Set the priority based on the type",
+    "version": "14.0.1.0.0",
+    "category": "Helpdesk",
+    "author": "Open Source Integrators",
+    "website": "https://github.com/ursais/osi-addons",
+    "depends": [
+        "helpdesk",
+    ],
+    "data": [
+        "views/helpdesk_ticket_type_views.xml",
+    ],
+    "installable": True,
+    "license": "LGPL-3",
+    "maintainers": [
+        "wolfhall",
+        "max3903",
+    ],
+}
diff --git a/helpdesk_ticket_type_default_priority/models/__init__.py b/helpdesk_ticket_type_default_priority/models/__init__.py
new file mode 100644
index 000000000..166eca9b3
--- /dev/null
+++ b/helpdesk_ticket_type_default_priority/models/__init__.py
@@ -0,0 +1,7 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import (
+    helpdesk_ticket,
+    helpdesk_ticket_type,
+)
diff --git a/helpdesk_ticket_type_default_priority/models/helpdesk_ticket.py b/helpdesk_ticket_type_default_priority/models/helpdesk_ticket.py
new file mode 100644
index 000000000..7410b1c8f
--- /dev/null
+++ b/helpdesk_ticket_type_default_priority/models/helpdesk_ticket.py
@@ -0,0 +1,15 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import api, models
+
+
+class HelpdeskTicket(models.Model):
+    _inherit = "helpdesk.ticket"
+
+    @api.onchange("ticket_type_id")
+    def _onchange_ticket_type_id(self):
+        if self.ticket_type_id:
+            self.priority = self.ticket_type_id.default_priority
+        else:
+            self.priority = "0"
diff --git a/helpdesk_ticket_type_default_priority/models/helpdesk_ticket_type.py b/helpdesk_ticket_type_default_priority/models/helpdesk_ticket_type.py
new file mode 100644
index 000000000..f1ece504d
--- /dev/null
+++ b/helpdesk_ticket_type_default_priority/models/helpdesk_ticket_type.py
@@ -0,0 +1,14 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import fields, models
+
+
+class HelpdeskTicketType(models.Model):
+    _inherit = "helpdesk.ticket.type"
+
+    default_priority = fields.Selection(
+        [("0", "All"), ("1", "Low Priority"), ("2", "High Priority"), ("3", "Urgent")],
+        string="Default Priority",
+        default="0",
+    )
diff --git a/helpdesk_ticket_type_default_priority/static/description/icon.png b/helpdesk_ticket_type_default_priority/static/description/icon.png
new file mode 100644
index 000000000..84791119f
Binary files /dev/null and b/helpdesk_ticket_type_default_priority/static/description/icon.png differ
diff --git a/helpdesk_ticket_type_default_priority/views/helpdesk_ticket_type_views.xml b/helpdesk_ticket_type_default_priority/views/helpdesk_ticket_type_views.xml
new file mode 100644
index 000000000..6383b73c9
--- /dev/null
+++ b/helpdesk_ticket_type_default_priority/views/helpdesk_ticket_type_views.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<odoo>
+
+    <record id="helpdesk_ticket_type_view_tree" model="ir.ui.view">
+        <field name="name">helpdesk.ticket.type.tree</field>
+        <field name="model">helpdesk.ticket.type</field>
+        <field
+            name="inherit_id"
+            ref="helpdesk.helpdesk_ticket_type_view_tree"
+        />
+        <field name="arch" type="xml">
+            <field name="name" position="after">
+                <field name="default_priority" widget="priority" />
+            </field>
+        </field>
+    </record>
+
+    <menuitem
+        id="helpdesk.helpdesk_ticket_type_menu"
+        name="Ticket Types"
+        action="helpdesk.helpdesk_ticket_type_action"
+        sequence="1"
+        parent="helpdesk.helpdesk_menu_config"
+        groups="base.group_no_one"
+    />
+
+</odoo>
diff --git a/helpdesk_timesheet_fieldservice/README.rst b/helpdesk_timesheet_fieldservice/README.rst
new file mode 100644
index 000000000..9babee3a3
--- /dev/null
+++ b/helpdesk_timesheet_fieldservice/README.rst
@@ -0,0 +1,30 @@
+==================================
+Helpdesk Timesheet - Field Service
+==================================
+
+.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
+   :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+   :alt: License: LGPL-3
+
+This module fixes the form view of the helpdesk ticket when `helpdesk_timesheet` and
+`helpdesk_fieldservice` are installed together.
+
+Usage
+=====
+
+* Go to Helpdesk
+* Create or select a ticket
+* In the "Service Requests" tab, you can create service requests for the FSM team
+
+To close a ticket, all the related service orders must be closed.
+
+Credits
+=======
+
+* Maxime Chambreuil <mchambreuil@opensourceintegrators.com>
+* Freni Patel <fpatel@opensourceintegrators.com>
+
+Contributors
+------------
+
+* Open Source Integrators <contact@opensourceintegrators.com>
diff --git a/helpdesk_timesheet_fieldservice/__init__.py b/helpdesk_timesheet_fieldservice/__init__.py
new file mode 100644
index 000000000..b9a9d2d72
--- /dev/null
+++ b/helpdesk_timesheet_fieldservice/__init__.py
@@ -0,0 +1,1 @@
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
diff --git a/helpdesk_timesheet_fieldservice/__manifest__.py b/helpdesk_timesheet_fieldservice/__manifest__.py
new file mode 100644
index 000000000..8f2a64cc5
--- /dev/null
+++ b/helpdesk_timesheet_fieldservice/__manifest__.py
@@ -0,0 +1,20 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+{
+    "name": "Helpdesk Timesheet - Field Service",
+    "summary": "Create FSM Orders and Timesheet from Helpdesk Ticket",
+    "version": "14.0.1.0.0",
+    "license": "LGPL-3",
+    "author": "Open Source Integrators",
+    "category": "Helpdesk",
+    "website": "https://github.com/ursais/osi-addons",
+    "depends": [
+        "helpdesk_timesheet",
+        "helpdesk_fieldservice",
+    ],
+    "data": [
+        "views/helpdesk_ticket.xml",
+    ],
+    "auto_install": True,
+    "maintainers": ["bodedra"],
+}
diff --git a/helpdesk_timesheet_fieldservice/static/description/icon.png b/helpdesk_timesheet_fieldservice/static/description/icon.png
new file mode 100644
index 000000000..955674d8f
Binary files /dev/null and b/helpdesk_timesheet_fieldservice/static/description/icon.png differ
diff --git a/helpdesk_timesheet_fieldservice/views/helpdesk_ticket.xml b/helpdesk_timesheet_fieldservice/views/helpdesk_ticket.xml
new file mode 100644
index 000000000..8eb1c979d
--- /dev/null
+++ b/helpdesk_timesheet_fieldservice/views/helpdesk_ticket.xml
@@ -0,0 +1,19 @@
+<!-- Copyright (c) 2021 Open Source Integrators
+     License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
+<odoo>
+
+    <!-- Helpdesk Ticket Form View -->
+    <record id="helpdesk_ticket_view_fieldservice_form" model="ir.ui.view">
+        <field name="name">helpdesk.ticket.fieldservice.form</field>
+        <field name="model">helpdesk.ticket</field>
+        <field name="inherit_id" ref="helpdesk.helpdesk_ticket_view_form" />
+        <field name="arch" type="xml">
+            <xpath expr="//notebook" position="inside">
+                 <page name="helpdesk_service_order_page" position="move" />
+            </xpath>
+            <notebook name="helpdesk_fieldservice_book" position="replace">
+            </notebook>
+        </field>
+    </record>
+
+</odoo>
diff --git a/osi_analytic_sales_simple/README.rst b/osi_analytic_sales_simple/README.rst
new file mode 100644
index 000000000..077d2a2ff
--- /dev/null
+++ b/osi_analytic_sales_simple/README.rst
@@ -0,0 +1,28 @@
+.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
+   :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+   :alt: License: LGPL-3
+
+=========================
+OSI Analytic Sales Simple
+=========================
+
+This module adds analytic accounting functionality to sale order lines
+
+Usage
+=====
+
+No special usage instructions
+
+Credits
+=======
+
+* Mayank Gosai <mgosai@ursainfosystems.com>
+* Bhavesh Odedra <bodedra@opensourceintegrators.com>
+* Michael Allen <mallen@opensourceintegrators.com>
+* Freni Patel <fpatel@opensourceintegrators.com>
+
+Contributors
+------------
+
+* Open Source Integrators <http://www.opensourceintegrators.com>
+* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
diff --git a/osi_analytic_sales_simple/__init__.py b/osi_analytic_sales_simple/__init__.py
new file mode 100644
index 000000000..548493cda
--- /dev/null
+++ b/osi_analytic_sales_simple/__init__.py
@@ -0,0 +1,4 @@
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import models
+from . import wizard
diff --git a/osi_analytic_sales_simple/__manifest__.py b/osi_analytic_sales_simple/__manifest__.py
new file mode 100644
index 000000000..56786701c
--- /dev/null
+++ b/osi_analytic_sales_simple/__manifest__.py
@@ -0,0 +1,19 @@
+# Copyright (C) 2019 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+{
+    "name": "OSI Analytic Sales Simple",
+    "version": "14.0.1.0.0",
+    "license": "LGPL-3",
+    "summary": "Analytic Accounts for sale order lines",
+    "author": "Open Source Integrators",
+    "maintainer": "Open Source Integrators",
+    "website": "https://github.com/ursais/osi-addons",
+    "category": "Analytic Accounting",
+    "depends": ["stock_account", "sale"],
+    "data": [
+        "views/sale_order_view.xml",
+    ],
+    "installable": True,
+    "maintainers": ["bodedra"],
+}
diff --git a/osi_analytic_sales_simple/models/__init__.py b/osi_analytic_sales_simple/models/__init__.py
new file mode 100644
index 000000000..22dc33cdf
--- /dev/null
+++ b/osi_analytic_sales_simple/models/__init__.py
@@ -0,0 +1,3 @@
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import account_move, sale_order_line
diff --git a/osi_analytic_sales_simple/models/account_move.py b/osi_analytic_sales_simple/models/account_move.py
new file mode 100644
index 000000000..9513fa045
--- /dev/null
+++ b/osi_analytic_sales_simple/models/account_move.py
@@ -0,0 +1,80 @@
+# Copyright (C) 2019 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import models
+
+
+class AccountMove(models.Model):
+    _inherit = "account.move"
+
+    def _stock_account_prepare_anglo_saxon_out_lines_vals(self):
+        lines_vals_list = []
+        for move in self:
+            if (
+                not move.is_sale_document(include_receipts=True)
+                or not move.company_id.anglo_saxon_accounting
+            ):
+                continue
+
+            for line in move.invoice_line_ids:
+
+                # Filter out lines being not eligible for COGS.
+                if (
+                    line.product_id.type != "product"
+                    or line.product_id.valuation != "real_time"
+                ):
+                    continue
+
+                # Retrieve accounts needed to generate the COGS.
+                accounts = line.product_id.product_tmpl_id.with_company(
+                    line.company_id
+                ).get_product_accounts(fiscal_pos=move.fiscal_position_id)
+                debit_interim_account = accounts["stock_output"]
+                credit_expense_account = (
+                    accounts["expense"] or self.journal_id.default_account_id
+                )
+                if not debit_interim_account or not credit_expense_account:
+                    continue
+
+                # Compute accounting fields.
+                sign = -1 if move.move_type == "out_refund" else 1
+                price_unit = line._stock_account_get_anglo_saxon_price_unit()
+                balance = sign * line.quantity * price_unit
+
+                # Add interim account line.
+                lines_vals_list.append(
+                    {
+                        "name": line.name[:64],
+                        "move_id": move.id,
+                        "product_id": line.product_id.id,
+                        "product_uom_id": line.product_uom_id.id,
+                        "quantity": line.quantity,
+                        "price_unit": price_unit,
+                        "debit": balance < 0.0 and -balance or 0.0,
+                        "credit": balance > 0.0 and balance or 0.0,
+                        "account_id": debit_interim_account.id,
+                        "analytic_account_id": line.analytic_account_id.id,
+                        "exclude_from_invoice_tab": True,
+                        "is_anglo_saxon_line": True,
+                    }
+                )
+
+                # Add expense account line.
+                lines_vals_list.append(
+                    {
+                        "name": line.name[:64],
+                        "move_id": move.id,
+                        "product_id": line.product_id.id,
+                        "product_uom_id": line.product_uom_id.id,
+                        "quantity": line.quantity,
+                        "price_unit": -price_unit,
+                        "debit": balance > 0.0 and balance or 0.0,
+                        "credit": balance < 0.0 and -balance or 0.0,
+                        "account_id": credit_expense_account.id,
+                        "analytic_account_id": line.analytic_account_id.id,
+                        "analytic_tag_ids": [(6, 0, line.analytic_tag_ids.ids)],
+                        "exclude_from_invoice_tab": True,
+                        "is_anglo_saxon_line": True,
+                    }
+                )
+        return lines_vals_list
diff --git a/osi_analytic_sales_simple/models/sale_order_line.py b/osi_analytic_sales_simple/models/sale_order_line.py
new file mode 100644
index 000000000..6b8e13b5c
--- /dev/null
+++ b/osi_analytic_sales_simple/models/sale_order_line.py
@@ -0,0 +1,44 @@
+# Copyright (C) 2019 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import api, fields, models
+
+
+class SaleOrderLine(models.Model):
+    _inherit = "sale.order.line"
+
+    analytic_account_id = fields.Many2one(
+        "account.analytic.account",
+        string="Analytic Account",
+        help="The analytic account related to a sales order Line.",
+        copy=False,
+    )
+
+    def _prepare_invoice_line(self, **optional_values):
+        res = super()._prepare_invoice_line()
+        if "analytic_account_id" not in res or res.get("analytic_account_id") is False:
+            default_analytic_account = self.env["account.analytic.default"].account_get(
+                self.product_id.id,
+                self.order_id.partner_id.id,
+                False,
+                self.order_id.user_id.id,
+                fields.Date.today(),
+            )
+            if default_analytic_account:
+                res.update(
+                    {"account_analytic_id": default_analytic_account.analytic_id.id}
+                )
+        return res
+
+    @api.onchange("product_id")
+    def _onchange_product_id(self):
+        if self.product_id and not self.order_id.analytic_account_id:
+            rec = self.env["account.analytic.default"].account_get(
+                self.product_id.id,
+                self.order_id.partner_id.id,
+                False,
+                self.env.uid,
+                fields.Date.today(),
+                company_id=self.company_id.id,
+            )
+            self.analytic_account_id = rec.analytic_id.id
diff --git a/osi_analytic_sales_simple/static/description/icon.png b/osi_analytic_sales_simple/static/description/icon.png
new file mode 100644
index 000000000..84791119f
Binary files /dev/null and b/osi_analytic_sales_simple/static/description/icon.png differ
diff --git a/osi_analytic_sales_simple/views/sale_order_view.xml b/osi_analytic_sales_simple/views/sale_order_view.xml
new file mode 100644
index 000000000..1b1127cf5
--- /dev/null
+++ b/osi_analytic_sales_simple/views/sale_order_view.xml
@@ -0,0 +1,22 @@
+<?xml version='1.0' encoding='UTF-8' ?>
+<odoo>
+
+    <!-- Copyright 2019 Open Source Integrators
+         License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
+
+    <!-- Inherit sale order form -->
+    <record id="view_order_form" model="ir.ui.view">
+        <field name="name">sale.order.form</field>
+        <field name="model">sale.order</field>
+        <field name="inherit_id" ref="sale.view_order_form" />
+        <field name="arch" type="xml">
+            <xpath
+                expr="//field[@name='order_line']/tree//field[@name='price_unit']"
+                position="before"
+            >
+                <field name="analytic_account_id" />
+            </xpath>
+        </field>
+    </record>
+
+</odoo>
diff --git a/osi_analytic_sales_simple/wizard/__init__.py b/osi_analytic_sales_simple/wizard/__init__.py
new file mode 100644
index 000000000..c49017b06
--- /dev/null
+++ b/osi_analytic_sales_simple/wizard/__init__.py
@@ -0,0 +1,3 @@
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import sale_make_invoice_advance
diff --git a/osi_analytic_sales_simple/wizard/sale_make_invoice_advance.py b/osi_analytic_sales_simple/wizard/sale_make_invoice_advance.py
new file mode 100644
index 000000000..db8e75c58
--- /dev/null
+++ b/osi_analytic_sales_simple/wizard/sale_make_invoice_advance.py
@@ -0,0 +1,15 @@
+# Copyright (C) 2019 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import models
+
+
+class SaleAdvancePaymentInv(models.TransientModel):
+    _inherit = "sale.advance.payment.inv"
+
+    def _create_invoice(self, order, so_line, amount):
+        invoice = super()._create_invoice(order, so_line, amount)
+        # Update Analytic account and Analytic Segments in Sale Order Line
+        so_line.analytic_account_id = order.analytic_account_id.id or False
+
+        return invoice
diff --git a/osi_analytic_segments/README.rst b/osi_analytic_segments/README.rst
new file mode 100644
index 000000000..6ecff0283
--- /dev/null
+++ b/osi_analytic_segments/README.rst
@@ -0,0 +1,36 @@
+.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
+   :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+   :alt: License: LGPL-3
+
+=====================
+OSI Analytic Segments
+=====================
+
+This module will have Additional segments for analytic accounts. 2 additional
+segments (dimensions) for analytical accounts. The values for selection can be
+added by the user. 
+
+Fields are added up in Invoice, Journal Item, Analytic Account.
+
+Configuration
+=============
+
+* Create Segments at Accounting > Configurations > Segments
+
+Usage
+=====
+
+* Use default segments based on configurations.
+
+Credits
+=======
+
+* Mayank Gosai <mgosai@ursainfosystems.com>
+* Bhavesh Odedra <bodedra@opensourceintegrators.com>
+* Freni Patel <fpatel@opensourceintegrators.com>
+
+Contributors
+------------
+
+* Open Source Integrators <http://www.opensourceintegrators.com>
+* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
diff --git a/osi_analytic_segments/__init__.py b/osi_analytic_segments/__init__.py
new file mode 100644
index 000000000..580de2f07
--- /dev/null
+++ b/osi_analytic_segments/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (C) 2019 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import models
diff --git a/osi_analytic_segments/__manifest__.py b/osi_analytic_segments/__manifest__.py
new file mode 100644
index 000000000..111abb84e
--- /dev/null
+++ b/osi_analytic_segments/__manifest__.py
@@ -0,0 +1,24 @@
+# Copyright (C) 2019 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+{
+    "name": "OSI Analytic Segments",
+    "version": "14.0.1.0.0",
+    "license": "LGPL-3",
+    "summary": "Additional segments for analytic accounts",
+    "author": "Open Source Integrators",
+    "maintainer": "Open Source Integrators",
+    "website": "https://github.com/ursais/osi-addons",
+    "category": "Analytic Accounting",
+    "depends": [
+        "account",
+    ],
+    "data": [
+        "security/ir.model.access.csv",
+        "views/analytic_segment.xml",
+        "views/account_analytic_line_view.xml",
+        "views/account_move_view.xml",
+    ],
+    "installable": True,
+    "maintainers": ["bodedra"],
+}
diff --git a/osi_analytic_segments/i18n/en_US.po b/osi_analytic_segments/i18n/en_US.po
new file mode 100644
index 000000000..9eb2740b8
--- /dev/null
+++ b/osi_analytic_segments/i18n/en_US.po
@@ -0,0 +1,189 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+#	* osi_analytic_segments
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 14.0+e\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2019-01-01 16:32+0000\n"
+"PO-Revision-Date: 2019-01-01 16:32+0000\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: osi_analytic_segments
+#: model:ir.model,name:osi_analytic_segments.model_account_analytic_line
+msgid "Analytic Line"
+msgstr "Analytic Line"
+
+#. module: osi_analytic_segments
+#: model:ir.actions.act_window,name:osi_analytic_segments.action_analytic_segment_one
+#: model:ir.model.fields,field_description:osi_analytic_segments.field_account_analytic_line__analytic_segment_one_id
+#: model:ir.model.fields,field_description:osi_analytic_segments.field_account_move_line__analytic_segment_one_id
+#: model:ir.ui.menu,name:osi_analytic_segments.menu_analytic_segment_one
+#: model:ir.ui.view,arch_db:osi_analytic_segments.analytic_segment_one_tree_view
+#: model:ir.ui.view,arch_db:osi_analytic_segments.analytic_segment_one_view_form
+msgid "Analytic Segment One"
+msgstr "Analytic Segment One"
+
+#. module: osi_analytic_segments
+#: model:ir.actions.act_window,name:osi_analytic_segments.action_analytic_segment_two
+#: model:ir.model.fields,field_description:osi_analytic_segments.field_account_analytic_line__analytic_segment_two_id
+#: model:ir.model.fields,field_description:osi_analytic_segments.field_account_move_line__analytic_segment_two_id
+#: model:ir.ui.menu,name:osi_analytic_segments.menu_analytic_segment_two
+#: model:ir.ui.view,arch_db:osi_analytic_segments.analytic_segment_two_tree_view
+#: model:ir.ui.view,arch_db:osi_analytic_segments.analytic_segment_two_view_form
+msgid "Analytic Segment Two"
+msgstr "Analytic Segment Two"
+
+#. module: osi_analytic_segments
+#: model:ir.model.fields,field_description:osi_analytic_segments.field_analytic_segment_one__code
+#: model:ir.model.fields,field_description:osi_analytic_segments.field_analytic_segment_two__code
+#: model:ir.ui.view,arch_db:osi_analytic_segments.analytic_segment_one_view_search
+#: model:ir.ui.view,arch_db:osi_analytic_segments.analytic_segment_two_view_search
+msgid "Code"
+msgstr "Code"
+
+#. module: osi_analytic_segments
+#: model:ir.model.fields,field_description:osi_analytic_segments.field_analytic_segment_one__create_uid
+#: model:ir.model.fields,field_description:osi_analytic_segments.field_analytic_segment_two__create_uid
+msgid "Created by"
+msgstr "Created by"
+
+#. module: osi_analytic_segments
+#: model:ir.model.fields,field_description:osi_analytic_segments.field_analytic_segment_one__create_date
+#: model:ir.model.fields,field_description:osi_analytic_segments.field_analytic_segment_two__create_date
+msgid "Created on"
+msgstr "Created on"
+
+#. module: osi_analytic_segments
+#: model:ir.model.fields,field_description:osi_analytic_segments.field_analytic_segment_one__description
+#: model:ir.model.fields,field_description:osi_analytic_segments.field_analytic_segment_two__description
+msgid "Description"
+msgstr "Description"
+
+#. module: osi_analytic_segments
+#: model:ir.ui.view,arch_db:osi_analytic_segments.analytic_segment_one_view_form
+#: model:ir.ui.view,arch_db:osi_analytic_segments.analytic_segment_two_view_form
+msgid "Description..."
+msgstr "Description..."
+
+#. module: osi_analytic_segments
+#: model:ir.model.fields,field_description:osi_analytic_segments.field_analytic_segment_one__display_name
+#: model:ir.model.fields,field_description:osi_analytic_segments.field_analytic_segment_two__display_name
+msgid "Display Name"
+msgstr "Display Name"
+
+#. module: osi_analytic_segments
+#: model:ir.model.fields,field_description:osi_analytic_segments.field_account_move_line__display_name
+#: model:ir.model.fields,field_description:osi_analytic_segments.field_account_analytic_line__display_name
+msgid "Display Name"
+msgstr "Display Name"
+
+#. module: osi_analytic_segments
+#: model:ir.model.fields,field_description:osi_analytic_segments.field_analytic_segment_one__id
+#: model:ir.model.fields,field_description:osi_analytic_segments.field_analytic_segment_two__id
+msgid "ID"
+msgstr "ID"
+
+#. module: osi_analytic_segments
+#: model:ir.model.fields,field_description:osi_analytic_segments.field_account_move_line__id
+msgid "ID"
+msgstr "ID"
+
+#. module: osi_analytic_segments
+#: model:ir.model,name:osi_analytic_segments.model_account_move_line
+msgid "Journal Item"
+msgstr "Journal Item"
+
+#. module: osi_analytic_segments
+#: model:ir.model.fields,field_description:osi_analytic_segments.field_analytic_segment_one____last_update
+#: model:ir.model.fields,field_description:osi_analytic_segments.field_analytic_segment_two____last_update
+msgid "Last Modified on"
+msgstr "Last Modified on"
+
+#. module: osi_analytic_segments
+#: model:ir.model.fields,field_description:osi_analytic_segments.field_analytic_segment_one__write_uid
+#: model:ir.model.fields,field_description:osi_analytic_segments.field_analytic_segment_two__write_uid
+msgid "Last Updated by"
+msgstr "Last Updated by"
+
+#. module: osi_analytic_segments
+#: model:ir.model.fields,field_description:osi_analytic_segments.field_analytic_segment_one__write_date
+#: model:ir.model.fields,field_description:osi_analytic_segments.field_analytic_segment_two__write_date
+msgid "Last Updated on"
+msgstr "Last Updated on"
+
+#. module: osi_analytic_segments
+#: model:ir.model.fields,field_description:osi_analytic_segments.field_analytic_segment_one__name
+#: model:ir.model.fields,field_description:osi_analytic_segments.field_analytic_segment_two__name
+#: model:ir.ui.view,arch_db:osi_analytic_segments.analytic_segment_one_view_search
+#: model:ir.ui.view,arch_db:osi_analytic_segments.analytic_segment_two_view_search
+msgid "Name"
+msgstr "Name"
+
+#. module: osi_analytic_segments
+#: model:ir.ui.view,arch_db:osi_analytic_segments.analytic_segment_one_view_search
+msgid "Search Analytic Segment One"
+msgstr "Search Analytic Segment One"
+
+#. module: osi_analytic_segments
+#: model:ir.ui.view,arch_db:osi_analytic_segments.analytic_segment_two_view_search
+msgid "Search Analytic Segment Two"
+msgstr "Search Analytic Segment Two"
+
+#. module: osi_analytic_segments
+#: model:ir.ui.menu,name:osi_analytic_segments.root_segment_menu
+msgid "Segments"
+msgstr "Segments"
+
+#. module: osi_analytic_segments
+#: model:ir.model,name:osi_analytic_segments.model_analytic_segment_one
+msgid "Analytic Segment One"
+msgstr "Analytic Segment One"
+
+#. module: osi_analytic_segments
+#: model:ir.model,name:osi_analytic_segments.model_analytic_segment_two
+msgid "Analytic Segment Two"
+msgstr "Analytic Segment Two"
+
+#. module: analytic
+#: model:ir.model,name:analytic.model_account_analytic_account
+#: model:ir.model.fields,field_description:analytic.field_account_analytic_account__name
+#: model:ir.model.fields,field_description:analytic.field_account_analytic_distribution__account_id
+#: model:ir.model.fields,field_description:analytic.field_account_analytic_line__account_id
+#: model_terms:ir.ui.view,arch_db:analytic.view_account_analytic_account_form
+#: model_terms:ir.ui.view,arch_db:analytic.view_account_analytic_account_search
+#: model_terms:ir.ui.view,arch_db:analytic.view_account_analytic_line_filter
+msgid "Analytic Account"
+msgstr "Analytic Account"
+
+#. module: analytic
+#: model:ir.actions.act_window,name:analytic.action_account_analytic_account_form
+#: model:ir.model.fields,field_description:analytic.field_account_analytic_tag__analytic_distribution_ids
+#: model_terms:ir.ui.view,arch_db:analytic.view_account_analytic_account_list
+msgid "Analytic Accounts"
+msgstr "Analytic Accounts"
+
+#. module: account
+#: model:ir.actions.act_window,name:account.action_open_partner_analytic_accounts
+#: model:ir.ui.menu,name:account.account_analytic_def_account
+#: model:ir.ui.view,arch_db:account.partner_view_button_contracts_count
+#: model:ir.ui.view,arch_db:account.res_config_settings_view_form
+msgid "Analytic Accounts"
+msgstr "Analytic Accounts"
+
+#. module: account
+#: model:ir.model.fields,field_description:account.field_account_invoice_line_account_analytic_id
+#: model:ir.model.fields,field_description:account.field_account_invoice_report_account_analytic_id
+#: model:ir.model.fields,field_description:account.field_account_move_line_analytic_account_id
+#: model:ir.model.fields,field_description:account.field_account_move_line_reconcile_writeoff_analytic_id
+#: model:ir.model.fields,field_description:account.field_account_reconcile_model_analytic_account_id
+#: model:ir.ui.view,arch_db:account.view_account_invoice_report_search
+#: model:ir.ui.view,arch_db:account.view_account_reconcile_model_form
+msgid "Analytic Account"
+msgstr "Analytic Account"
diff --git a/osi_analytic_segments/models/__init__.py b/osi_analytic_segments/models/__init__.py
new file mode 100644
index 000000000..237dc5dbd
--- /dev/null
+++ b/osi_analytic_segments/models/__init__.py
@@ -0,0 +1,9 @@
+# Copyright (C) 2019 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import (
+    account_analytic_line,
+    account_move_line,
+    analytic_segment_one,
+    analytic_segment_two,
+)
diff --git a/osi_analytic_segments/models/account_analytic_line.py b/osi_analytic_segments/models/account_analytic_line.py
new file mode 100644
index 000000000..87d0e9fc6
--- /dev/null
+++ b/osi_analytic_segments/models/account_analytic_line.py
@@ -0,0 +1,20 @@
+# Copyright (C) 2019 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import fields, models
+
+
+class AccountAnalyticLine(models.Model):
+    _inherit = "account.analytic.line"
+
+    def _get_default_segment_one(self):
+        return self.env["analytic.segment.one"].get_default_segment_one()
+
+    analytic_segment_one_id = fields.Many2one(
+        "analytic.segment.one",
+        string="Analytic Segment One",
+        default=_get_default_segment_one,
+    )
+    analytic_segment_two_id = fields.Many2one(
+        "analytic.segment.two", string="Analytic Segment Two"
+    )
diff --git a/osi_analytic_segments/models/account_move_line.py b/osi_analytic_segments/models/account_move_line.py
new file mode 100644
index 000000000..a4c8a9eb6
--- /dev/null
+++ b/osi_analytic_segments/models/account_move_line.py
@@ -0,0 +1,29 @@
+# Copyright (C) 2019 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from odoo import fields, models
+
+
+class AccountMoveLine(models.Model):
+    _inherit = "account.move.line"
+
+    def _get_default_segment_one(self):
+        return self.env["analytic.segment.one"].get_default_segment_one()
+
+    analytic_segment_one_id = fields.Many2one(
+        "analytic.segment.one",
+        string="Analytic Segment One",
+        default=_get_default_segment_one,
+    )
+    analytic_segment_two_id = fields.Many2one(
+        "analytic.segment.two", string="Analytic Segment Two"
+    )
+
+    def _prepare_analytic_line(self):
+        res = super()._prepare_analytic_line()
+        res[0].update(
+            {
+                "analytic_segment_one_id": self.analytic_segment_one_id.id,
+                "analytic_segment_two_id": self.analytic_segment_two_id.id,
+            }
+        )
+        return res
diff --git a/osi_analytic_segments/models/analytic_segment_one.py b/osi_analytic_segments/models/analytic_segment_one.py
new file mode 100644
index 000000000..c39ac8b1a
--- /dev/null
+++ b/osi_analytic_segments/models/analytic_segment_one.py
@@ -0,0 +1,35 @@
+# Copyright (C) 2019 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from odoo import api, fields, models
+from odoo.osv import expression
+
+
+class AnalyticSegmentOne(models.Model):
+    _name = "analytic.segment.one"
+    _description = "Analytic Segment One"
+    _order = "name,code"
+
+    code = fields.Char("Code")
+    name = fields.Char("Name")
+    description = fields.Text("Description")
+
+    def name_get(self):
+        result = []
+        for segment in self:
+            name = "[{}] {}".format(segment.code, segment.name)
+            result.append((segment.id, name))
+        return result
+
+    @api.model
+    def name_search(self, name, args=None, operator="ilike", limit=100):
+        args = args or []
+        domain = []
+        if name:
+            domain = ["|", ("code", "=ilike", name + "%"), ("name", operator, name)]
+            if operator in expression.NEGATIVE_TERM_OPERATORS:
+                domain = ["&", "!"] + domain[1:]
+        segments = self.search(domain + args, limit=limit)
+        return segments.name_get()
+
+    def get_default_segment_one(self):
+        return False
diff --git a/osi_analytic_segments/models/analytic_segment_two.py b/osi_analytic_segments/models/analytic_segment_two.py
new file mode 100644
index 000000000..dab9603d3
--- /dev/null
+++ b/osi_analytic_segments/models/analytic_segment_two.py
@@ -0,0 +1,32 @@
+# Copyright (C) 2019 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from odoo import api, fields, models
+from odoo.osv import expression
+
+
+class AnalyticSegmentTwo(models.Model):
+    _name = "analytic.segment.two"
+    _description = "Analytic Segment Two"
+    _order = "name,code"
+
+    code = fields.Char("Code")
+    name = fields.Char("Name")
+    description = fields.Text("Description")
+
+    def name_get(self):
+        result = []
+        for segment in self:
+            name = "[{}] {}".format(segment.code, segment.name)
+            result.append((segment.id, name))
+        return result
+
+    @api.model
+    def name_search(self, name, args=None, operator="ilike", limit=100):
+        args = args or []
+        domain = []
+        if name:
+            domain = ["|", ("code", "=ilike", name + "%"), ("name", operator, name)]
+            if operator in expression.NEGATIVE_TERM_OPERATORS:
+                domain = ["&", "!"] + domain[1:]
+        segments = self.search(domain + args, limit=limit)
+        return segments.name_get()
diff --git a/osi_analytic_segments/security/ir.model.access.csv b/osi_analytic_segments/security/ir.model.access.csv
new file mode 100644
index 000000000..743df81bc
--- /dev/null
+++ b/osi_analytic_segments/security/ir.model.access.csv
@@ -0,0 +1,7 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_analytic_segment_two_manager,analytic.segment.two.manager,model_analytic_segment_two,account.group_account_manager,1,1,1,1
+access_analytic_segment_two_user,analytic.segment.two.user,model_analytic_segment_two,account.group_account_user,1,0,0,0
+access_analytic_segment_one_manager,analytic.segment.one.manager,model_analytic_segment_one,account.group_account_manager,1,1,1,1
+access_analytic_segment_one_user,analytic.segment.one.user,model_analytic_segment_one,account.group_account_user,1,0,0,0
+access_analytic_segment_one_analytic,analytic.segment.one.analytic,model_analytic_segment_one,analytic.group_analytic_accounting,1,1,1,1
+access_analytic_segment_two_analytic,analytic.segment.two.analytic,model_analytic_segment_two,analytic.group_analytic_accounting,1,1,1,1
diff --git a/osi_analytic_segments/static/description/icon.png b/osi_analytic_segments/static/description/icon.png
new file mode 100644
index 000000000..84791119f
Binary files /dev/null and b/osi_analytic_segments/static/description/icon.png differ
diff --git a/osi_analytic_segments/views/account_analytic_line_view.xml b/osi_analytic_segments/views/account_analytic_line_view.xml
new file mode 100644
index 000000000..7869331ff
--- /dev/null
+++ b/osi_analytic_segments/views/account_analytic_line_view.xml
@@ -0,0 +1,50 @@
+<odoo>
+
+    <!-- Copyright 2019 Open Source Integrators
+         License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
+
+    <!-- Form View account analytic Line -->
+    <record id="analytic_account_line_form_segments" model="ir.ui.view">
+        <field name="name">account.analytic.line.form.segments</field>
+        <field name="model">account.analytic.line</field>
+        <field
+            name="inherit_id"
+            ref="analytic.view_account_analytic_line_form"
+        />
+        <field name="arch" type="xml">
+            <xpath expr="//field[@name='account_id']" position="after">
+                <field
+                    name="analytic_segment_one_id"
+                    groups="analytic.group_analytic_accounting"
+                />
+                <field
+                    name="analytic_segment_two_id"
+                    groups="analytic.group_analytic_accounting"
+                />
+            </xpath>
+        </field>
+    </record>
+
+    <!-- Form View account analytic Line -->
+    <record id="analytic_account_line_tree_segments" model="ir.ui.view">
+        <field name="name">account.analytic.line.tree.segments</field>
+        <field name="model">account.analytic.line</field>
+        <field
+            name="inherit_id"
+            ref="analytic.view_account_analytic_line_tree"
+        />
+        <field name="arch" type="xml">
+            <xpath expr="//field[@name='account_id']" position="after">
+                <field
+                    name="analytic_segment_one_id"
+                    groups="analytic.group_analytic_accounting"
+                />
+                <field
+                    name="analytic_segment_two_id"
+                    groups="analytic.group_analytic_accounting"
+                />
+            </xpath>
+        </field>
+    </record>
+
+</odoo>
diff --git a/osi_analytic_segments/views/account_move_view.xml b/osi_analytic_segments/views/account_move_view.xml
new file mode 100644
index 000000000..efe9b57c3
--- /dev/null
+++ b/osi_analytic_segments/views/account_move_view.xml
@@ -0,0 +1,60 @@
+<odoo>
+
+    <!-- Copyright 2019 Open Source Integrators
+         License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
+
+    <!-- Form View account move -->
+    <record id="account_move_form_segments" model="ir.ui.view">
+        <field name="name">account.move.form.segments</field>
+        <field name="model">account.move</field>
+        <field name="inherit_id" ref="account.view_move_form" />
+        <field name="arch" type="xml">
+            <xpath
+                expr="//field[@name='line_ids']/tree/field[@name='analytic_account_id']"
+                position="after"
+            >
+                <field
+                    name="analytic_segment_one_id"
+                    groups="analytic.group_analytic_accounting"
+                />
+                <field
+                    name="analytic_segment_two_id"
+                    groups="analytic.group_analytic_accounting"
+                />
+            </xpath>
+             <xpath
+                expr="//field[@name='invoice_line_ids']/tree/field[@name='analytic_account_id']"
+                position="after"
+            >
+                <field
+                    name="analytic_segment_one_id"
+                    groups="analytic.group_analytic_accounting"
+                />
+                <field
+                    name="analytic_segment_two_id"
+                    groups="analytic.group_analytic_accounting"
+                />
+            </xpath>
+        </field>
+    </record>
+
+    <!-- Tree View account move -->
+    <record id="account_move_line_tree_segments" model="ir.ui.view">
+        <field name="name">account.move.line.tree.segments</field>
+        <field name="model">account.move.line</field>
+        <field name="inherit_id" ref="account.view_move_line_tree" />
+        <field name="arch" type="xml">
+            <xpath expr="//field[@name='analytic_account_id']" position="after">
+                <field
+                    name="analytic_segment_one_id"
+                    groups="analytic.group_analytic_accounting"
+                />
+                <field
+                    name="analytic_segment_two_id"
+                    groups="analytic.group_analytic_accounting"
+                />
+            </xpath>
+        </field>
+    </record>
+
+</odoo>
diff --git a/osi_analytic_segments/views/analytic_segment.xml b/osi_analytic_segments/views/analytic_segment.xml
new file mode 100644
index 000000000..65b218a07
--- /dev/null
+++ b/osi_analytic_segments/views/analytic_segment.xml
@@ -0,0 +1,136 @@
+<odoo>
+
+    <!-- Copyright 2019 Open Source Integrators
+         License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
+
+    <!-- Segments menu in settings -->
+    <menuitem
+        name='Segments'
+        id='root_segment_menu'
+        parent='account.menu_finance_configuration'
+        groups="analytic.group_analytic_accounting"
+    />
+
+    <!-- Tree View for Analytic Segment One-->
+    <record id="analytic_segment_one_tree_view" model="ir.ui.view">
+        <field name="name">analytic.segment.one.tree</field>
+        <field name="model">analytic.segment.one</field>
+        <field name="arch" type="xml">
+            <tree string="Analytic Segment One">
+                <field name="code" />
+                <field name="name" />
+            </tree>
+        </field>
+    </record>
+
+    <!-- Form View for Analytic Segment One-->
+    <record id="analytic_segment_one_view_form" model="ir.ui.view">
+        <field name="name">analytic.segment.one.form</field>
+        <field name="model">analytic.segment.one</field>
+        <field name="arch" type="xml">
+            <form string="Analytic Segment One">
+                <sheet>
+                    <group name="segment_one">
+                        <field name="code" />
+                        <field name="name" required="1" />
+                        <field
+                            name="description"
+                            placeholder="Description..."
+                        />
+                    </group>
+                </sheet>
+            </form>
+        </field>
+    </record>
+
+    <!-- Search View for Analytic Segment One-->
+    <record id="analytic_segment_one_view_search" model="ir.ui.view">
+        <field name="name">analytic.segment.one.search</field>
+        <field name="model">analytic.segment.one</field>
+        <field name="arch" type="xml">
+            <search string="Search Analytic Segment One">
+                <field name="code" string="Code" />
+                <field name="name" string="Name" />
+            </search>
+        </field>
+    </record>
+
+    <!-- Action View for Analytic Segment One-->
+    <record id="action_analytic_segment_one" model="ir.actions.act_window">
+        <field name="name">Analytic Segment One</field>
+        <field name="type">ir.actions.act_window</field>
+        <field name="res_model">analytic.segment.one</field>
+        <field name="view_mode">tree,form</field>
+    </record>
+
+    <!-- Menu for Analytic Segment One-->
+    <menuitem
+        id="menu_analytic_segment_one"
+        action="action_analytic_segment_one"
+        parent="root_segment_menu"
+        groups="analytic.group_analytic_accounting"
+        sequence="1"
+    />
+
+    <!-- Tree View for Analytic Segment Two-->
+    <record id="analytic_segment_two_tree_view" model="ir.ui.view">
+        <field name="name">analytic.segment.two.tree</field>
+        <field name="model">analytic.segment.two</field>
+        <field name="arch" type="xml">
+            <tree string="Analytic Segment Two">
+                <field name="code" />
+                <field name="name" />
+            </tree>
+        </field>
+    </record>
+
+    <!-- Form View for Analytic Segment Two-->
+    <record id="analytic_segment_two_view_form" model="ir.ui.view">
+        <field name="name">analytic.segment.two.form</field>
+        <field name="model">analytic.segment.two</field>
+        <field name="arch" type="xml">
+            <form string="Analytic Segment Two">
+                <sheet>
+                    <group name="segment_two">
+                        <field name="code" />
+                        <field name="name" required="1" />
+                        <field
+                            name="description"
+                            placeholder="Description..."
+                        />
+                    </group>
+                </sheet>
+            </form>
+        </field>
+    </record>
+
+    <!-- Search View for Analytic Segment Two-->
+    <record id="analytic_segment_two_view_search" model="ir.ui.view">
+        <field name="name">analytic.segment.two.search</field>
+        <field name="model">analytic.segment.two</field>
+        <field name="arch" type="xml">
+            <search string="Search Analytic Segment Two">
+                <field name="code" string="Code" />
+                <field name="name" string="Name" />
+            </search>
+        </field>
+    </record>
+
+    <!-- Action View for Analytic Segment Two-->
+    <record id="action_analytic_segment_two" model="ir.actions.act_window">
+        <field name="name">Analytic Segment Two</field>
+        <field name="type">ir.actions.act_window</field>
+        <field name="res_model">analytic.segment.two</field>
+        <field name="view_mode">tree,form</field>
+    </record>
+
+    <!-- Menu for Analytic Segment Two-->
+    <menuitem
+        id="menu_analytic_segment_two"
+        action="action_analytic_segment_two"
+        parent="root_segment_menu"
+        groups="analytic.group_analytic_accounting"
+        sequence="2"
+    />
+
+</odoo>
diff --git a/osi_analytic_segments_defaults/README.rst b/osi_analytic_segments_defaults/README.rst
new file mode 100644
index 000000000..62ef66c9d
--- /dev/null
+++ b/osi_analytic_segments_defaults/README.rst
@@ -0,0 +1,30 @@
+.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
+   :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+   :alt: License: LGPL-3
+
+==============================
+OSI Analytic Segments Defaults
+==============================
+
+This module adds 2 additional analytic segments to Analytic Defaults related models and views
+
+Configuration
+=============
+
+* Create Segments at Accounting/Configurations/Segments
+
+Usage
+=====
+
+
+Credits
+=======
+
+* Open Source Integrators <http://www.opensourceintegrators.com>
+
+Contributors
+------------
+
+* Mayank Gosai <mgosai@ursainfosystems.com>
+* Bhavesh Odedra <bodedra@opensourceintegrators.com>
+* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
diff --git a/osi_analytic_segments_defaults/__init__.py b/osi_analytic_segments_defaults/__init__.py
new file mode 100644
index 000000000..7d768b54b
--- /dev/null
+++ b/osi_analytic_segments_defaults/__init__.py
@@ -0,0 +1,3 @@
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import models
diff --git a/osi_analytic_segments_defaults/__manifest__.py b/osi_analytic_segments_defaults/__manifest__.py
new file mode 100644
index 000000000..6bdf06d26
--- /dev/null
+++ b/osi_analytic_segments_defaults/__manifest__.py
@@ -0,0 +1,23 @@
+# Copyright (C) 2019 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+{
+    "name": "OSI Analytic Segments Defaults",
+    "version": "14.0.1.0.0",
+    "license": "LGPL-3",
+    "summary": "Additional analytic segments for Analytic Defaults",
+    "author": "Open Source Integrators",
+    "maintainers": ["Open Source Integrators"],
+    "website": "https://github.com/ursais/osi-addons",
+    "category": "Analytic Accounting",
+    "depends": [
+        "sale",
+        "purchase",
+        "account",
+        "osi_analytic_segments",
+    ],
+    "data": [
+        "views/account_analytic_default_view.xml",
+    ],
+    "installable": True,
+}
diff --git a/osi_analytic_segments_defaults/i18n/en_US.po b/osi_analytic_segments_defaults/i18n/en_US.po
new file mode 100644
index 000000000..ac15634b8
--- /dev/null
+++ b/osi_analytic_segments_defaults/i18n/en_US.po
@@ -0,0 +1,37 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+#	* osi_analytic_segments_defaults
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 12.0+e\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2019-01-01 16:32+0000\n"
+"PO-Revision-Date: 2019-01-01 16:32+0000\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: osi_analytic_segments_defaults
+#: model:ir.model,name:osi_analytic_segments_defaults.model_account_analytic_default
+msgid "Analytic Distribution"
+msgstr "Analytic Distribution"
+
+#. module: osi_analytic_segments_defaults
+#: model:ir.model.fields,field_description:osi_analytic_segments_defaults.field_account_analytic_default_analytic_segment_one
+msgid "Analytic Segment One"
+msgstr "Analytic Segment One"
+
+#. module: osi_analytic_segments_defaults
+#: model:ir.model.fields,field_description:osi_analytic_segments_defaults.field_account_analytic_default_analytic_segment_two
+msgid "Analytic Segment Two"
+msgstr "Analytic Segment Two"
+
+#. module: account
+#: model:ir.model.fields,field_description:account_analytic_default.field_account_analytic_default_analytic_id
+#: model:ir.ui.view,arch_db:account_analytic_default.view_account_analytic_default_form_search
+msgid "Analytic Account"
+msgstr "Analytic Account"
diff --git a/osi_analytic_segments_defaults/models/__init__.py b/osi_analytic_segments_defaults/models/__init__.py
new file mode 100644
index 000000000..f1d780b21
--- /dev/null
+++ b/osi_analytic_segments_defaults/models/__init__.py
@@ -0,0 +1,7 @@
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from . import (
+    account_analytic_default,
+    account_move_line,
+    purchase_order,
+    sale_order_line,
+)
diff --git a/osi_analytic_segments_defaults/models/account_analytic_default.py b/osi_analytic_segments_defaults/models/account_analytic_default.py
new file mode 100644
index 000000000..6e8ac979e
--- /dev/null
+++ b/osi_analytic_segments_defaults/models/account_analytic_default.py
@@ -0,0 +1,20 @@
+# Copyright (C) 2019 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from odoo import fields, models
+
+
+class AccountAnalyticDefault(models.Model):
+    _inherit = "account.analytic.default"
+
+    def _get_default_segment_one(self):
+        return self.env["analytic.segment.one"].get_default_segment_one()
+
+    analytic_segment_one_id = fields.Many2one(
+        "analytic.segment.one",
+        string="Analytic Segment One",
+        default=_get_default_segment_one,
+        copy=False,
+    )
+    analytic_segment_two_id = fields.Many2one(
+        "analytic.segment.two", string="Analytic Segment Two", copy=False
+    )
diff --git a/osi_analytic_segments_defaults/models/account_move_line.py b/osi_analytic_segments_defaults/models/account_move_line.py
new file mode 100644
index 000000000..cbb677219
--- /dev/null
+++ b/osi_analytic_segments_defaults/models/account_move_line.py
@@ -0,0 +1,24 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from odoo import api, fields, models
+
+
+class AccountMoveLine(models.Model):
+    _inherit = "account.move.line"
+
+    @api.onchange("product_id")
+    def _onchange_product_id(self):
+        res = super(AccountMoveLine, self)._onchange_product_id()
+        rec = self.env["account.analytic.default"].account_get(
+            self.product_id.id,
+            self.partner_id.id,
+            self.account_id.id,
+            self.env.uid,
+            fields.Date.today(),
+            company_id=self.company_id.id,
+        )
+        if rec and not self.analytic_segment_one_id:
+            self.analytic_segment_one_id = rec.analytic_segment_one_id.id
+        if rec and not self.analytic_segment_two_id:
+            self.analytic_segment_two_id = rec.analytic_segment_two_id.id
+        return res
diff --git a/osi_analytic_segments_defaults/models/purchase_order.py b/osi_analytic_segments_defaults/models/purchase_order.py
new file mode 100644
index 000000000..4c7c556d5
--- /dev/null
+++ b/osi_analytic_segments_defaults/models/purchase_order.py
@@ -0,0 +1,23 @@
+# Copyright (C) 2019 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import api, fields, models
+
+
+class PurchaseOrderLine(models.Model):
+    _inherit = "purchase.order.line"
+
+    @api.onchange("product_id")
+    def _onchange_product_id(self):
+        if self.product_id:
+            rec = self.env["account.analytic.default"].account_get(
+                self.product_id.id,
+                self.order_id.partner_id.id,
+                False,
+                self.env.uid,
+                fields.Date.today(),
+                company_id=self.company_id.id,
+            )
+            self.account_analytic_id = rec.analytic_id.id
+            self.analytic_segment_one_id = rec.analytic_segment_one_id.id
+            self.analytic_segment_two_id = rec.analytic_segment_two_id.id
diff --git a/osi_analytic_segments_defaults/models/sale_order_line.py b/osi_analytic_segments_defaults/models/sale_order_line.py
new file mode 100644
index 000000000..4a4b5e249
--- /dev/null
+++ b/osi_analytic_segments_defaults/models/sale_order_line.py
@@ -0,0 +1,51 @@
+# Copyright (C) 2019 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import api, fields, models
+
+
+class SaleOrderLine(models.Model):
+    _inherit = "sale.order.line"
+
+    analytic_account_id = fields.Many2one(
+        "account.analytic.account",
+        string="Analytic Account",
+        help="The analytic account related to a sales order Line.",
+        copy=False,
+    )
+
+    def _prepare_invoice_line(self, qty):
+        res = super(SaleOrderLine, self)._prepare_invoice_line(qty)
+        default_analytic_account = self.env["account.analytic.default"].account_get(
+            product_id=self.product_id.id,
+            partner_id=self.order_id.partner_id.id,
+            account_id=self.account_id.id,
+            user_id=self.order_id.user_id.id,
+            date=fields.Date.today(),
+            company_id=self.company_id.id,
+        )
+        if default_analytic_account:
+            d_id = default_analytic_account
+            res.update(
+                {
+                    "account_analytic_id": d_id.id,
+                    "analytic_segment_one_id": d_id.analytic_segment_one_id.id,
+                    "analytic_segment_two_id": d_id.analytic_segment_two_id.id,
+                }
+            )
+        return res
+
+    @api.onchange("product_id")
+    def _onchange_product_id(self):
+        if self.product_id:
+            rec = self.env["account.analytic.default"].account_get(
+                product_id=self.product_id.id,
+                partner_id=self.order_id.partner_id.id,
+                account_id=self.account_id.id or False,
+                user_id=self.env.uid,
+                date=fields.Date.today(),
+                company_id=self.company_id.id,
+            )
+            self.analytic_account_id = rec.analytic_id.id
+            self.analytic_segment_one_id = rec.analytic_segment_one_id.id
+            self.analytic_segment_two_id = rec.analytic_segment_two_id.id
diff --git a/osi_analytic_segments_defaults/static/description/icon.png b/osi_analytic_segments_defaults/static/description/icon.png
new file mode 100644
index 000000000..84791119f
Binary files /dev/null and b/osi_analytic_segments_defaults/static/description/icon.png differ
diff --git a/osi_analytic_segments_defaults/views/account_analytic_default_view.xml b/osi_analytic_segments_defaults/views/account_analytic_default_view.xml
new file mode 100644
index 000000000..5c083d9ac
--- /dev/null
+++ b/osi_analytic_segments_defaults/views/account_analytic_default_view.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" ?>
+<odoo>
+
+    <!-- Copyright 2019 Open Source Integrators
+         License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
+
+    <record id="view_account_analytic_default_tree_segments" model="ir.ui.view">
+        <field name="name">account.analytic.default.tree.segments</field>
+        <field name="model">account.analytic.default</field>
+        <field
+            name="inherit_id"
+            ref="account.view_account_analytic_default_tree"
+        />
+        <field name="arch" type="xml">
+            <xpath expr="//field[@name='analytic_id']" position="after">
+                <field
+                    name="analytic_segment_one_id"
+                    groups="analytic.group_analytic_accounting"
+                />
+                <field
+                    name="analytic_segment_two_id"
+                    groups="analytic.group_analytic_accounting"
+                />
+            </xpath>
+        </field>
+    </record>
+
+    <record id="view_account_analytic_default_form_segments" model="ir.ui.view">
+        <field name="name">account.analytic.default.form.segments</field>
+        <field name="model">account.analytic.default</field>
+        <field
+            name="inherit_id"
+            ref="account.view_account_analytic_default_form"
+        />
+        <field name="arch" type="xml">
+            <xpath expr="//field[@name='analytic_id']" position="attributes">
+                <attribute name='required'>0</attribute>
+            </xpath>
+            <xpath expr="//field[@name='analytic_id']" position="after">
+                <field
+                    name="analytic_segment_one_id"
+                    groups="analytic.group_analytic_accounting"
+                />
+                <field
+                    name="analytic_segment_two_id"
+                    groups="analytic.group_analytic_accounting"
+                />
+            </xpath>
+        </field>
+    </record>
+
+</odoo>
diff --git a/osi_analytic_segments_expenses/README.rst b/osi_analytic_segments_expenses/README.rst
new file mode 100644
index 000000000..a4c900384
--- /dev/null
+++ b/osi_analytic_segments_expenses/README.rst
@@ -0,0 +1,30 @@
+.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
+   :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+   :alt: License: LGPL-3
+
+==============================
+OSI Analytic Segments Expenses
+==============================
+
+This module adds 2 additional analytic segments to Budget related models and views
+
+Configuration
+=============
+
+* Create Segments at Accounting/Configurations/Segments
+
+Usage
+=====
+
+
+Credits
+=======
+
+* Open Source Integrators <http://www.opensourceintegrators.com>
+
+Contributors
+------------
+
+* Mayank Gosai <mgosai@ursainfosystems.com>
+* Bhavesh Odedra <bodedra@opensourceintegrators.com>
+* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
diff --git a/osi_analytic_segments_expenses/__init__.py b/osi_analytic_segments_expenses/__init__.py
new file mode 100644
index 000000000..7d768b54b
--- /dev/null
+++ b/osi_analytic_segments_expenses/__init__.py
@@ -0,0 +1,3 @@
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import models
diff --git a/osi_analytic_segments_expenses/__manifest__.py b/osi_analytic_segments_expenses/__manifest__.py
new file mode 100644
index 000000000..a1952ec47
--- /dev/null
+++ b/osi_analytic_segments_expenses/__manifest__.py
@@ -0,0 +1,22 @@
+# Copyright (C) 2019 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+{
+    "name": "OSI Analytic Segments Expenses",
+    "version": "14.0.1.0.0",
+    "license": "LGPL-3",
+    "summary": "Additional segments for analytic accounts for Expenses.",
+    "author": "Open Source Integrators",
+    "maintainer": "Open Source Integrators",
+    "website": "https://github.com/ursais/osi-addons",
+    "category": "Analytic Accounting",
+    "depends": [
+        "osi_analytic_segments",
+        "hr_expense",
+    ],
+    "data": [
+        "views/hr_expense_views.xml",
+    ],
+    "installable": True,
+    "maintainers": ["bodedra"],
+}
diff --git a/osi_analytic_segments_expenses/i18n/en_US.po b/osi_analytic_segments_expenses/i18n/en_US.po
new file mode 100644
index 000000000..545f7fd3d
--- /dev/null
+++ b/osi_analytic_segments_expenses/i18n/en_US.po
@@ -0,0 +1,44 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+#	* osi_analytic_segments_expenses
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 12.0+e\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2019-01-01 16:32+0000\n"
+"PO-Revision-Date: 2019-01-01 16:32+0000\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: osi_analytic_segments_expenses
+#: model:ir.model.fields,field_description:osi_analytic_segments_expenses.field_hr_expense_analytic_segment_one
+#: model:ir.model.fields,field_description:osi_analytic_segments_expenses.field_hr_expense_sheet_analytic_segment_one
+#: model:ir.model.fields,field_description:osi_analytic_segments_expenses.field_hr_expense_sheet_analytic_segment_two
+msgid "Analytic Segment One"
+msgstr "Analytic Segment One"
+
+#. module: osi_analytic_segments_expenses
+#: model:ir.model.fields,field_description:osi_analytic_segments_expenses.field_hr_expense_analytic_segment_two
+msgid "Analytic Segment Two"
+msgstr "Analytic Segment Two"
+
+#. module: osi_analytic_segments_expenses
+#: model:ir.model,name:osi_analytic_segments_expenses.model_hr_expense
+msgid "Expense"
+msgstr "Expense"
+
+#. module: osi_analytic_segments_expenses
+#: model:ir.model,name:osi_analytic_segments_expenses.model_hr_expense_sheet
+msgid "Expense Report"
+msgstr "Expense Report"
+
+#. module: hr_expense
+#: model:ir.model.fields,field_description:hr_expense.field_hr_expense_analytic_account_id
+#: model:ir.ui.view,arch_db:hr_expense.view_hr_expense_filter
+msgid "Analytic Account"
+msgstr "Analytic Account"
diff --git a/osi_analytic_segments_expenses/models/__init__.py b/osi_analytic_segments_expenses/models/__init__.py
new file mode 100644
index 000000000..93279ce03
--- /dev/null
+++ b/osi_analytic_segments_expenses/models/__init__.py
@@ -0,0 +1,3 @@
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import hr_expense
diff --git a/osi_analytic_segments_expenses/models/hr_expense.py b/osi_analytic_segments_expenses/models/hr_expense.py
new file mode 100644
index 000000000..456b6dfe0
--- /dev/null
+++ b/osi_analytic_segments_expenses/models/hr_expense.py
@@ -0,0 +1,31 @@
+# Copyright (C) 2019 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from odoo import fields, models
+
+
+class HrExpense(models.Model):
+    _inherit = "hr.expense"
+
+    def _get_default_segment_one(self):
+        return self.env["analytic.segment.one"].get_default_segment_one()
+
+    analytic_segment_one_id = fields.Many2one(
+        "analytic.segment.one",
+        string="Analytic Segment One",
+        default=_get_default_segment_one,
+        copy=False,
+    )
+    analytic_segment_two_id = fields.Many2one(
+        "analytic.segment.two", string="Analytic Segment Two", copy=False
+    )
+
+    def _get_account_move_line_values(self):
+        res = super(HrExpense, self)._get_account_move_line_values()
+        for expense in self:
+            res[expense.id][0].update(
+                {
+                    "analytic_segment_one_id": expense.analytic_segment_one_id.id,
+                    "analytic_segment_two_id": expense.analytic_segment_two_id.id,
+                }
+            )
+        return res
diff --git a/osi_analytic_segments_expenses/static/description/icon.png b/osi_analytic_segments_expenses/static/description/icon.png
new file mode 100644
index 000000000..84791119f
Binary files /dev/null and b/osi_analytic_segments_expenses/static/description/icon.png differ
diff --git a/osi_analytic_segments_expenses/views/hr_expense_views.xml b/osi_analytic_segments_expenses/views/hr_expense_views.xml
new file mode 100644
index 000000000..ed2c883ae
--- /dev/null
+++ b/osi_analytic_segments_expenses/views/hr_expense_views.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<odoo>
+
+    <!-- Copyright 2019 Open Source Integrators
+         License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
+
+    <record id="view_expenses_tree_segments" model="ir.ui.view">
+        <field name="name">hr.expense.tree.segments</field>
+        <field name="model">hr.expense</field>
+        <field name="type">tree</field>
+        <field name="inherit_id" ref="hr_expense.view_expenses_tree" />
+        <field name="arch" type="xml">
+            <xpath expr="//field[@name='analytic_account_id']" position='after'>
+                <field name="analytic_segment_one_id" />
+                <field name="analytic_segment_two_id" />
+            </xpath>
+        </field>
+    </record>
+
+    <record id="view_expenses_form_segments" model="ir.ui.view">
+        <field name="name">hr.expense.form.segments</field>
+        <field name="model">hr.expense</field>
+        <field name="type">form</field>
+        <field name="inherit_id" ref="hr_expense.hr_expense_view_form" />
+        <field name="arch" type="xml">
+            <xpath expr="//field[@name='analytic_account_id']" position='after'>
+                <field name="analytic_segment_one_id" />
+                <field name="analytic_segment_two_id" />
+            </xpath>
+        </field>
+    </record>
+
+    <record id="view_hr_expense_sheet_form_segments" model="ir.ui.view">
+        <field name="name">hr.expense.sheet.form</field>
+        <field name="model">hr.expense.sheet</field>
+        <field name="inherit_id" ref="hr_expense.view_hr_expense_sheet_form" />
+        <field name="arch" type="xml">
+            <xpath
+                expr="//tree/field[@name='analytic_account_id']"
+                position='after'
+            >
+                <field name="analytic_segment_one_id" />
+                <field name="analytic_segment_two_id" />
+            </xpath>
+        </field>
+    </record>
+
+</odoo>
diff --git a/osi_analytic_segments_multi_company/README.rst b/osi_analytic_segments_multi_company/README.rst
new file mode 100644
index 000000000..4150081a4
--- /dev/null
+++ b/osi_analytic_segments_multi_company/README.rst
@@ -0,0 +1,36 @@
+.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
+   :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+   :alt: License: LGPL-3
+
+===================================
+OSI Analytic Segments Multi Company
+===================================
+
+This module will carry the Analytic Segments functionality 
+over to the multi-company workflows. 
+
+Distribtuions will now copy Segments One and Two to their corresponding 
+Journal Entries.
+
+Configuration
+=============
+
+* Create Segments at Accounting > Configurations > Segments
+* Configure Multi-Company Accounting by Company
+
+Usage
+=====
+
+* Use default segments based on configurations.
+* Add distributions
+* Verify segments have been copied over accordingly
+
+Credits
+=======
+
+* Steven Campbell <scampbell@opensourceintegrators.com>
+
+Contributors
+------------
+
+* Open Source Integrators <http://www.opensourceintegrators.com>
diff --git a/osi_analytic_segments_multi_company/__init__.py b/osi_analytic_segments_multi_company/__init__.py
new file mode 100644
index 000000000..ff8dc3cb9
--- /dev/null
+++ b/osi_analytic_segments_multi_company/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import models
diff --git a/osi_analytic_segments_multi_company/__manifest__.py b/osi_analytic_segments_multi_company/__manifest__.py
new file mode 100644
index 000000000..d6536885b
--- /dev/null
+++ b/osi_analytic_segments_multi_company/__manifest__.py
@@ -0,0 +1,17 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+{
+    "name": "OSI Analytic Segments Multi Company",
+    "version": "14.0.1.0.0",
+    "license": "LGPL-3",
+    "summary": "Additional segments for analytic accounts",
+    "author": "Open Source Integrators",
+    "maintainer": "Open Source Integrators",
+    "website": "https://github.com/ursais/osi-addons",
+    "category": "Analytic Accounting",
+    "depends": ["osi_analytic_segments", "account_bill_line_distribution"],
+    "maintainers": ["Open Source Integrators"],
+    "data": [],
+    "installable": True,
+}
diff --git a/osi_analytic_segments_multi_company/models/__init__.py b/osi_analytic_segments_multi_company/models/__init__.py
new file mode 100644
index 000000000..74ab96c23
--- /dev/null
+++ b/osi_analytic_segments_multi_company/models/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import account_move
diff --git a/osi_analytic_segments_multi_company/models/account_move.py b/osi_analytic_segments_multi_company/models/account_move.py
new file mode 100644
index 000000000..c68dd0b08
--- /dev/null
+++ b/osi_analytic_segments_multi_company/models/account_move.py
@@ -0,0 +1,31 @@
+# Copyright (C) 2021 Open Source Integrators
+# Copyright (C) 2021 Serpent Consulting Services
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+from odoo import models
+
+
+class AccountMove(models.Model):
+    _inherit = "account.move"
+
+    # Mutli-Company (account_bill_line_distribution)
+
+    def get_from_lines(
+        self, from_lines, invoice_line_id, invoice_id, amount, distribution, is_invoice
+    ):
+        super().get_from_lines(
+            from_lines, invoice_line_id, invoice_id, amount, distribution, is_invoice
+        )
+        for line_id in from_lines:
+            line_id[2][
+                "analytic_segment_one_id"
+            ] = invoice_line_id.analytic_segment_one_id.id
+            line_id[2][
+                "analytic_segment_two_id"
+            ] = invoice_line_id.analytic_segment_two_id.id
+
+    # Mutli-Company (account_bill_line_distribution)
+    def get_to_lines(self, to_lines, line, company, invoice_id, is_invoice):
+        super().get_to_lines(to_lines, line, company, invoice_id, is_invoice)
+        for line_id in to_lines:
+            line_id[2]["analytic_segment_one_id"] = line.get("analytic_segment_one_id")
+            line_id[2]["analytic_segment_two_id"] = line.get("analytic_segment_two_id")
diff --git a/osi_analytic_segments_multi_company/static/description/icon.png b/osi_analytic_segments_multi_company/static/description/icon.png
new file mode 100644
index 000000000..84791119f
Binary files /dev/null and b/osi_analytic_segments_multi_company/static/description/icon.png differ
diff --git a/osi_analytic_segments_purchase/README.rst b/osi_analytic_segments_purchase/README.rst
new file mode 100644
index 000000000..052761a8b
--- /dev/null
+++ b/osi_analytic_segments_purchase/README.rst
@@ -0,0 +1,26 @@
+.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
+    :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+    :alt: License: LGPL-3
+
+==============================
+OSI Analytic Segments Purchase
+==============================
+
+This module adds 2 additional analytic segments to Purchase related models and views
+
+Configuration
+=============
+
+* Create Segments at Accounting/Configurations/Segments
+
+Credits
+=======
+
+* Open Source Integrators <http://www.opensourceintegrators.com>
+
+Contributors
+------------
+
+* Mayank Gosai <mgosai@ursainfosystems.com>
+* Bhavesh Odedra <bodedra@opensourceintegrators.com>
+* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
diff --git a/osi_analytic_segments_purchase/__init__.py b/osi_analytic_segments_purchase/__init__.py
new file mode 100644
index 000000000..7d768b54b
--- /dev/null
+++ b/osi_analytic_segments_purchase/__init__.py
@@ -0,0 +1,3 @@
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import models
diff --git a/osi_analytic_segments_purchase/__manifest__.py b/osi_analytic_segments_purchase/__manifest__.py
new file mode 100644
index 000000000..d7346f96d
--- /dev/null
+++ b/osi_analytic_segments_purchase/__manifest__.py
@@ -0,0 +1,22 @@
+# Copyright (C) 2019 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+{
+    "name": "OSI Analytic Segments Purchase",
+    "version": "14.0.1.0.0",
+    "license": "LGPL-3",
+    "summary": "Additional analytic segments in Purchase",
+    "author": "Open Source Integrators",
+    "maintainer": "Open Source Integrators",
+    "website": "https://github.com/ursais/osi-addons",
+    "category": "Analytic Accounting",
+    "depends": [
+        "purchase",
+        "osi_analytic_segments",
+    ],
+    "data": [
+        "views/purchase_order_view.xml",
+    ],
+    "installable": True,
+    "maintainers": ["bodedra"],
+}
diff --git a/osi_analytic_segments_purchase/i18n/en_US.po b/osi_analytic_segments_purchase/i18n/en_US.po
new file mode 100644
index 000000000..8c3d0f74d
--- /dev/null
+++ b/osi_analytic_segments_purchase/i18n/en_US.po
@@ -0,0 +1,44 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+#	* osi_analytic_segments_purchase
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 12.0+e\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2019-01-01 16:32+0000\n"
+"PO-Revision-Date: 2019-01-01 16:32+0000\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: osi_analytic_segments_purchase
+#: model:ir.ui.view,arch_db:osi_analytic_segments_purchase.purchase_order_line_search_segments
+msgid "Analytic Account"
+msgstr "Analytic Account"
+
+#. module: osi_analytic_segments_purchase
+#: model:ir.model.fields,field_description:osi_analytic_segments_purchase.field_purchase_order_line_analytic_segment_one
+#: model:ir.ui.view,arch_db:osi_analytic_segments_purchase.purchase_order_line_search_segments
+msgid "Analytic Segment One"
+msgstr "Analytic Segment One"
+
+#. module: osi_analytic_segments_purchase
+#: model:ir.model.fields,field_description:osi_analytic_segments_purchase.field_purchase_order_line_analytic_segment_two
+#: model:ir.ui.view,arch_db:osi_analytic_segments_purchase.purchase_order_line_search_segments
+msgid "Analytic Segment Two"
+msgstr "Analytic Segment Two"
+
+#. module: osi_analytic_segments_purchase
+#: model:ir.model,name:osi_analytic_segments_purchase.model_purchase_order_line
+msgid "Purchase Order Line"
+msgstr "Purchase Order Line"
+
+#. module: purchase
+#: model:ir.model.fields,field_description:purchase.field_purchase_order_line_account_analytic_id
+#: model:ir.model.fields,field_description:purchase.field_purchase_report_account_analytic_id
+msgid "Analytic Account"
+msgstr "Analytic Account"
diff --git a/osi_analytic_segments_purchase/models/__init__.py b/osi_analytic_segments_purchase/models/__init__.py
new file mode 100644
index 000000000..23aaefb04
--- /dev/null
+++ b/osi_analytic_segments_purchase/models/__init__.py
@@ -0,0 +1,4 @@
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from . import (
+    purchase_order_line,
+)
diff --git a/osi_analytic_segments_purchase/models/purchase_order_line.py b/osi_analytic_segments_purchase/models/purchase_order_line.py
new file mode 100644
index 000000000..affa17268
--- /dev/null
+++ b/osi_analytic_segments_purchase/models/purchase_order_line.py
@@ -0,0 +1,30 @@
+# Copyright (C) 2019 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from odoo import fields, models
+
+
+class PurchaseOrderLine(models.Model):
+    _inherit = "purchase.order.line"
+
+    def _get_default_segment_one(self):
+        return self.env["analytic.segment.one"].get_default_segment_one()
+
+    analytic_segment_one_id = fields.Many2one(
+        "analytic.segment.one",
+        string="Analytic Segment One",
+        default=_get_default_segment_one,
+        copy=False,
+    )
+    analytic_segment_two_id = fields.Many2one(
+        "analytic.segment.two", string="Analytic Segment Two", copy=False
+    )
+
+    def _prepare_account_move_line(self, move=False):
+        res = super()._prepare_account_move_line(move)
+        res.update(
+            {
+                "analytic_segment_one_id": self.analytic_segment_one_id.id,
+                "analytic_segment_two_id": self.analytic_segment_two_id.id,
+            }
+        )
+        return res
diff --git a/osi_analytic_segments_purchase/static/description/icon.png b/osi_analytic_segments_purchase/static/description/icon.png
new file mode 100644
index 000000000..84791119f
Binary files /dev/null and b/osi_analytic_segments_purchase/static/description/icon.png differ
diff --git a/osi_analytic_segments_purchase/views/purchase_order_view.xml b/osi_analytic_segments_purchase/views/purchase_order_view.xml
new file mode 100644
index 000000000..95605191a
--- /dev/null
+++ b/osi_analytic_segments_purchase/views/purchase_order_view.xml
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<odoo>
+
+    <!-- Copyright 2021 Open Source Integrators
+         License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
+
+    <!-- new field added to purchase order form -->
+    <record id="analytic_purchase_order_form" model="ir.ui.view">
+        <field name="name">analytic.purchase.order.form</field>
+        <field name="model">purchase.order</field>
+        <field name="type">form</field>
+        <field name="inherit_id" ref="purchase.purchase_order_form" />
+        <field name="arch" type="xml">
+            <xpath
+                expr="//field[@name='order_line']/tree/field[@name='account_analytic_id']"
+                position="after"
+            >
+                <field name="analytic_segment_one_id" />
+                <field name="analytic_segment_two_id" />
+            </xpath>
+        </field>
+    </record>
+
+    <record id="purchase_order_line_tree_segments" model="ir.ui.view">
+        <field name="name">purchase.order.line.tree.segments</field>
+        <field name="model">purchase.order.line</field>
+        <field name="inherit_id" ref="purchase.purchase_order_line_tree" />
+        <field name="arch" type="xml">
+            <field name='order_id' position="after">
+                <field name="state" />
+            </field>
+            <field name='product_id' position="after">
+                <field name="analytic_segment_one_id" />
+                <field name="analytic_segment_two_id" />
+            </field>
+        </field>
+    </record>
+
+    <record id="purchase_order_line_form_segments" model="ir.ui.view">
+        <field name="name">purchase.order.line.form.segments</field>
+        <field name="model">purchase.order.line</field>
+        <field name="inherit_id" ref="purchase.purchase_order_line_form2" />
+        <field name="arch" type="xml">
+            <xpath expr="//field[@name='date_order']" position="before">
+                <field name="analytic_segment_one_id" />
+                <field name="analytic_segment_two_id" />
+                <field name="state" />
+            </xpath>
+        </field>
+    </record>
+
+    <record id="purchase_order_line_search_segments" model="ir.ui.view">
+        <field name="name">purchase.order.line.search.segments</field>
+        <field name="model">purchase.order.line</field>
+        <field name="inherit_id" ref="purchase.purchase_order_line_search" />
+        <field name="type">search</field>
+        <field name="arch" type="xml">
+            <xpath expr="//group/filter[4]" position="after">
+                <filter
+                    name="groupby_analytic_account"
+                    string="Analytic Account"
+                    domain="[]"
+                    context="{'group_by' : 'account_analytic_id'}"
+                />
+                <filter
+                    name="groupby_analytic_seg_1"
+                    string="Analytic Segment One"
+                    domain="[]"
+                    context="{'group_by' : 'analytic_segment_one_id'}"
+                />
+                <filter
+                    name="groupby_analytic_seg_2"
+                    string="Analytic Segment Two"
+                    domain="[]"
+                    context="{'group_by' : 'analytic_segment_two_id'}"
+                />
+            </xpath>
+        </field>
+    </record>
+
+    <record id="action_purchase_order_lines" model="ir.actions.act_window">
+        <field name="name">Purchase Order Lines</field>
+        <field name="res_model">purchase.order.line</field>
+        <field name="view_id" ref="purchase.purchase_order_line_tree" />
+        <field name='view_mode'>tree,form</field>
+        <field name="help" type="html">
+            <p class="oe_view_nocontent_create">
+                Click to create a Purchase Order Line
+            </p>
+        </field>
+    </record>
+
+    <menuitem
+        id='purchase_order_lines_menu'
+        action='action_purchase_order_lines'
+        parent='purchase.menu_procurement_management'
+        sequence='10'
+        groups='purchase.group_purchase_user'
+    />
+
+</odoo>
diff --git a/osi_analytic_segments_purchase_subscription/README.rst b/osi_analytic_segments_purchase_subscription/README.rst
new file mode 100644
index 000000000..f8a265116
--- /dev/null
+++ b/osi_analytic_segments_purchase_subscription/README.rst
@@ -0,0 +1,84 @@
+===========================================
+Analytic Segments in Purchase Subscriptions
+===========================================
+
+.. |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-ursais%2Fosi--addons-lightgray.png?logo=github
+    :target: https://github.com/ursais/osi-addons/
+    :alt: ursais/osi-addons
+
+|badge1| |badge2| |badge3|
+
+This module adds 2 analytic segments to purchase subscriptions and copy them to
+the vendor bills.
+
+**Table of contents**
+
+.. contents::
+   :local:
+
+Configuration
+=============
+
+* Go to Accounting > Configurations > Segments
+* Create segments
+
+Usage
+=====
+
+* Go to Purchase Subscription
+* Select or create a purchase subscription and set the analytic segments
+* Generate a vendor bill from the subscription
+
+Bug Tracker
+===========
+
+Bugs are tracked on `GitHub Issues <https://github.com/ursais/osi-addons/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 <https://github.com/ursais/osi-addons/issues/new?body=module:%20osi_analytic_segments_purchase_subscription%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
+
+Credits
+=======
+
+Contributors
+------------
+
+* `Open Source Integrators <https://www.opensourceintegrators.com>`_:
+
+  * Mayank Gosai <mgosai@ursainfosystems.com>
+  * Bhavesh Odedra <bodedra@opensourceintegrators.com>
+  * Maxime Chambreuil <mchambreuil@opensourceintegrators.com>
+
+* `Serpent Consulting Services <https://www.serpentcs.com>`_:
+
+  * Murtuza Saleh <murtuzasaleh@serpentcs.com>
+
+Maintainers
+-----------
+
+This module is maintained by Open Source Integrators.
+
+.. image:: https://github.com/ursais.png
+   :target: https://www.opensourceintegrators.com
+   :alt: Open Source Integrators
+
+Open Source Integrators™ (OSI) provides customers a unique combination of
+open source business process consulting and implementations.
+
+.. |maintainer-mgosai| image:: https://github.com/mgosai.png?size=40px
+    :target: https://github.com/mgosai
+    :alt: Mayank Gosai
+
+Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
+
+|maintainer-mgosai|
+
+This module is part of the `OSI Odoo Addons <https://github.com/ursais/osi-addons/tree/12.0/osi_analytic_segments_purchase_subscription>`_ project on GitHub.
+
+You are welcome to contribute. To learn how, please visit https://odoo-community.org/page/Contribute.
diff --git a/osi_analytic_segments_purchase_subscription/__init__.py b/osi_analytic_segments_purchase_subscription/__init__.py
new file mode 100644
index 000000000..708e164fd
--- /dev/null
+++ b/osi_analytic_segments_purchase_subscription/__init__.py
@@ -0,0 +1,3 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from . import models
diff --git a/osi_analytic_segments_purchase_subscription/__manifest__.py b/osi_analytic_segments_purchase_subscription/__manifest__.py
new file mode 100644
index 000000000..d984f8f73
--- /dev/null
+++ b/osi_analytic_segments_purchase_subscription/__manifest__.py
@@ -0,0 +1,21 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+{
+    "name": "Analytic Segments in Purchase Subscription",
+    "version": "14.0.1.0.0",
+    "license": "LGPL-3",
+    "summary": "Additional analytic segments in purchase subscription",
+    "author": "Open Source Integrators",
+    "maintainers": ["Open Source Integrators"],
+    "website": "https://github.com/ursais/osi-addons",
+    "category": "Analytic Accounting",
+    "depends": [
+        "purchase_subscription",
+        "osi_analytic_segments",
+    ],
+    "data": [
+        "views/purchase_subscription.xml",
+    ],
+    "installable": True,
+}
diff --git a/osi_analytic_segments_purchase_subscription/models/__init__.py b/osi_analytic_segments_purchase_subscription/models/__init__.py
new file mode 100644
index 000000000..6b0b6b1c7
--- /dev/null
+++ b/osi_analytic_segments_purchase_subscription/models/__init__.py
@@ -0,0 +1,6 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from . import (
+    purchase_subscription,
+    purchase_subscription_line,
+)
diff --git a/osi_analytic_segments_purchase_subscription/models/purchase_subscription.py b/osi_analytic_segments_purchase_subscription/models/purchase_subscription.py
new file mode 100644
index 000000000..d2c104761
--- /dev/null
+++ b/osi_analytic_segments_purchase_subscription/models/purchase_subscription.py
@@ -0,0 +1,30 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from odoo import fields, models
+
+
+class PurchaseSubscription(models.Model):
+    _inherit = "purchase.subscription"
+
+    def _get_default_segment_one(self):
+        return self.env["analytic.segment.one"].get_default_segment_one()
+
+    analytic_segment_one_id = fields.Many2one(
+        "analytic.segment.one",
+        string="Analytic Segment One",
+        default=_get_default_segment_one,
+        copy=False,
+    )
+    analytic_segment_two_id = fields.Many2one(
+        "analytic.segment.two", string="Analytic Segment Two", copy=False
+    )
+
+    def _prepare_invoice_line(self, line, fiscal_position):
+        res = super()._prepare_invoice_line(line, fiscal_position)
+        res.update(
+            {
+                "analytic_segment_one_id": line.analytic_segment_one_id.id,
+                "analytic_segment_two_id": line.analytic_segment_two_id.id,
+            }
+        )
+        return res
diff --git a/osi_analytic_segments_purchase_subscription/models/purchase_subscription_line.py b/osi_analytic_segments_purchase_subscription/models/purchase_subscription_line.py
new file mode 100644
index 000000000..c40995292
--- /dev/null
+++ b/osi_analytic_segments_purchase_subscription/models/purchase_subscription_line.py
@@ -0,0 +1,20 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from odoo import fields, models
+
+
+class PurchaseSubscriptionLine(models.Model):
+    _inherit = "purchase.subscription.line"
+
+    def _get_default_segment_one(self):
+        return self.env["analytic.segment.one"].get_default_segment_one()
+
+    analytic_segment_one_id = fields.Many2one(
+        "analytic.segment.one",
+        string="Analytic Segment One",
+        default=_get_default_segment_one,
+        copy=False,
+    )
+    analytic_segment_two_id = fields.Many2one(
+        "analytic.segment.two", string="Analytic Segment Two", copy=False
+    )
diff --git a/osi_analytic_segments_purchase_subscription/static/description/icon.png b/osi_analytic_segments_purchase_subscription/static/description/icon.png
new file mode 100644
index 000000000..84791119f
Binary files /dev/null and b/osi_analytic_segments_purchase_subscription/static/description/icon.png differ
diff --git a/osi_analytic_segments_purchase_subscription/views/purchase_subscription.xml b/osi_analytic_segments_purchase_subscription/views/purchase_subscription.xml
new file mode 100644
index 000000000..951dd0fdf
--- /dev/null
+++ b/osi_analytic_segments_purchase_subscription/views/purchase_subscription.xml
@@ -0,0 +1,27 @@
+<!-- Copyright 2021 Open Source Integrators
+     License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
+<odoo>
+
+    <!-- Inherit purchase subscription form -->
+    <record id="segments_purchase_subscription_form" model="ir.ui.view">
+        <field name="name">purchase.subscription.segments</field>
+        <field name="model">purchase.subscription</field>
+        <field
+            name="inherit_id"
+            ref="purchase_subscription.purchase_subscription_view_form"
+        />
+        <field name="arch" type="xml">
+            <xpath expr="//field[@name='analytic_account_id']" position="after">
+                <field
+                    name="analytic_segment_one_id"
+                    groups="analytic.group_analytic_accounting"
+                />
+                <field
+                    name="analytic_segment_two_id"
+                    groups="analytic.group_analytic_accounting"
+                />
+            </xpath>
+        </field>
+    </record>
+
+</odoo>
diff --git a/osi_analytic_segments_sales/README.rst b/osi_analytic_segments_sales/README.rst
new file mode 100644
index 000000000..49e1f970d
--- /dev/null
+++ b/osi_analytic_segments_sales/README.rst
@@ -0,0 +1,34 @@
+.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
+   :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+   :alt: License: LGPL-3
+
+=====================
+OSI Analytic Segments
+=====================
+
+This module will have Additional segments for analytic accounts.
+2 additional segments (dimensions) for analytical accounts. The values for selection can be added by the user. 
+
+Fields are added up in Sales, Purchase, Invoice, Journal Item, Analytic Account.
+
+Configuration
+=============
+
+* Create Segments at Accounting/Configurations/Segments
+
+Usage
+=====
+
+
+Credits
+=======
+
+* Open Source Integrators <http://www.opensourceintegrators.com>
+
+Contributors
+------------
+
+* Mayank Gosai <mgosai@ursainfosystems.com>
+* Bhavesh Odedra <bodedra@opensourceintegrators.com>
+* Freni Patel <fpatel@opensourceintegrators.com>
+* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
diff --git a/osi_analytic_segments_sales/__init__.py b/osi_analytic_segments_sales/__init__.py
new file mode 100644
index 000000000..548493cda
--- /dev/null
+++ b/osi_analytic_segments_sales/__init__.py
@@ -0,0 +1,4 @@
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import models
+from . import wizard
diff --git a/osi_analytic_segments_sales/__manifest__.py b/osi_analytic_segments_sales/__manifest__.py
new file mode 100644
index 000000000..848e4fa23
--- /dev/null
+++ b/osi_analytic_segments_sales/__manifest__.py
@@ -0,0 +1,23 @@
+# Copyright (C) 2019 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+{
+    "name": "OSI Analytic Segments Sales",
+    "version": "14.0.1.0.0",
+    "license": "LGPL-3",
+    "summary": "Additional segments for analytic accounts for Sales",
+    "author": "Open Source Integrators",
+    "maintainer": "Open Source Integrators",
+    "website": "https://github.com/ursais/osi-addons",
+    "category": "Analytic Accounting",
+    "depends": [
+        "stock_account",
+        "sale_management",
+        "osi_analytic_segments",
+    ],
+    "data": [
+        "views/sale_order_view.xml",
+    ],
+    "installable": True,
+    "maintainers": ["bodedra"],
+}
diff --git a/osi_analytic_segments_sales/i18n/en_US.po b/osi_analytic_segments_sales/i18n/en_US.po
new file mode 100644
index 000000000..45f2a9776
--- /dev/null
+++ b/osi_analytic_segments_sales/i18n/en_US.po
@@ -0,0 +1,50 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+#	* osi_analytic_segments_sales
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 12.0+e\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2019-01-01 16:32+0000\n"
+"PO-Revision-Date: 2019-01-01 16:32+0000\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: osi_analytic_segments_sales
+#: model:ir.ui.view,arch_db:osi_analytic_segments_sales.sale_order_line_search_segments
+msgid "Analytic Account"
+msgstr "Analytic Account"
+
+#. module: sale
+#: model:ir.ui.view,arch_db:sale.sale_order_line_search_segments
+msgid "Analytic Account"
+msgstr "Analytic Account"
+
+#. module: osi_analytic_segments_sales
+#: model:ir.model.fields,field_description:osi_analytic_segments_sales.field_sale_order_line_analytic_account_id
+msgid "Analytic Account"
+msgstr "Analytic Account"
+
+#. module: osi_analytic_segments_sales
+#: model:ir.model.fields,field_description:osi_analytic_segments_sales.field_sale_order_analytic_segment_one
+#: model:ir.model.fields,field_description:osi_analytic_segments_sales.field_sale_order_line_analytic_segment_one
+msgid "Analytic Segment One"
+msgstr "Analytic Segment One"
+
+#. module: osi_analytic_segments_sales
+#: model:ir.model.fields,field_description:osi_analytic_segments_sales.field_sale_order_analytic_segment_two
+#: model:ir.model.fields,field_description:osi_analytic_segments_sales.field_sale_order_line_analytic_segment_two
+msgid "Analytic Segment Two"
+msgstr "Analytic Segment Two"
+
+#. module: sale
+#: model:ir.model.fields,field_description:sale.field_report_all_channels_sales_analytic_account_id
+#: model:ir.model.fields,field_description:sale.field_sale_order_analytic_account_id
+#: model:ir.model.fields,field_description:sale.field_sale_report_analytic_account_id
+msgid "Analytic Account"
+msgstr "Analytic Account"
diff --git a/osi_analytic_segments_sales/models/__init__.py b/osi_analytic_segments_sales/models/__init__.py
new file mode 100644
index 000000000..bb3e1caa4
--- /dev/null
+++ b/osi_analytic_segments_sales/models/__init__.py
@@ -0,0 +1,6 @@
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from . import (
+    sale_order,
+    sale_order_line,
+    account_move,
+)
diff --git a/osi_analytic_segments_sales/models/account_move.py b/osi_analytic_segments_sales/models/account_move.py
new file mode 100644
index 000000000..728dd1493
--- /dev/null
+++ b/osi_analytic_segments_sales/models/account_move.py
@@ -0,0 +1,83 @@
+# Copyright (C) 2019 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import models
+
+
+class AccountMove(models.Model):
+    _inherit = "account.move"
+
+    def _stock_account_prepare_anglo_saxon_out_lines_vals(self):
+        lines_vals_list = []
+        for move in self:
+            if (
+                not move.is_sale_document(include_receipts=True)
+                or not move.company_id.anglo_saxon_accounting
+            ):
+                continue
+
+            for line in move.invoice_line_ids:
+
+                # Filter out lines being not eligible for COGS.
+                if (
+                    line.product_id.type != "product"
+                    or line.product_id.valuation != "real_time"
+                ):
+                    continue
+
+                # Retrieve accounts needed to generate the COGS.
+                accounts = line.product_id.product_tmpl_id.with_company(
+                    line.company_id
+                ).get_product_accounts(fiscal_pos=move.fiscal_position_id)
+                debit_interim_account = accounts["stock_output"]
+                credit_expense_account = (
+                    accounts["expense"] or self.journal_id.default_account_id
+                )
+                if not debit_interim_account or not credit_expense_account:
+                    continue
+
+                # Compute accounting fields.
+                sign = -1 if move.move_type == "out_refund" else 1
+                price_unit = line._stock_account_get_anglo_saxon_price_unit()
+                balance = sign * line.quantity * price_unit
+
+                # Add interim account line.
+                lines_vals_list.append(
+                    {
+                        "name": line.name[:64],
+                        "move_id": move.id,
+                        "product_id": line.product_id.id,
+                        "product_uom_id": line.product_uom_id.id,
+                        "quantity": line.quantity,
+                        "price_unit": price_unit,
+                        "debit": balance < 0.0 and -balance or 0.0,
+                        "credit": balance > 0.0 and balance or 0.0,
+                        "account_id": debit_interim_account.id,
+                        "analytic_account_id": line.analytic_account_id.id,
+                        "analytic_segment_one_id": line.analytic_segment_one_id.id,
+                        "analytic_segment_two_id": line.analytic_segment_two_id.id,
+                        "exclude_from_invoice_tab": True,
+                        "is_anglo_saxon_line": True,
+                    }
+                )
+                # Add expense account line.
+                lines_vals_list.append(
+                    {
+                        "name": line.name[:64],
+                        "move_id": move.id,
+                        "product_id": line.product_id.id,
+                        "product_uom_id": line.product_uom_id.id,
+                        "quantity": line.quantity,
+                        "price_unit": -price_unit,
+                        "debit": balance > 0.0 and balance or 0.0,
+                        "credit": balance < 0.0 and -balance or 0.0,
+                        "account_id": credit_expense_account.id,
+                        "analytic_account_id": line.analytic_account_id.id,
+                        "analytic_segment_one_id": line.analytic_segment_one_id.id,
+                        "analytic_segment_two_id": line.analytic_segment_two_id.id,
+                        "analytic_tag_ids": [(6, 0, line.analytic_tag_ids.ids)],
+                        "exclude_from_invoice_tab": True,
+                        "is_anglo_saxon_line": True,
+                    }
+                )
+        return lines_vals_list
diff --git a/osi_analytic_segments_sales/models/sale_order.py b/osi_analytic_segments_sales/models/sale_order.py
new file mode 100644
index 000000000..b0da01261
--- /dev/null
+++ b/osi_analytic_segments_sales/models/sale_order.py
@@ -0,0 +1,20 @@
+# Copyright (C) 2019 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from odoo import fields, models
+
+
+class SaleOrder(models.Model):
+    _inherit = "sale.order"
+
+    def _get_default_segment_one(self):
+        return self.env["analytic.segment.one"].get_default_segment_one()
+
+    analytic_segment_one_id = fields.Many2one(
+        "analytic.segment.one",
+        string="Analytic Segment One",
+        default=_get_default_segment_one,
+        copy=False,
+    )
+    analytic_segment_two_id = fields.Many2one(
+        "analytic.segment.two", string="Analytic Segment Two", copy=False
+    )
diff --git a/osi_analytic_segments_sales/models/sale_order_line.py b/osi_analytic_segments_sales/models/sale_order_line.py
new file mode 100644
index 000000000..a95f97c73
--- /dev/null
+++ b/osi_analytic_segments_sales/models/sale_order_line.py
@@ -0,0 +1,36 @@
+# Copyright (C) 2019 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from odoo import fields, models
+
+
+class SaleOrderLine(models.Model):
+    _inherit = "sale.order.line"
+
+    def _get_default_segment_one(self):
+        return self.env["analytic.segment.one"].get_default_segment_one()
+
+    analytic_account_id = fields.Many2one(
+        "account.analytic.account",
+        string="Analytic Account",
+        help="The analytic account related to a sales order Line.",
+        copy=False,
+    )
+    analytic_segment_one_id = fields.Many2one(
+        "analytic.segment.one",
+        string="Analytic Segment One",
+        default=_get_default_segment_one,
+        copy=False,
+    )
+    analytic_segment_two_id = fields.Many2one(
+        "analytic.segment.two", string="Analytic Segment Two", copy=False
+    )
+
+    def _prepare_invoice_line(self, **optional_values):
+        res = super()._prepare_invoice_line()
+        res.update(
+            {
+                "analytic_segment_one_id": self.order_id.analytic_segment_one_id.id,
+                "analytic_segment_two_id": self.order_id.analytic_segment_two_id.id,
+            }
+        )
+        return res
diff --git a/osi_analytic_segments_sales/static/description/icon.png b/osi_analytic_segments_sales/static/description/icon.png
new file mode 100644
index 000000000..84791119f
Binary files /dev/null and b/osi_analytic_segments_sales/static/description/icon.png differ
diff --git a/osi_analytic_segments_sales/views/sale_order_view.xml b/osi_analytic_segments_sales/views/sale_order_view.xml
new file mode 100644
index 000000000..28299ea4c
--- /dev/null
+++ b/osi_analytic_segments_sales/views/sale_order_view.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<odoo>
+
+    <!-- Copyright 2019 Open Source Integrators
+         License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
+
+    <!-- Inherit sale order form -->
+    <record id="view_order_form" model="ir.ui.view">
+        <field name="name">sale.order.form</field>
+        <field name="model">sale.order</field>
+        <field name="inherit_id" ref="sale.view_order_form" />
+        <field name="arch" type="xml">
+            <xpath expr="//group[@name='sale_info']" position="inside">
+                <field name="analytic_segment_one_id" />
+                <field name="analytic_segment_two_id" />
+            </xpath>
+        </field>
+    </record>
+</odoo>
diff --git a/osi_analytic_segments_sales/wizard/__init__.py b/osi_analytic_segments_sales/wizard/__init__.py
new file mode 100644
index 000000000..c49017b06
--- /dev/null
+++ b/osi_analytic_segments_sales/wizard/__init__.py
@@ -0,0 +1,3 @@
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import sale_make_invoice_advance
diff --git a/osi_analytic_segments_sales/wizard/sale_make_invoice_advance.py b/osi_analytic_segments_sales/wizard/sale_make_invoice_advance.py
new file mode 100644
index 000000000..d506ca308
--- /dev/null
+++ b/osi_analytic_segments_sales/wizard/sale_make_invoice_advance.py
@@ -0,0 +1,18 @@
+# Copyright (C) 2019 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import models
+
+
+class SaleAdvancePaymentInv(models.TransientModel):
+    _inherit = "sale.advance.payment.inv"
+
+    def _create_invoice(self, order, so_line, amount):
+        invoice = super()._create_invoice(order, so_line, amount)
+
+        # Update Analytic account and Analytic Segments in Sale Order Line
+        so_line.analytic_account_id = order.analytic_account_id.id
+        so_line.analytic_segment_one_id = order.analytic_segment_one_id.id
+        so_line.analytic_segment_two_id = order.analytic_segment_two_id.id
+
+        return invoice
diff --git a/osi_analytic_segments_stock/README.rst b/osi_analytic_segments_stock/README.rst
new file mode 100644
index 000000000..50d44722a
--- /dev/null
+++ b/osi_analytic_segments_stock/README.rst
@@ -0,0 +1,33 @@
+.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
+   :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+   :alt: License: LGPL-3
+
+==============================
+OSI Analytic Segments in Stock
+==============================
+
+This module adds 2 segments for analytic accounts.
+
+Configuration
+=============
+
+* Go to *Accounting > Configuration > Segments*
+* Create your segments
+
+Usage
+=====
+
+* Go to *Inventory > Operations > Scrap*
+* Create or select a scrap order
+* Set the 2 segments and validate
+
+Credits
+=======
+
+Contributors
+------------
+
+* Open Source Integrators <https://www.opensourceintegrators.com>
+
+  * Maxime Chambreuil <mchambreuil@opensourceintegrators.com>
+  * Freni Patel <fpatel@opensourceintergrators.com>
diff --git a/osi_analytic_segments_stock/__init__.py b/osi_analytic_segments_stock/__init__.py
new file mode 100644
index 000000000..7f24b3df1
--- /dev/null
+++ b/osi_analytic_segments_stock/__init__.py
@@ -0,0 +1,3 @@
+# Copyright (C) 2019 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from . import models
diff --git a/osi_analytic_segments_stock/__manifest__.py b/osi_analytic_segments_stock/__manifest__.py
new file mode 100644
index 000000000..a2993420f
--- /dev/null
+++ b/osi_analytic_segments_stock/__manifest__.py
@@ -0,0 +1,21 @@
+# Copyright (C) 2019 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+{
+    "name": "OSI Analytic Segments Stock",
+    "version": "14.0.1.0.0",
+    "license": "LGPL-3",
+    "summary": "Additional segments for analytic accounts for Stock",
+    "author": "Open Source Integrators",
+    "maintainer": "Open Source Integrators",
+    "website": "https://github.com/ursais/osi-addons",
+    "category": "Analytic Accounting",
+    "depends": [
+        "stock_analytic",
+        "osi_analytic_segments",
+    ],
+    "data": [
+        "views/stock_move.xml",
+        "views/stock_scrap.xml",
+    ],
+    "maintainers": ["bodedra"],
+}
diff --git a/osi_analytic_segments_stock/models/__init__.py b/osi_analytic_segments_stock/models/__init__.py
new file mode 100644
index 000000000..7c354cd64
--- /dev/null
+++ b/osi_analytic_segments_stock/models/__init__.py
@@ -0,0 +1,5 @@
+# Copyright (C) 2019 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from . import stock_move
+from . import stock_move_line
+from . import stock_scrap
diff --git a/osi_analytic_segments_stock/models/stock_move.py b/osi_analytic_segments_stock/models/stock_move.py
new file mode 100644
index 000000000..a646629bb
--- /dev/null
+++ b/osi_analytic_segments_stock/models/stock_move.py
@@ -0,0 +1,43 @@
+# Copyright (C) 2019 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from odoo import fields, models
+
+
+class StockMove(models.Model):
+    _inherit = "stock.move"
+
+    def _get_default_segment_one(self):
+        return self.env["analytic.segment.one"].get_default_segment_one()
+
+    analytic_segment_one_id = fields.Many2one(
+        "analytic.segment.one",
+        string="Analytic Segment One",
+        default=_get_default_segment_one,
+    )
+    analytic_segment_two_id = fields.Many2one(
+        "analytic.segment.two", string="Analytic Segment Two"
+    )
+
+    def _prepare_account_move_line(
+        self, qty, cost, credit_account_id, debit_account_id, description
+    ):
+        self.ensure_one()
+        res = super(StockMove, self)._prepare_account_move_line(
+            qty, cost, credit_account_id, debit_account_id, description
+        )
+        # Add analytic account in debit line
+        if not self.analytic_account_id or not res:
+            return res
+
+        for num in range(0, 2):
+            if (
+                res[num][2]["account_id"]
+                != self.product_id.categ_id.property_stock_valuation_account_id.id
+            ):
+                res[num][2].update(
+                    {
+                        "analytic_segment_one_id": self.analytic_segment_one_id.id,
+                        "analytic_segment_two_id": self.analytic_segment_two_id.id,
+                    }
+                )
+        return res
diff --git a/osi_analytic_segments_stock/models/stock_move_line.py b/osi_analytic_segments_stock/models/stock_move_line.py
new file mode 100644
index 000000000..7529286c1
--- /dev/null
+++ b/osi_analytic_segments_stock/models/stock_move_line.py
@@ -0,0 +1,10 @@
+# Copyright (C) 2019 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+from odoo import fields, models
+
+
+class StockMoveLine(models.Model):
+    _inherit = "stock.move.line"
+
+    analytic_segment_one_id = fields.Many2one(related="move_id.analytic_segment_one_id")
+    analytic_segment_two_id = fields.Many2one(related="move_id.analytic_segment_two_id")
diff --git a/osi_analytic_segments_stock/models/stock_scrap.py b/osi_analytic_segments_stock/models/stock_scrap.py
new file mode 100644
index 000000000..fc374c68e
--- /dev/null
+++ b/osi_analytic_segments_stock/models/stock_scrap.py
@@ -0,0 +1,29 @@
+# Copyright (C) 2019 Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
+from odoo import fields, models
+
+
+class StockScrap(models.Model):
+    _inherit = "stock.scrap"
+
+    def _get_default_segment_one(self):
+        return self.env["analytic.segment.one"].get_default_segment_one()
+
+    analytic_segment_one_id = fields.Many2one(
+        "analytic.segment.one",
+        string="Analytic Segment One",
+        default=_get_default_segment_one,
+    )
+    analytic_segment_two_id = fields.Many2one(
+        "analytic.segment.two", string="Analytic Segment Two"
+    )
+
+    def _prepare_move_values(self):
+        res = super()._prepare_move_values()
+        res.update(
+            {
+                "analytic_segment_one_id": self.analytic_segment_one_id.id,
+                "analytic_segment_two_id": self.analytic_segment_two_id.id,
+            }
+        )
+        return res
diff --git a/osi_analytic_segments_stock/static/description/icon.png b/osi_analytic_segments_stock/static/description/icon.png
new file mode 100644
index 000000000..84791119f
Binary files /dev/null and b/osi_analytic_segments_stock/static/description/icon.png differ
diff --git a/osi_analytic_segments_stock/views/stock_move.xml b/osi_analytic_segments_stock/views/stock_move.xml
new file mode 100644
index 000000000..4ad6b2521
--- /dev/null
+++ b/osi_analytic_segments_stock/views/stock_move.xml
@@ -0,0 +1,71 @@
+<odoo>
+
+    <record id="view_move_form" model="ir.ui.view">
+        <field name="name">stock.move.picking.form</field>
+        <field name="model">stock.move</field>
+        <field name="inherit_id" ref="stock.view_move_form" />
+        <field name="arch" type="xml">
+            <xpath expr="//field[@name='location_dest_id']" position="after">
+                <field name="analytic_segment_one_id" />
+                <field name="analytic_segment_two_id" />
+            </xpath>
+        </field>
+    </record>
+
+    <record id="view_move_tree" model="ir.ui.view">
+        <field name="name">stock.move.picking.tree</field>
+        <field name="model">stock.move</field>
+        <field name="inherit_id" ref="stock.view_move_tree" />
+        <field name="arch" type="xml">
+            <xpath expr="//field[@name='product_uom']" position="after">
+                <field name="analytic_segment_one_id" />
+                <field name="analytic_segment_two_id" />
+            </xpath>
+        </field>
+    </record>
+
+    <record id="view_move_search_analytic" model="ir.ui.view">
+        <field name="name">stock.move.search</field>
+        <field name="model">stock.move</field>
+        <field name="inherit_id" ref="stock.view_move_search" />
+        <field name="arch" type="xml">
+            <xpath expr="//field[@name='partner_id']" position="after">
+                <field name="analytic_segment_one_id" />
+                <field name="analytic_segment_two_id" />
+            </xpath>
+            <xpath
+                expr="//filter[@name='groupby_dest_location_id']"
+                position="after"
+            >
+                <filter
+                    string="Segment One"
+                    name="segment1"
+                    context="{'group_by': 'analytic_segment_one_id'}"
+                    groups="analytic.group_analytic_accounting"
+                />
+                <filter
+                    string="Segment Two"
+                    name="segment2"
+                    context="{'group_by': 'analytic_segment_two_id'}"
+                    groups="analytic.group_analytic_accounting"
+                />
+            </xpath>
+        </field>
+    </record>
+
+    <record id="view_picking_form_analytic" model="ir.ui.view">
+        <field name="name">stock.picking.form</field>
+        <field name="model">stock.picking</field>
+        <field name="inherit_id" ref="stock.view_picking_form" />
+        <field name="arch" type="xml">
+            <xpath
+                expr="//field[@name='move_ids_without_package']/tree/field[@name='product_id']"
+                position="after"
+            >
+                <field name="analytic_segment_one_id" />
+                <field name="analytic_segment_two_id" />
+            </xpath>
+        </field>
+    </record>
+
+</odoo>
diff --git a/osi_analytic_segments_stock/views/stock_scrap.xml b/osi_analytic_segments_stock/views/stock_scrap.xml
new file mode 100644
index 000000000..96b24a6ab
--- /dev/null
+++ b/osi_analytic_segments_stock/views/stock_scrap.xml
@@ -0,0 +1,15 @@
+<odoo>
+
+    <record id="view_scrap_analytic_form" model="ir.ui.view">
+        <field name="name">stock.scrap.analytic.form</field>
+        <field name="model">stock.scrap</field>
+        <field name="inherit_id" ref="stock.stock_scrap_form_view" />
+        <field name="arch" type="xml">
+            <xpath expr="//group/group[1]" position="inside">
+                <field name="analytic_segment_one_id" />
+                <field name="analytic_segment_two_id" />
+            </xpath>
+        </field>
+    </record>
+
+</odoo>
diff --git a/osi_analytic_segments_stock_scrap/README.rst b/osi_analytic_segments_stock_scrap/README.rst
new file mode 100644
index 000000000..411b53956
--- /dev/null
+++ b/osi_analytic_segments_stock_scrap/README.rst
@@ -0,0 +1,72 @@
+==========================
+Scrap Reason Code Analytic
+==========================
+
+.. |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-ursais%2Fosi--addons-lightgray.png?logo=github
+    :target: https://github.com/OCA/stock-logistics-warehouse/tree/14.0/scrap_reason_code
+    :alt: OCA/stock-logistics-warehouse
+
+|badge1| |badge2| |badge3|
+
+Assign Analytic Segments and Analytic Account to Reason Codes and map those to Scrap Orders.
+
+
+**Table of contents**
+
+.. contents::
+   :local:
+
+Usage
+=====
+
+* Add a Scrap Reason Code to a Scrap Order.
+* Observe the Analytic Account and Segments copied over
+
+
+Bug Tracker
+===========
+
+Bugs are tracked on `GitHub Issues <https://github.com/ursais/osi-addons/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 <https://github.com/ursais/osi-addons/issues/new?body=module:%20osi_scrap_reason_code_analytic%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
+
+Credits
+=======
+
+Contributors
+------------
+
+* Open Source Integrators <http://www.opensourceintegrators.com>
+
+  * Steven Campbell <scampbell@opensourceintegrators.com>
+
+Maintainers
+-----------
+
+This module is maintained by Open Source Integrators.
+
+.. image:: https://github.com/ursais.png
+   :target: https://www.opensourceintegrators.com
+   :alt: Open Source Integrators
+
+Open Source Integrators™ (OSI) provides customers a unique combination of
+open source business process consulting and implementations.
+
+.. |maintainer-bodedra| image:: https://github.com/bodedra.png?size=40px
+    :target: https://github.com/bodedra
+    :alt: Bhavesh Odedra
+
+Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
+
+|maintainer-bodedra|
+
+This module is part of the `OSI Odoo Addons <https://github.com/ursais/osi-addons/>`_ project on GitHub.
+
+You are welcome to contribute. To learn how, please visit https://odoo-community.org/page/Contribute.
diff --git a/osi_analytic_segments_stock_scrap/__init__.py b/osi_analytic_segments_stock_scrap/__init__.py
new file mode 100644
index 000000000..66ca882fc
--- /dev/null
+++ b/osi_analytic_segments_stock_scrap/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (C) 2018 Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from . import models
diff --git a/osi_analytic_segments_stock_scrap/__manifest__.py b/osi_analytic_segments_stock_scrap/__manifest__.py
new file mode 100644
index 000000000..29eca0860
--- /dev/null
+++ b/osi_analytic_segments_stock_scrap/__manifest__.py
@@ -0,0 +1,21 @@
+# Copyright (C) 2018 Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+{
+    "name": "Scrap Reason Code Analtyic",
+    "summary": "Provide a user-defined list of scrapping reasons",
+    "version": "14.0.1.0.0",
+    "license": "AGPL-3",
+    "author": "Open Source Integrators",
+    "maintainer": "Open Source Integrators",
+    "website": "https://github.com/ursais/osi-addons",
+    "category": "Inventory",
+    "depends": ["stock_analytic", "scrap_reason_code", "osi_analytic_segments_stock"],
+    "data": [
+        "views/reason_code_view.xml",
+        "views/stock_scrap_views.xml",
+    ],
+    "application": False,
+    "development_status": "Beta",
+    "maintainers": ["bodedra"],
+}
diff --git a/osi_analytic_segments_stock_scrap/models/__init__.py b/osi_analytic_segments_stock_scrap/models/__init__.py
new file mode 100644
index 000000000..df01e8eb7
--- /dev/null
+++ b/osi_analytic_segments_stock_scrap/models/__init__.py
@@ -0,0 +1,5 @@
+# Copyright (C) 2018 Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from . import reason_code
+from . import stock_scrap
diff --git a/osi_analytic_segments_stock_scrap/models/reason_code.py b/osi_analytic_segments_stock_scrap/models/reason_code.py
new file mode 100644
index 000000000..859682e48
--- /dev/null
+++ b/osi_analytic_segments_stock_scrap/models/reason_code.py
@@ -0,0 +1,22 @@
+# Copyright (C) 2018 Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+from odoo import fields, models
+
+
+class ScrapReasonCode(models.Model):
+    _inherit = "scrap.reason.code"
+
+    def _get_default_segment_one(self):
+        return self.env["analytic.segment.one"].get_default_segment_one()
+
+    analytic_account_id = fields.Many2one(
+        string="Analytic Account", comodel_name="account.analytic.account"
+    )
+    analytic_segment_one_id = fields.Many2one(
+        "analytic.segment.one",
+        string="Analytic Segment One",
+        default=_get_default_segment_one,
+    )
+    analytic_segment_two_id = fields.Many2one(
+        "analytic.segment.two", string="Analytic Segment Two"
+    )
diff --git a/osi_analytic_segments_stock_scrap/models/stock_scrap.py b/osi_analytic_segments_stock_scrap/models/stock_scrap.py
new file mode 100644
index 000000000..0c83a7d0d
--- /dev/null
+++ b/osi_analytic_segments_stock_scrap/models/stock_scrap.py
@@ -0,0 +1,14 @@
+# Copyright (C) 2018 Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+from odoo import api, models
+
+
+class StockScrap(models.Model):
+    _inherit = "stock.scrap"
+
+    @api.onchange("reason_code_id")
+    def onchange_reason_code_id(self):
+        if self.reason_code_id:
+            self.analytic_account_id = self.reason_code_id.analytic_account_id
+            self.analytic_segment_one_id = self.reason_code_id.analytic_segment_one_id
+            self.analytic_segment_two_id = self.reason_code_id.analytic_segment_two_id
diff --git a/osi_analytic_segments_stock_scrap/static/description/icon.png b/osi_analytic_segments_stock_scrap/static/description/icon.png
new file mode 100644
index 000000000..84791119f
Binary files /dev/null and b/osi_analytic_segments_stock_scrap/static/description/icon.png differ
diff --git a/osi_analytic_segments_stock_scrap/views/reason_code_view.xml b/osi_analytic_segments_stock_scrap/views/reason_code_view.xml
new file mode 100644
index 000000000..ae6788546
--- /dev/null
+++ b/osi_analytic_segments_stock_scrap/views/reason_code_view.xml
@@ -0,0 +1,24 @@
+<!-- Copyright 2018 Open Source Integrators
+     License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
+<odoo>
+
+    <!-- Reason Code Type -->
+    <record id="view_reason_code_form_analytic" model="ir.ui.view">
+        <field name="name">reason.code.form</field>
+        <field name="model">scrap.reason.code</field>
+        <field
+            name="inherit_id"
+            ref="scrap_reason_code.view_scrap_reason_code_form"
+        />
+        <field name="arch" type="xml">
+            <xpath expr="//form/group[3]" position="after">
+                <group>
+                    <field name="analytic_account_id" />
+                    <field name="analytic_segment_one_id" />
+                    <field name="analytic_segment_two_id" />
+                </group>
+            </xpath>
+        </field>
+    </record>
+
+</odoo>
diff --git a/osi_analytic_segments_stock_scrap/views/stock_scrap_views.xml b/osi_analytic_segments_stock_scrap/views/stock_scrap_views.xml
new file mode 100644
index 000000000..5b036390c
--- /dev/null
+++ b/osi_analytic_segments_stock_scrap/views/stock_scrap_views.xml
@@ -0,0 +1,19 @@
+<!-- Copyright 2018 Open Source Integrators
+     License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
+<odoo>
+
+    <record id="stock_scrap_form_reason_code_required" model="ir.ui.view">
+        <field name="name">stock.scrap.form.reason.code.required</field>
+        <field name="model">stock.scrap</field>
+        <field
+            name="inherit_id"
+            ref="scrap_reason_code.stock_scrap_form_reason_code"
+        />
+        <field name="arch" type="xml">
+            <field name="reason_code_id" position='attributes'>
+                <attribute name="required">1</attribute>
+            </field>
+        </field>
+    </record>
+
+</odoo>
diff --git a/osi_bank_reconciled_report/README.rst b/osi_bank_reconciled_report/README.rst
new file mode 100644
index 000000000..f43879296
--- /dev/null
+++ b/osi_bank_reconciled_report/README.rst
@@ -0,0 +1,32 @@
+.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
+   :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+   :alt: License: LGPL-3
+
+==========================
+OSI Bank Reconciled Report
+==========================
+
+This module adds an extended report underneath Reconciliation Report
+that shows both reconciled and unreconciled bank statement lines.
+
+Configuration
+=============
+
+* Have a Journal of type 'Bank' with statements in it
+
+Usage
+=====
+
+* Go to *Accounting Dashboard > 3 Dots on Top Right of Kanban Card for Bank Account > Reconciled Report*
+
+
+Credits
+=======
+
+Contributors
+------------
+
+* Open Source Integrators <https://www.opensourceintegrators.com>
+
+  * Steven Campbell <scampbell@opensourceintegrators.com>
+  * Freni Patel <fpatel@opensourceintegrators.com>
diff --git a/osi_bank_reconciled_report/__init__.py b/osi_bank_reconciled_report/__init__.py
new file mode 100644
index 000000000..22bcdd921
--- /dev/null
+++ b/osi_bank_reconciled_report/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (C) 2020 Open Source Integrators
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
+
+from . import models
diff --git a/osi_bank_reconciled_report/__manifest__.py b/osi_bank_reconciled_report/__manifest__.py
new file mode 100644
index 000000000..6da83f440
--- /dev/null
+++ b/osi_bank_reconciled_report/__manifest__.py
@@ -0,0 +1,19 @@
+# Copyright (C) 2020 Open Source Integrators
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
+
+{
+    "name": "OSI Bank Reconciled Report",
+    "summary": "View Reconciled Bank Statement Lines",
+    "version": "14.0.1.0.0",
+    "author": "Open Source Integrators, ",
+    "website": "https://github.com/ursais/osi-addons",
+    "category": "Account",
+    "depends": ["account_reports"],
+    "license": "LGPL-3",
+    "data": [
+        "data/account_financial_report_data.xml",
+        "views/account_journal_dashboard_view.xml",
+    ],
+    "installable": True,
+    "maintainers": ["osi-scampbell"],
+}
diff --git a/osi_bank_reconciled_report/data/account_financial_report_data.xml b/osi_bank_reconciled_report/data/account_financial_report_data.xml
new file mode 100644
index 000000000..538ebe941
--- /dev/null
+++ b/osi_bank_reconciled_report/data/account_financial_report_data.xml
@@ -0,0 +1,13 @@
+<odoo>
+    <record
+        id="action_account_report_bank_reconciled_with_journal"
+        model="ir.actions.client"
+    >
+        <field name="name">Bank Reconciled</field>
+        <field name="tag">account_report</field>
+        <field
+            name="context"
+            eval="{'model': 'account.bank.reconciled.report'}"
+        />
+    </record>
+</odoo>
diff --git a/osi_bank_reconciled_report/models/__init__.py b/osi_bank_reconciled_report/models/__init__.py
new file mode 100644
index 000000000..09de7103c
--- /dev/null
+++ b/osi_bank_reconciled_report/models/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (C) 2020 Open Source Integrators
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
+
+from . import account_bank_reconciled_report
diff --git a/osi_bank_reconciled_report/models/account_bank_reconciled_report.py b/osi_bank_reconciled_report/models/account_bank_reconciled_report.py
new file mode 100644
index 000000000..100decbf2
--- /dev/null
+++ b/osi_bank_reconciled_report/models/account_bank_reconciled_report.py
@@ -0,0 +1,490 @@
+# Copyright (C) 2020 Open Source Integrators
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
+
+from odoo import _, api, models
+from odoo.osv import expression
+from odoo.tools.misc import format_date
+
+
+class AccountBankReconciliationReport(models.AbstractModel):
+    _name = "account.bank.reconciled.report"
+    _description = "Bank Reconciled Report"
+    _inherit = "account.report"
+
+    filter_date = {"date": "", "filter": "today"}
+
+    line_number = 0
+
+    def _get_columns_name(self, options):
+        return [
+            {"name": ""},
+            {"name": _("Date")},
+            {"name": _("Amount"), "class": "number"},
+            {"name": _("Memo")},
+            {"name": _("Reference")},
+        ]
+
+    def _add_title_line(self, options, title, amount=None, level=0, date=False):
+        line_number = 0
+        line_number += 1
+        line_currency = self.env.context.get("line_currency", False)
+        return {
+            "id": "line_" + str(line_number),
+            "name": title,
+            "columns": [
+                {"name": date and format_date(self.env, date) or "", "class": "date"},
+                {"name": amount and self.format_value(amount, line_currency)},
+                {"name": ""},
+                {"name": ""},
+            ],
+            "level": level,
+        }
+
+    def _add_total_line(self, amount):
+        line_number = 0
+        line_number += 1
+        line_currency = self.env.context.get("line_currency", False)
+        return {
+            "id": "line_" + str(self.line_number),
+            "name": _("Total Virtual GL Balance"),
+            "columns": [
+                {"name": "", "class": "date"},
+                {"name": self.format_value(amount, line_currency)},
+                {"name": ""},
+                {"name": ""},
+            ],
+            "level": 1,
+            "class": "total",
+        }
+
+    def _add_bank_statement_line(self, line, amount):
+        name = line.name
+        line_currency = self.env.context.get("line_currency", False)
+        return {
+            "id": str(line.id),
+            "caret_options": "account.bank.statement.line",
+            "model": "account.bank.statement.line",
+            "name": len(name) >= 75 and name[0:70] + "..." or name,
+            "columns": [
+                {"name": format_date(self.env, line.date), "class": "date"},
+                {"name": self.format_value(amount, line_currency)},
+                {"name": ""},
+                {"name": line.ref},
+            ],
+            "class": "o_account_reports_level3",
+        }
+
+    def print_pdf(self, options):
+        options["active_id"] = self.env.context.get("active_id")
+        return super(AccountBankReconciliationReport, self).print_pdf(options)
+
+    def print_xlsx(self, options):
+        options["active_id"] = self.env.context.get("active_id")
+        return super(AccountBankReconciliationReport, self).print_xlsx(options)
+
+    @api.model
+    def _get_bank_rec_report_data(self, options, line_id=None):
+        # General data + setup
+        rslt = {}
+
+        journal_id = self._context.get("active_id") or options.get("active_id")
+        journal = self.env["account.journal"].browse(journal_id)
+        selected_companies = self.env["res.company"].browse(
+            self.env.context["allowed_company_ids"]
+        )
+        rslt["use_foreign_currency"] = (
+            journal.currency_id != journal.company_id.currency_id
+            if journal.currency_id
+            else False
+        )
+        rslt["account_ids"] = list(
+            {
+                journal.payment_debit_account_id.id,
+                journal.payment_credit_account_id.id,
+            }
+        )
+        rslt["line_currency"] = (
+            journal.currency_id if rslt["use_foreign_currency"] else False
+        )
+        self = self.with_context(line_currency=rslt["line_currency"])
+        lines_already_accounted = self.env["account.move.line"].search(
+            [
+                ("account_id", "in", rslt["account_ids"]),
+                ("date", "<=", options["date"]["date_to"]),
+                ("company_id", "in", self.env.context["allowed_company_ids"]),
+            ]
+        )
+        rslt["odoo_balance"] = sum(
+            [
+                line.amount_currency if rslt["use_foreign_currency"] else line.balance
+                for line in lines_already_accounted
+            ]
+        )
+
+        # Payments reconciled with a bank statement line
+        aml_domain = [
+            ("account_id", "in", rslt["account_ids"]),
+            "|",
+            ("statement_line_id", "=", False),
+            ("statement_line_id.date", ">", options["date"]["date_to"]),
+            ("account_internal_type", "=", "liquidity"),
+            ("full_reconcile_id", "!=", False),
+            ("date", "<=", options["date"]["date_to"]),
+        ]
+        companies_unreconciled_selection_domain = []
+        for company in selected_companies:
+            company_domain = [("company_id", "=", company.id)]
+            if company.tax_lock_date:
+                company_domain = expression.AND(
+                    [company_domain, [("date", ">=", company.tax_lock_date)]]
+                )
+            companies_unreconciled_selection_domain = expression.OR(
+                [companies_unreconciled_selection_domain, company_domain]
+            )
+        aml_domain += companies_unreconciled_selection_domain
+
+        move_lines = self.env["account.move.line"].search(aml_domain)
+
+        if move_lines:
+            rslt["reconciled_pmts"] = move_lines
+
+        # Payments not reconciled with a bank statement line
+        aml_domain2 = [
+            ("account_id", "in", rslt["account_ids"]),
+            "|",
+            ("statement_line_id", "=", False),
+            ("statement_line_id.date", ">", options["date"]["date_to"]),
+            ("account_internal_type", "=", "liquidity"),
+            ("full_reconcile_id", "=", False),
+            ("date", "<=", options["date"]["date_to"]),
+        ]
+
+        companies_unreconciled_selection_domain = []
+        for company in selected_companies:
+            company_domain = [("company_id", "=", company.id)]
+            if company.tax_lock_date:
+                company_domain = expression.AND(
+                    [company_domain, [("date", ">=", company.tax_lock_date)]]
+                )
+            companies_unreconciled_selection_domain = expression.OR(
+                [companies_unreconciled_selection_domain, company_domain]
+            )
+        aml_domain2 += companies_unreconciled_selection_domain
+
+        move_lines2 = self.env["account.move.line"].search(aml_domain2)
+
+        if move_lines2:
+            rslt["not_reconciled_pmts"] = move_lines2
+
+        # Bank statement lines reconciled with a payment
+        rslt["reconciled_st_positive"] = self.env["account.bank.statement.line"].search(
+            [
+                ("statement_id.journal_id", "=", journal_id),
+                ("date", "<=", options["date"]["date_to"]),
+                ("amount", ">", 0),
+                ("company_id", "in", self.env.context["allowed_company_ids"]),
+            ]
+        )
+
+        rslt["reconciled_st_negative"] = self.env["account.bank.statement.line"].search(
+            [
+                ("statement_id.journal_id", "=", journal_id),
+                ("date", "<=", options["date"]["date_to"]),
+                ("amount", "<", 0),
+                ("company_id", "in", self.env.context["allowed_company_ids"]),
+            ]
+        )
+
+        # Bank statement lines not reconciled with a payment
+        rslt["not_reconciled_st_positive"] = self.env[
+            "account.bank.statement.line"
+        ].search(
+            [
+                ("statement_id.journal_id", "=", journal_id),
+                ("date", "<=", options["date"]["date_to"]),
+                ("amount", ">", 0),
+                ("company_id", "in", self.env.context["allowed_company_ids"]),
+            ]
+        )
+
+        rslt["not_reconciled_st_negative"] = self.env[
+            "account.bank.statement.line"
+        ].search(
+            [
+                ("statement_id.journal_id", "=", journal_id),
+                ("date", "<=", options["date"]["date_to"]),
+                ("amount", "<", 0),
+                ("company_id", "in", self.env.context["allowed_company_ids"]),
+            ]
+        )
+
+        # Final
+        last_statement = self.env["account.bank.statement"].search(
+            [
+                ("journal_id", "=", journal_id),
+                ("date", "<=", options["date"]["date_to"]),
+                ("company_id", "in", self.env.context["allowed_company_ids"]),
+            ],
+            order="date desc, id desc",
+            limit=1,
+        )
+        rslt["last_st_balance"] = last_statement.balance_end
+        rslt["last_st_end_date"] = last_statement.date
+
+        return rslt
+
+    @api.model
+    def _get_amount(self, line, report_data):
+        if report_data["use_foreign_currency"]:
+            if line.currency_id == report_data["line_currency"]:
+                return line.amount_currency
+            else:
+                return line.currency_id._convert(
+                    line.amount_currency,
+                    report_data["line_currency"],
+                    self.env.user.company_id,
+                    line.date,
+                )
+        else:
+            return line.balance
+
+    @api.model
+    def _get_lines(self, options, line_id=None):
+        # Fetch data
+        report_data = self._get_bank_rec_report_data(options, line_id)
+        self = self.with_context(line_currency=report_data["line_currency"])
+        # Compute totals
+        unrec_tot = sum(
+            [
+                -(self._get_amount(aml, report_data))
+                for aml in report_data.get("reconciled_pmts", [])
+            ]
+        )
+        outstanding_plus_tot = sum(
+            [
+                st_line.amount
+                for st_line in report_data.get("reconciled_st_positive", [])
+            ]
+        )
+        outstanding_minus_tot = sum(
+            [
+                st_line.amount
+                for st_line in report_data.get("reconciled_st_negative", [])
+            ]
+        )
+        computed_stmt_balance = (
+            report_data["odoo_balance"]
+            + outstanding_plus_tot
+            + outstanding_minus_tot
+            + unrec_tot
+        )
+        difference = computed_stmt_balance - report_data["last_st_balance"]
+
+        # Build report
+        lines = []
+
+        lines.append(
+            self._add_title_line(
+                options,
+                _("Virtual GL Balance"),
+                amount=None
+                if self.env.user.company_id.totals_below_sections
+                else computed_stmt_balance,
+                level=0,
+            )
+        )
+
+        gl_title = _("Current balance of account %s")
+        if len(report_data["account_ids"]) > 1:
+            gl_title = _("Current balance of accounts %s")
+
+        accounts = self.env["account.account"].browse(report_data["account_ids"])
+        accounts_string = ", ".join(accounts.mapped("code"))
+        lines.append(
+            self._add_title_line(
+                options,
+                gl_title % accounts_string,
+                level=1,
+                amount=report_data["odoo_balance"],
+                date=options["date"]["date_from"],
+            )
+        )
+
+        lines.append(self._add_title_line(options, _("Operations to Process"), level=1))
+
+        if report_data.get("not_reconciled_st_positive") or report_data.get(
+            "not_reconciled_st_negative"
+        ):
+            lines.append(
+                self._add_title_line(
+                    options,
+                    _(
+                        "Unreconciled Bank \
+                                           Statement Lines"
+                    ),
+                    level=2,
+                )
+            )
+            for line in report_data.get("not_reconciled_st_positive", []):
+                lines.append(self._add_bank_statement_line(line, line.amount))
+
+            for line in report_data.get("not_reconciled_st_negative", []):
+                lines.append(self._add_bank_statement_line(line, line.amount))
+
+        if report_data.get("reconciled_st_positive") or report_data.get(
+            "reconciled_st_negative"
+        ):
+            lines.append(
+                self._add_title_line(
+                    options,
+                    _(
+                        "Reconciled Bank \
+                                           Statement Lines"
+                    ),
+                    level=2,
+                )
+            )
+            for line in report_data.get("reconciled_st_positive", []):
+                lines.append(self._add_bank_statement_line(line, line.amount))
+
+            for line in report_data.get("reconciled_st_negative", []):
+                lines.append(self._add_bank_statement_line(line, line.amount))
+
+        if report_data.get("not_reconciled_pmts"):
+            lines.append(
+                self._add_title_line(
+                    options,
+                    _(
+                        "Validated Payments \
+                                            Not Linked with a Bank \
+                                            Statement Line"
+                    ),
+                    level=2,
+                )
+            )
+            for line in report_data["not_reconciled_pmts"]:
+                line_number = 0
+                line_number += 1
+                line_description = line_title = line.ref
+                if (
+                    line_description
+                    and len(line_description) > 70
+                    and not self.env.context.get("print_mode")
+                ):
+                    line_description = line.ref[:65] + "..."
+                lines.append(
+                    {
+                        "id": str(line.id),
+                        "name": line.name,
+                        "columns": [
+                            {"name": format_date(self.env, line.date)},
+                            {
+                                "name": line_description,
+                                "title": line_title,
+                                "style": "display:block;",
+                            },
+                            {
+                                "name": self.format_value(
+                                    -self._get_amount(line, report_data),
+                                    report_data["line_currency"],
+                                )
+                            },
+                        ],
+                        "class": "o_account_reports_level3",
+                        "caret_options": "account.payment",
+                    }
+                )
+
+        if report_data.get("reconciled_pmts"):
+            lines.append(
+                self._add_title_line(
+                    options,
+                    _(
+                        "Validated Payments Linked \
+                            with a Bank Statement Line"
+                    ),
+                    level=2,
+                )
+            )
+            for line in report_data["reconciled_pmts"]:
+                line_number = 0
+                line_number += 1
+                line_description = line_title = line.ref
+                if (
+                    line_description
+                    and len(line_description) > 70
+                    and not self.env.context.get("print_mode")
+                ):
+                    line_description = line.ref[:65] + "..."
+                lines.append(
+                    {
+                        "id": str(line.id),
+                        "name": line.name,
+                        "columns": [
+                            {"name": format_date(self.env, line.date)},
+                            {
+                                "name": line_description,
+                                "title": line_title,
+                                "style": "display:block;",
+                            },
+                            {
+                                "name": self.format_value(
+                                    -self._get_amount(line, report_data),
+                                    report_data["line_currency"],
+                                )
+                            },
+                        ],
+                        "class": "o_account_reports_level3",
+                        "caret_options": "account.payment",
+                    }
+                )
+
+        if self.env.user.company_id.totals_below_sections:
+            lines.append(self._add_total_line(computed_stmt_balance))
+
+        lines.append(
+            self._add_title_line(
+                options,
+                _(
+                    "Last Bank Statement \
+                                            Ending Balance"
+                ),
+                level=0,
+                amount=report_data["last_st_balance"],
+                date=report_data["last_st_end_date"],
+            )
+        )
+        last_line = self._add_title_line(
+            options, _("Unexplained Difference"), level=0, amount=difference
+        )
+        last_line["title_hover"] = _(
+            """Difference between Virtual \
+                                     GL Balance and Last Bank Statement \
+                                     Ending Balance.\n
+                                     If non-zero, it could be due to
+                                     1) some bank statements being not yet \
+                                     encoded into Odoo
+                                     2) payments double-encoded"""
+        )
+        line_currency = self.env.context.get("line_currency", False)
+        if self.env.context.get("no_format"):
+            last_line["columns"][-1]["title"] = self.format_value(
+                computed_stmt_balance, line_currency
+            ) - self.format_value(report_data["last_st_balance"], line_currency)
+        else:
+            last_line["columns"][-1]["title"] = (
+                self.format_value(computed_stmt_balance, line_currency)
+                + " - "
+                + self.format_value(report_data["last_st_balance"], line_currency)
+            )
+        lines.append(last_line)
+
+        return lines
+
+    @api.model
+    def _get_report_name(self):
+        journal_id = self._context.get("active_id")
+        if journal_id:
+            journal = self.env["account.journal"].browse(journal_id)
+            return _("Bank Reconciliation") + ": " + journal.name
+        return _("Bank Reconciliation")
diff --git a/osi_bank_reconciled_report/static/description/icon.png b/osi_bank_reconciled_report/static/description/icon.png
new file mode 100644
index 000000000..84791119f
Binary files /dev/null and b/osi_bank_reconciled_report/static/description/icon.png differ
diff --git a/osi_bank_reconciled_report/views/account_journal_dashboard_view.xml b/osi_bank_reconciled_report/views/account_journal_dashboard_view.xml
new file mode 100644
index 000000000..a1ef24750
--- /dev/null
+++ b/osi_bank_reconciled_report/views/account_journal_dashboard_view.xml
@@ -0,0 +1,27 @@
+<odoo>
+    <record
+        model="ir.ui.view"
+        id="account_reports_journal_dashboard_kanban_view_reconciled"
+    >
+        <field name="name">account.journal.dashboard.kanban.reports</field>
+        <field name="model">account.journal</field>
+        <field
+            name="inherit_id"
+            ref="account_reports.account_reports_journal_dashboard_kanban_view"
+        />
+        <field name="arch" type="xml">
+            <xpath
+                expr="//div[hasclass('o_kanban_manage_reconciliation')]"
+                position="inside"
+            >
+                <div groups="account.group_account_manager">
+                    <a
+                        type="action"
+                        name="%(action_account_report_bank_reconciled_with_journal)d"
+                    >Reconciled Report</a>
+                </div>
+            </xpath>
+        </field>
+    </record>
+
+</odoo>
diff --git a/osi_credit_card_reconciliation/README.rst b/osi_credit_card_reconciliation/README.rst
new file mode 100644
index 000000000..9fedd8bf9
--- /dev/null
+++ b/osi_credit_card_reconciliation/README.rst
@@ -0,0 +1,80 @@
+==========================
+Credit Card Reconciliation
+==========================
+
+.. |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-LGPL--3-blue.png
+    :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+    :alt: License: LGPL-3
+.. |badge3| image:: https://img.shields.io/badge/github-ursais%2Fosi--addons-lightgray.png?logo=github
+    :target: https://github.com/ursais/osi-addons/tree/12.0/osi_credit_card_reconciliation
+    :alt: ursais/osi-addons
+
+|badge1| |badge2| |badge3|
+
+This module allows you to reconcile your credit cards.
+
+**Table of contents**
+
+.. contents::
+   :local:
+
+Configuration
+=============
+
+* Coming soon...
+
+Usage
+=====
+
+* Coming soon...
+
+Bug Tracker
+===========
+
+Bugs are tracked on `GitHub Issues <https://github.com/ursais/osi-addons/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 <https://github.com/ursais/osi-addons/issues/new?body=module:%osi_credit_card_reconciliation%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
+
+Credits
+=======
+
+* Open Source Integrators <http://www.opensourceintegrators.com>
+
+Contributors
+------------
+
+* Balaji Kannan <bkannan@opensourceintegrators.com>
+* Bhavesh Odedra <bodedra@opensourceintegrators.com>
+* Sandip Mangukiya <smangukiya@opensourceintegrators.com>
+* Mayank Gosai <mgosai@opensourceintegrators.com>
+* Steve Campbell <scampbell@opensourceintegrators.com>
+* Maxime Chambreuil <mchambreuil@opensourceintegrators.com>
+* Freni Patel <fpatel@opensourceintegrators.com>
+
+Maintainers
+-----------
+
+This module is maintained by Open Source Integrators.
+
+.. image:: https://github.com/ursais.png
+   :target: https://www.opensourceintegrators.com
+   :alt: Open Source Integrators
+
+Open Source Integrators™ (OSI) provides customers a unique combination of
+open source business process consulting and implementations.
+
+.. |maintainer-mgosai| image:: https://github.com/mgosai.png?size=40px
+    :target: https://github.com/mgosai
+    :alt: Mayank Gosai
+
+Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
+
+|maintainer-mgosai|
+
+This module is part of the `OSI Odoo Addons <https://github.com/ursais/osi-addons>`_ project on GitHub.
+
+You are welcome to contribute. To learn how, please visit https://odoo-community.org/page/Contribute.
diff --git a/osi_credit_card_reconciliation/__init__.py b/osi_credit_card_reconciliation/__init__.py
new file mode 100644
index 000000000..1b33df084
--- /dev/null
+++ b/osi_credit_card_reconciliation/__init__.py
@@ -0,0 +1,18 @@
+# Copyright (C) 2019 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import models
+from odoo import api, SUPERUSER_ID
+
+
+def init_settings(env):
+    """Activate the Multi Currency by default."""
+    curr_config_id = env["res.config.settings"].create({"group_multi_currency": True})
+    # We need to call execute, otherwise the "implied_group" in fields are not
+    # processed.
+    curr_config_id.execute()
+
+
+def post_init(cr, registry):
+    env = api.Environment(cr, SUPERUSER_ID, {})
+    init_settings(env)
diff --git a/osi_credit_card_reconciliation/__manifest__.py b/osi_credit_card_reconciliation/__manifest__.py
new file mode 100644
index 000000000..9ecda82fa
--- /dev/null
+++ b/osi_credit_card_reconciliation/__manifest__.py
@@ -0,0 +1,30 @@
+# Copyright (C) 2019 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+{
+    "name": "Credit Card Reconciliation",
+    "summary": "Reconcile your credit cards",
+    "version": "14.0.1.0.0",
+    "license": "LGPL-3",
+    "author": "Open Source Integrators",
+    "maintainer": "Open Source Integrators",
+    "website": "https://github.com/ursais/osi-addons",
+    "category": "Accounting",
+    "depends": [
+        "account_accountant",
+        "account_payment_credit_card",
+    ],
+    "data": [
+        "security/credit_card_reconciliation_security.xml",
+        "security/ir.model.access.csv",
+        "views/cc_rec_statement_view.xml",
+        "views/account_move_line_view.xml",
+        "report/cc_rec_statement_view.xml",
+        "report/cc_rec_statement_detail.xml",
+        "report/cc_rec_statement_summary.xml",
+    ],
+    "post_init_hook": "post_init",
+    "application": False,
+    "development_status": "Beta",
+    "maintainers": ["mgosai"],
+}
diff --git a/osi_credit_card_reconciliation/models/__init__.py b/osi_credit_card_reconciliation/models/__init__.py
new file mode 100644
index 000000000..bc1c78695
--- /dev/null
+++ b/osi_credit_card_reconciliation/models/__init__.py
@@ -0,0 +1,8 @@
+# Copyright (C) 2019 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import (
+    cc_rec_statement,
+    cc_rec_statement_line,
+    account_move_line,
+)
diff --git a/osi_credit_card_reconciliation/models/account_move_line.py b/osi_credit_card_reconciliation/models/account_move_line.py
new file mode 100644
index 000000000..8f9918231
--- /dev/null
+++ b/osi_credit_card_reconciliation/models/account_move_line.py
@@ -0,0 +1,17 @@
+# Copyright (C) 2019 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import fields, models
+
+
+class AccountMoveLine(models.Model):
+    _inherit = "account.move.line"
+
+    cleared_cc_account = fields.Boolean(
+        "CC Cleared?", help="Check if the transaction has cleared from the bank"
+    )
+    cc_rec_statement_id = fields.Many2one(
+        "cc.rec.statement",
+        string="CC Rec Statement",
+        help="The credit card reconciliation statement linked with the journal" " item",
+    )
diff --git a/osi_credit_card_reconciliation/models/cc_rec_statement.py b/osi_credit_card_reconciliation/models/cc_rec_statement.py
new file mode 100644
index 000000000..d1138ab76
--- /dev/null
+++ b/osi_credit_card_reconciliation/models/cc_rec_statement.py
@@ -0,0 +1,711 @@
+# Copyright (C) 2019 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+import time
+from operator import itemgetter
+
+from odoo import _, api, fields, models
+from odoo.exceptions import UserError
+
+
+class CcRecStatement(models.Model):
+    _name = "cc.rec.statement"
+    _description = "CC Rec Statement"
+    _order = "ending_date desc"
+
+    def check_group(self):
+        """Check if following security constraints are implemented for groups:
+        CC Statement Preparer– they can create, view and delete any of the Bank
+         Statements provided the Bank Statement is not in the DONE state,
+        or the Ready for Review state.
+        Bank Statement Verifier – they can create, view, edit, and delete any
+         of the Bank Statements information at any time.
+        NOTE: DONE Bank Statements  are only allowed to be deleted by a Bank
+         Statement Verifier."""
+
+        group_verifier_id = self.env["ir.model.data"].xmlid_to_res_id(
+            "osi_credit_card_reconciliation.group_cc_stmt_verifier"
+        )
+        if group_verifier_id:
+            group_verifier = self.env["res.groups"].browse(group_verifier_id)
+            group_user_ids = [user.id for user in group_verifier.users]
+            for statement in self:
+                if statement.state != "draft" and self._uid not in group_user_ids:
+                    raise UserError(
+                        _(
+                            "Only a member of '%s' group can delete/edit credit"
+                            " card statements when not in the draft state!"
+                            % (group_verifier.name)
+                        )
+                    )
+        return True
+
+    def copy(self, default=None):
+        self.ensure_one()
+        default = dict(default or {})
+        default.update(
+            {"credit_move_line_ids": [], "debit_move_line_ids": [], "name": ""}
+        )
+        return super().copy(default)
+
+    def write(self, vals):
+        for rec in self:
+            # Check if the user is allowed to perform the action
+            rec.check_group()
+            if "journal_id" in vals and vals.get("journal_id"):
+                journal = self.env["account.journal"].browse(vals.get("journal_id"))
+                if (
+                    journal
+                    and journal.partner_id
+                    and journal.partner_id.property_account_payable_id
+                ):
+                    vals.update(
+                        {
+                            "account_id": journal.partner_id.property_account_payable_id.id
+                        }
+                    )
+            return super(CcRecStatement, rec).write(vals)
+
+    @api.model
+    def create(self, vals):
+        if "journal_id" in vals and vals.get("journal_id"):
+            journal = self.env["account.journal"].browse(vals.get("journal_id"))
+            if (
+                journal
+                and journal.partner_id
+                and journal.partner_id.property_account_payable_id
+            ):
+                vals.update(
+                    {"account_id": journal.partner_id.property_account_payable_id.id}
+                )
+        return super(CcRecStatement, self).create(vals)
+
+    def unlink(self):
+        # Reset the related account.move.line to be re-assigned later to
+        # statement.
+        # Check if the user is allowed to perform the action
+        self.check_group()
+        for rec in self:
+            lines = rec.credit_move_line_ids + rec.debit_move_line_ids
+            # call unlink method to reset
+            lines.unlink()
+            return super(CcRecStatement, rec).unlink()
+
+    def _check_difference_balance(self):
+        "Check if difference balance is zero or not."
+        for statement in self:
+            if statement.cleared_balance_cur:
+                if statement.difference_cur != 0.0:
+                    raise UserError(
+                        _(
+                            "Prior to reconciling a statement, all differences "
+                            "must be accounted for and the difference must be "
+                            "zero. Please review and make necessary changes."
+                        )
+                    )
+            else:
+                if statement.difference != 0.0:
+                    raise UserError(
+                        _(
+                            "Prior to reconciling a statement, all differences "
+                            "must be accounted for and the difference must be "
+                            "zero. Please review and make necessary changes."
+                        )
+                    )
+        return True
+
+    def action_cancel(self):
+        "Cancel the statement."
+        for rec in self:
+            rec.write({"state": "cancel"})
+        return True
+
+    def action_review(self):
+        # Change the status of statement from 'draft' to 'to_be_reviewed'."
+        # If difference balance not zero prevent further processing
+        for rec in self:
+            rec._check_difference_balance()
+            rec.write({"state": "to_be_reviewed"})
+        return True
+
+    def action_process(self):
+        # Set the account move lines as Cleared and Assign CC Acc Rec
+        # Statement ID for the statement lines which are marked as Cleared.
+        # If difference balance not zero prevent further processing
+        self._check_difference_balance()
+        for rec in self:
+            lines = rec.credit_move_line_ids + rec.debit_move_line_ids
+            for line in lines:
+                # Mark the move lines as 'Cleared' and assign the
+                # 'CC Acc Rec Statement ID'
+                line.move_line_id.write(
+                    {
+                        "cleared_cc_account": line.cleared_cc_account,
+                        "cc_rec_statement_id": line.cleared_cc_account
+                        and rec.id
+                        or False,
+                    }
+                )
+            rec.write(
+                {
+                    "state": "done",
+                    "verified_by_user_id": self._uid,
+                    "verified_date": time.strftime("%Y-%m-%d"),
+                }
+            )
+        return True
+
+    def action_cancel_draft(self):
+        """Reset the statement to draft and perform resetting operations."""
+        aml = self.env["account.move.line"]
+        sline = self.env["cc.rec.statement.line"]
+        for rec in self:
+            lines = rec.credit_move_line_ids + rec.debit_move_line_ids
+            for line in lines:
+                sline |= line
+
+                # Find move lines related to statement lines
+                if line.move_line_id:
+                    aml |= line.move_line_id
+
+            # Reset 'Cleared' and 'CC Acc Rec Statement ID' to False
+            aml.write({"cleared_cc_account": False, "cc_rec_statement_id": False})
+            # Reset 'Cleared' in statement lines
+            sline.write({"cleared_cc_account": False, "research_required": False})
+            # Reset statement
+            rec.write(
+                {"state": "draft", "verified_by_user_id": False, "verified_date": False}
+            )
+        return True
+
+    def action_select_all(self):
+        """Mark all the statement lines as 'Cleared'."""
+        line_ids = self.env["cc.rec.statement.line"]
+        for rec in self:
+            lines = rec.credit_move_line_ids + rec.debit_move_line_ids
+            line_ids |= map(lambda x: x.id, lines)
+            line_ids.write({"cleared_cc_account": True})
+        return True
+
+    def action_unselect_all(self):
+        """Reset 'Cleared' in all the statement lines."""
+        line_ids = self.env["cc.rec.statement.line"]
+        for rec in self:
+            lines = rec.credit_move_line_ids + rec.debit_move_line_ids
+            line_ids |= map(lambda x: x.id, lines)
+            line_ids.write({"cleared_cc_account": False})
+        return True
+
+    # refresh data
+    def refresh_record(self):
+        retval = True
+        refdict = {}
+        # get current state of moves in the statement
+        for rec in self:
+            if rec.state == "draft":
+                for cr_item in rec.credit_move_line_ids:
+                    if cr_item.move_line_id and cr_item.cleared_cc_account:
+                        refdict[cr_item.move_line_id.id] = cr_item.cleared_cc_account
+
+                for dr_item in rec.debit_move_line_ids:
+                    if dr_item.move_line_id and dr_item.cleared_cc_account:
+                        refdict[dr_item.move_line_id.id] = dr_item.cleared_cc_account
+
+        # for the statement
+        for rec in self:
+            # process only if the statement is in draft state
+            if rec.state == "draft":
+                ending_date = rec.ending_date
+                suppress_ending_date_filter = rec.suppress_ending_date_filter
+                vals = self.fetch_data(ending_date, suppress_ending_date_filter)
+
+                # list of credit lines
+                outlist = []
+                for cr_item in vals["value"]["credit_move_line_ids"]:
+                    cr_dict = cr_item[2]
+                    cr_dict["cleared_cc_account"] = (
+                        refdict and refdict.get(cr_dict["move_line_id"]) or False
+                    )
+                    cr_dict["research_required"] = False
+                    item = [0, False, cr_dict]
+                    outlist.append(item)
+
+                # list of debit lines
+                inlist = []
+                for dr_item in vals["value"]["debit_move_line_ids"]:
+                    dr_dict = dr_item[2]
+                    dr_dict["cleared_cc_account"] = (
+                        refdict and refdict.get(dr_dict["move_line_id"], False) or False
+                    )
+                    dr_dict["research_required"] = False
+
+                    item = [0, False, dr_dict]
+                    inlist.append(item)
+
+                # write it to the record so it is visible on the form
+                retval = rec.write(
+                    {
+                        "last_ending_date": vals["value"]["last_ending_date"],
+                        "starting_balance": vals["value"]["starting_balance"],
+                        "credit_move_line_ids": outlist,
+                        "debit_move_line_ids": inlist,
+                    }
+                )
+        return retval
+
+    # Get starting balance for the account
+    def get_starting_balance(self, journal_id, account_id, ending_date):
+        result = (False, 0.0)
+        reslist = []
+        statement_obj = self.env["cc.rec.statement"]
+        domain = [
+            ("journal_id", "=", journal_id),
+            ("account_id", "=", account_id),
+            ("state", "=", "done"),
+        ]
+        statement_ids = statement_obj.search(domain)
+
+        # get all statements for this account in the past
+        for statement in statement_ids:
+            if statement.ending_date < ending_date:
+                reslist.append((statement.ending_date, abs(statement.ending_balance)))
+
+        # get the latest statement value
+        if len(reslist):
+            reslist = sorted(reslist, key=itemgetter(0))
+            result = reslist[len(reslist) - 1]
+        return result
+
+    @api.onchange("journal_id")
+    def onchange_journal_id(self):
+        if self.journal_id:
+            if not self.journal_id.partner_id:
+                raise UserError(
+                    _(
+                        "Please define the credit card company on the selected "
+                        "journal (%s)." % self.journal_id.name
+                    )
+                )
+            self.account_id = self.journal_id.partner_id.property_account_payable_id
+
+    def fetch_data(self, ending_date, suppress_ending_date_filter):
+
+        aml = self.env["account.move.line"]
+        sline = self.env["cc.rec.statement.line"]
+        val = {"value": {"credit_move_line_ids": [], "debit_move_line_ids": []}}
+
+        for rec in self:
+            journal_id = rec.journal_id.id
+            account_id = rec.account_id.id
+
+            if journal_id and account_id:
+                line_ids = sline.search([("statement_id", "=", rec.id)])
+                # Call unlink method to reset and remove existing statement
+                # lines and mark reset field values in related move lines
+                line_ids.unlink()
+
+                # Apply filter on move lines to allow
+                # 1. credit and debit side journal items in posted state of
+                #    the selected GL account
+                # 2. Journal items which are not cleared in previous credit
+                #    card statements
+                # 3. Date less than or equal to ending date provided the
+                #    'Suppress Ending Date Filter' is not checkec
+                domain = [
+                    ("account_id", "=", account_id),
+                    ("move_id.state", "=", "posted"),
+                    ("cleared_cc_account", "=", False),
+                ]
+                if not suppress_ending_date_filter:
+                    domain += [("date", "<=", ending_date)]
+                line_ids = aml.search(domain)
+                for line in line_ids:
+                    amount_currency = (
+                        (line.amount_currency < 0)
+                        and (-1 * line.amount_currency)
+                        or line.amount_currency
+                    )
+
+                    # Get partner for the original transaction
+                    counterpart_lines = line.move_id.line_ids.filtered(
+                        lambda ids: ids.account_id.id
+                        == ids.journal_id.payment_debit_account_id.id
+                    )
+                    if len(counterpart_lines) >= 2:
+                        partner_id = counterpart_lines[1].partner_id
+                    else:
+                        partner_id = line.partner_id
+                    res = {
+                        "ref": line.ref,
+                        "date": line.date,
+                        "partner_id": partner_id.id,
+                        "currency_id": line.currency_id.id,
+                        "amount": line.credit or line.debit,
+                        "amountcur": amount_currency,
+                        "name": line.ref,
+                        "move_line_id": line.id,
+                        "type": line.credit and "cr" or "dr",
+                        "from_filter": True,
+                    }
+                    if res["type"] == "cr":
+                        val["value"]["credit_move_line_ids"].append((0, 0, res))
+                    else:
+                        val["value"]["debit_move_line_ids"].append((0, 0, res))
+
+                # Look for previous statement for the account to pull ending
+                # balance as starting balance
+                prev_stmt = self.get_starting_balance(
+                    journal_id, account_id, ending_date
+                )
+                val["value"]["last_ending_date"] = prev_stmt[0]
+                val["value"]["starting_balance"] = prev_stmt[1]
+                val["value"]["journal_id"] = journal_id
+                val["value"]["account_id"] = account_id
+        return val
+
+    @api.onchange("suppress_ending_date_filter", "ending_date")
+    def onchange_suppress_date(self):
+        return self.fetch_data(self.ending_date, self.suppress_ending_date_filter)
+
+    name = fields.Char(
+        "Name",
+        required=True,
+        states={"done": [("readonly", True)]},
+        help="This is a unique name identifying the statement "
+        "(e.g. Credit Card X January 2012).",
+    )
+    account_id = fields.Many2one(
+        "account.account",
+        string="Account",
+        states={"done": [("readonly", True)]},
+        domain="[('company_id', '=', company_id), ('type', '!=', 'view')]",
+        help="The Credit Card Payable Account that is being reconciled.",
+    )
+    ending_date = fields.Date(
+        "Statement Date",
+        required=True,
+        states={"done": [("readonly", True)]},
+        default=lambda *a: time.strftime("%Y-%m-%d"),
+        help="Statement Date",
+    )
+    last_ending_date = fields.Date(
+        string="Last Statement Date",
+        help="The date of the previous credit card statement.",
+    )
+    starting_balance = fields.Float(
+        string="Starting Balance (b/fwd)",
+        required=True,
+        digits="Account",
+        help="Starting Balance for the current credit card statement.",
+        states={"done": [("readonly", True)]},
+    )
+    ending_balance = fields.Float(
+        string="Statement Balance (due)",
+        required=True,
+        digits="Account",
+        help="Statement balance (due)",
+        states={"done": [("readonly", True)]},
+    )
+    company_id = fields.Many2one(
+        "res.company",
+        string="Company",
+        required=True,
+        readonly=True,
+        default=lambda self: self.env.user.company_id,
+        help="The Company the credit card belongs to",
+    )
+    notes = fields.Text("Notes")
+    verified_date = fields.Date(
+        "Verified Date",
+        states={"done": [("readonly", True)]},
+        help="Date when the credit card statement was verified.",
+    )
+    verified_by_user_id = fields.Many2one(
+        "res.users",
+        string="Verified By",
+        states={"done": [("readonly", True)]},
+        help="Entered automatically by the “last user” who saved it. "
+        "System generated.",
+    )
+    credit_move_line_ids = fields.One2many(
+        "cc.rec.statement.line",
+        "statement_id",
+        string="Credits",
+        domain=[("type", "=", "cr")],
+        context={"default_type": "cr"},
+        states={"done": [("readonly", True)]},
+    )
+    debit_move_line_ids = fields.One2many(
+        "cc.rec.statement.line",
+        "statement_id",
+        string="Debits",
+        domain=[("type", "=", "dr")],
+        context={"default_type": "dr"},
+        states={"done": [("readonly", True)]},
+    )
+    cleared_balance = fields.Float(
+        compute="_compute_balance",
+        string="Cleared Total",
+        digits="Account",
+        help="Total cleared amount",
+    )
+    cleared_balance_cur = fields.Float(
+        compute="_compute_balance",
+        string="Cleared Total(Cur)",
+        digits="Account",
+        help="Cleared Total (Cur)",
+    )
+    difference = fields.Float(
+        compute="_compute_balance",
+        string="Difference",
+        digits="Account",
+        help="(Statement Balance – Cleared Total)",
+    )
+    difference_cur = fields.Float(
+        compute="_compute_balance",
+        string="Difference (Cur)",
+        digits="Account",
+        help="(Statement Balance – Cleared Total.)",
+    )
+    uncleared_balance = fields.Float(
+        compute="_compute_balance",
+        string="Uncleared Total",
+        digits="Account",
+        help="Total Uncleared",
+    )
+    uncleared_balance_cur = fields.Float(
+        compute="_compute_balance",
+        string="Uncleared Total (Cur)",
+        digits="Account",
+        help="Total Uncleared (Cur)",
+    )
+    sum_of_debits = fields.Float(
+        compute="_compute_balance",
+        string="Cleared Payments/Credits",
+        digits="Account",
+        help="Cleared Credit Card Payments, credits",
+    )
+    sum_of_debits_cur = fields.Float(
+        compute="_compute_balance",
+        string="Cleared Payments (Cur)",
+        digits="Account",
+        help="Cleared Credit Card Payments, Credits (Cur)",
+    )
+    sum_of_debits_lines = fields.Float(
+        compute="_compute_balance",
+        string="Number of cleared payments/credits",
+        help="Credit Card Payments/Credits # of Items",
+    )
+    sum_of_credits = fields.Float(
+        compute="_compute_balance",
+        string="Cleared Charges",
+        digits="Account",
+        help="Cleared Credit Card Charges, Fees, Interest and Penalties",
+    )
+    sum_of_credits_cur = fields.Float(
+        compute="_compute_balance",
+        string="Cleared Charges (Cur)",
+        digits="Account",
+        help="Credit Card Charges, Fees, Interest and Penalties (Cur)",
+    )
+    sum_of_credits_lines = fields.Float(
+        compute="_compute_balance",
+        string="Number of cleared charges",
+        help="Credit Card Charges, Fees, Interest and Penalties # of Items",
+    )
+    sum_of_udebits = fields.Float(
+        compute="_compute_balance",
+        string="Uncleared Payments/Credits",
+        digits="Account",
+        help="Uncleared Credit Card Payments, credits",
+    )
+    sum_of_udebits_cur = fields.Float(
+        compute="_compute_balance",
+        string="Uncleared Payments/Credits (Cur)",
+        digits="Account",
+        help="Uncleared Credit Card Payments, credits (Cur)",
+    )
+    sum_of_udebits_lines = fields.Float(
+        compute="_compute_balance",
+        string="Number of cleared payments/credits",
+        help="Credit Card Payments/Credits # of Items",
+    )
+    sum_of_ucredits = fields.Float(
+        compute="_compute_balance",
+        string="Uncleared Charges",
+        digits="Account",
+        help="Uncleared Credit Card Charges, Fees, Interest and Penalties",
+    )
+    sum_of_ucredits_cur = fields.Float(
+        compute="_compute_balance",
+        string="Uncleared Charges (Cur)",
+        digits="Account",
+        help="Uncleared Credit Card Charges, Fees, Interest and Penalties " "(Cur)",
+    )
+    sum_of_ucredits_lines = fields.Float(
+        compute="_compute_balance",
+        string="Number of uncleared charges",
+        help="Credit Card Charges, Fees, Interest and Penalties # of Items",
+    )
+    suppress_ending_date_filter = fields.Boolean(
+        "Show all charges, credits and payments",
+        help="If this is checked then the Statement End Date filter on the "
+        "transactions below will not occur. "
+        "All transactions would come over.",
+    )
+    state = fields.Selection(
+        [
+            ("draft", "Draft"),
+            ("to_be_reviewed", "Ready for Review"),
+            ("done", "Done"),
+            ("cancel", "Cancel"),
+        ],
+        "State",
+        index=True,
+        readonly=True,
+        default="draft",
+    )
+    journal_id = fields.Many2one(
+        "account.journal",
+        string="Journal",
+        required=True,
+        states={"done": [("readonly", True)]},
+        domain="[('credit_card', '=', True)]",
+    )
+
+    _sql_constraints = [
+        (
+            "name_company_uniq",
+            "unique (name, company_id, account_id)",
+            "The name of the statement must be unique per company and G/L" " account!",
+        )
+    ]
+
+    def _compute_balance(self):
+        """Computed as following:
+        A) Credit card payments/credits Amount:
+             Total SUM of Amts of lines with Cleared = True
+           Credit card payments/credits # of Items:
+             Total of number of lines with Cleared = True
+        B) Credit card charges, interest and penalties:
+           Credit card charges, interest and penalties # of Items:
+           Cleared Balance (Total Sum of the Deposit Amount Cleared (A)
+                          – Total Sum of Checks Amount Cleared (B))
+           Difference = (Statement Balance - cleared balance = should be zero.
+        """
+        res = {}
+        account_precision = self.env["decimal.precision"].precision_get("Account")
+        for statement in self:
+            res[statement.id] = {
+                "sum_of_credits": 0.0,
+                "sum_of_debits": 0.0,
+                "sum_of_credits_cur": 0.0,
+                "sum_of_debits_cur": 0.0,
+                "sum_of_ucredits": 0.0,
+                "sum_of_udebits": 0.0,
+                "sum_of_ucredits_cur": 0.0,
+                "sum_of_udebits_cur": 0.0,
+                "cleared_balance": 0.0,
+                "cleared_balance_cur": 0.0,
+                "uncleared_balance": 0.0,
+                "uncleared_balance_cur": 0.0,
+                "difference": 0.0,
+                "difference_cur": 0.0,
+                "cleared_cc_account": 0.0,
+                "sum_of_credits_lines": 0.0,
+                "sum_of_debits_lines": 0.0,
+                "sum_of_ucredits_lines": 0.0,
+                "sum_of_udebits_lines": 0.0,
+            }
+            statement.sum_of_debits_lines = 0.0
+            statement.sum_of_udebits_lines = 0.0
+            statement.sum_of_credits_lines = 0.0
+            for line in statement.credit_move_line_ids:
+                statement.sum_of_credits += (
+                    line.cleared_cc_account
+                    and round(line.amount, account_precision)
+                    or 0.0
+                )
+                statement.sum_of_credits_cur += (
+                    line.cleared_cc_account
+                    and round(line.amountcur, account_precision)
+                    or 0.0
+                )
+                statement.sum_of_credits_lines += line.cleared_cc_account and 1.0 or 0.0
+                statement.sum_of_ucredits += (
+                    (not line.cleared_cc_account)
+                    and round(line.amount, account_precision)
+                    or 0.0
+                )
+                statement.sum_of_ucredits_cur += (
+                    (not line.cleared_cc_account)
+                    and round(line.amountcur, account_precision)
+                    or 0.0
+                )
+                statement.sum_of_ucredits_lines += (
+                    (not line.cleared_cc_account) and 1.0 or 0.0
+                )
+            for line in statement.debit_move_line_ids:
+                statement.sum_of_debits += (
+                    line.cleared_cc_account
+                    and round(line.amount, account_precision)
+                    or 0.0
+                )
+                statement.sum_of_debits_cur += (
+                    line.cleared_cc_account
+                    and round(line.amountcur, account_precision)
+                    or 0.0
+                )
+                statement.sum_of_debits_lines += line.cleared_cc_account and 1.0 or 0.0
+                statement.sum_of_udebits += (
+                    (not line.cleared_cc_account)
+                    and round(line.amount, account_precision)
+                    or 0.0
+                )
+                statement.sum_of_udebits_cur += (
+                    (not line.cleared_cc_account)
+                    and round(line.amountcur, account_precision)
+                    or 0.0
+                )
+                statement.sum_of_udebits_lines += (
+                    (not line.cleared_cc_account) and 1.0 or 0.0
+                )
+
+            statement.cleared_balance = abs(
+                round(
+                    statement.sum_of_debits - statement.sum_of_credits,
+                    account_precision,
+                )
+            )
+            statement.cleared_balance_cur = abs(
+                round(
+                    statement.sum_of_debits_cur - statement.sum_of_credits_cur,
+                    account_precision,
+                )
+            )
+            statement.uncleared_balance = abs(
+                round(
+                    statement.sum_of_udebits - statement.sum_of_ucredits,
+                    account_precision,
+                )
+            )
+            statement.uncleared_balance_cur = abs(
+                round(
+                    statement.sum_of_udebits_cur - statement.sum_of_ucredits_cur,
+                    account_precision,
+                )
+            )
+            statement.difference = round(
+                (
+                    abs(statement.starting_balance - statement.ending_balance)
+                    - statement.cleared_balance
+                ),
+                account_precision,
+            )
+            statement.difference_cur = round(
+                (
+                    abs(statement.starting_balance - statement.ending_balance)
+                    - statement.cleared_balance_cur
+                ),
+                account_precision,
+            )
diff --git a/osi_credit_card_reconciliation/models/cc_rec_statement_line.py b/osi_credit_card_reconciliation/models/cc_rec_statement_line.py
new file mode 100644
index 000000000..fd3181df9
--- /dev/null
+++ b/osi_credit_card_reconciliation/models/cc_rec_statement_line.py
@@ -0,0 +1,73 @@
+# Copyright (C) 2019 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import _, api, fields, models
+from odoo.exceptions import UserError
+
+
+class CCRecStatementLine(models.Model):
+    _name = "cc.rec.statement.line"
+    _description = "Statement Line"
+
+    name = fields.Char(
+        "Name", required=True, help="Derived from the related Journal Item."
+    )
+    ref = fields.Char("Reference", help="Derived from the related Journal Item.")
+    partner_id = fields.Many2one(
+        "res.partner", string="Partner", help="Derived from the related Journal Item"
+    )
+    amount = fields.Float(
+        string="Amount",
+        digits="Account",
+        help="Derived from the 'debit' amount from related Journal Item.",
+    )
+    amountcur = fields.Float(
+        string="Amount in Currency",
+        digits="Account",
+        help="Derived from the 'amount currency' amount from related Journal" " Item.",
+    )
+    date = fields.Date("Date", required=True, help="Derived from related Journal Item.")
+    statement_id = fields.Many2one(
+        "cc.rec.statement", string="Statement", required=True, ondelete="cascade"
+    )
+    move_line_id = fields.Many2one(
+        "account.move.line", "Journal Item", help="Related Journal Item."
+    )
+    cleared_cc_account = fields.Boolean(
+        "CC Cleared? ", help="Check if the transaction has cleared from the cc"
+    )
+    research_required = fields.Boolean(
+        "Research Required?",
+        help="Check if the transaction should be researched by the accounting " "team.",
+    )
+    currency_id = fields.Many2one(
+        "res.currency",
+        string="Currency",
+        help="The optional other currency if it is a multi-currency entry.",
+    )
+    type = fields.Selection([("dr", "Debit"), ("cr", "Credit")], "Cr/Dr")
+    from_filter = fields.Boolean("From Filter")
+
+    @api.model
+    def create(self, vals):
+        # Prevent manually adding new statement line.
+        # This would allow only onchange method to pre-populate statement lines
+        # based on the filter rules.
+        if "from_filter" in vals and vals["from_filter"] is False:
+            raise UserError(
+                _(
+                    "You cannot add any new bank statement line manually as of "
+                    'this revision for "%s" !'
+                )
+                % vals["name"]
+            )
+        return super().create(vals)
+
+    def unlink(self):
+        for rec in self:
+            # Reset field values in move lines to be added later
+            if rec.move_line_id:
+                rec.move_line_id.write(
+                    {"cleared_cc_account": False, "cc_rec_statement_id": False}
+                )
+            return super(CCRecStatementLine, rec).unlink()
diff --git a/osi_credit_card_reconciliation/report/cc_rec_statement_detail.xml b/osi_credit_card_reconciliation/report/cc_rec_statement_detail.xml
new file mode 100644
index 000000000..a2940a07a
--- /dev/null
+++ b/osi_credit_card_reconciliation/report/cc_rec_statement_detail.xml
@@ -0,0 +1,316 @@
+<odoo>
+
+    <!-- Copyright (C) 2019 Open Source Integrators
+         License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
+
+    <!-- Customize Report -->
+    <template id="credit_card_detail">
+        <t t-call="web.html_container">
+            <t t-foreach="docs" t-as="o">
+                <t t-set="company" t-value="o.company_id" />
+                <t t-call="web.external_layout_standard">
+                    <div class="page">
+                        <div class="row">
+                            <br />
+                            <h3 align="center">
+                                <b>Reconciliation Detail</b>
+                            </h3>
+                        </div>
+                        <div>
+                            <br />
+                            <h4 align="center">
+                                <b>Perioding Date
+                                    <t t-if="o.ending_date">
+                                        <span t-field="o.ending_date" />
+                                    </t>
+                                </b>
+                            </h4>
+                        </div>
+
+                        <table
+                            class="table table-condensed"
+                            name="move_line_ids_table"
+                        >
+                            <thead>
+                                <tr>
+                                    <th class="hidden">Source Document</th>
+                                    <th align="right" class="text-right">Date
+                                    </th>
+                                    <th align="right" class="text-right">
+                                        Comment
+                                    </th>
+                                    <th align="right" class="text-right">
+                                        Partner
+                                    </th>
+                                    <th align="right" class="text-right">
+                                        Reference
+                                    </th>
+                                    <th align="right" class="text-right">
+                                        Cleared
+                                    </th>
+                                    <th align="right" class="text-right">Amount(
+                                        <span
+                                            t-field="company.currency_id.symbol"
+                                        />
+                                        )
+                                    </th>
+                                    <t t-if="o.account_id.currency_id">
+                                        <th align="right" class="text-right">
+                                            Amount(<span
+                                                t-field="o.account_id.currency_id.symbol"
+                                            />
+                                            )
+                                        </th>
+                                    </t>
+
+                                </tr>
+                            </thead>
+                            <tbody class="move_lines_tbody">
+                                <tr>
+                                    <td>
+                                        <b>Initial Balance</b>
+                                    </td>
+                                    <td />
+                                    <td />
+                                    <td />
+                                    <td />
+                                    <td />
+                                    <td>
+                                        <span
+                                            t-field="o.starting_balance"
+                                            t-field-options='{"widget": "monetary", "display_currency": company.currency_id}'
+                                        />
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <b>Cleared Transactions</b>
+                                    </td>
+                                    <td />
+                                    <td />
+                                    <td />
+                                    <td />
+                                    <td />
+                                    <td />
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <b>Deposits &amp; Credits -
+                                            <t
+                                                t-if="o.sum_of_debits_lines == 0.00"
+                                            />
+                                            <t
+                                                t-if="not o.sum_of_debits_lines == 0.00"
+                                            >
+                                                <span
+                                                    t-field="o.sum_of_debits_lines"
+                                                />
+                                            </t>
+                                            items
+                                        </b>
+                                    </td>
+                                    <td />
+                                    <td />
+                                    <td />
+                                    <td />
+                                    <td />
+                                    <td />
+                                </tr>
+                                <tr
+                                    t-foreach="o.debit_move_line_ids"
+                                    t-as="l"
+                                    align="left"
+                                >
+                                    <td />
+                                    <td>
+                                        <span t-field="l.date" />
+                                    </td>
+                                    <td>
+                                        <span t-field="l.name" />
+                                    </td>
+                                    <td>
+                                        <span t-field="l.partner_id.name" />
+                                    </td>
+                                    <td>
+                                        <span t-field="l.ref" />
+                                    </td>
+                                    <td>
+                                        <t t-if="l.cleared_cc_account">
+                                            <input
+                                                type="checkbox"
+                                                checked="checked"
+                                            />
+                                        </t>
+                                    </td>
+                                    <td>
+                                        <span
+                                            t-field="l.amount"
+                                            t-field-options='{"widget": "monetary", "display_currency": company.currency_id}'
+                                        />
+                                    </td>
+                                    <td>
+                                        <t t-if="not l.amountcur == 0.00">
+                                            <p />
+                                            <span
+                                                t-field="l.amountcur"
+                                                t-field-options='{"widget": "monetary", "display_currency": o.account_id.currency_id}'
+                                            />
+                                        </t>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <b>Total Deposits &amp; Credits</b>
+                                    </td>
+                                    <td />
+                                    <td />
+                                    <td />
+                                    <td />
+                                    <td />
+                                    <td>
+                                        <span
+                                            t-field="o.sum_of_debits"
+                                            t-field-options='{"widget": "monetary", "display_currency": company.currency_id}'
+                                        />
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <b>Checks &amp; Payments -
+                                            <t
+                                                t-if="o.sum_of_credits_lines == 0.00"
+                                            />
+                                            <t
+                                                t-if="not o.sum_of_credits_lines == 0.00"
+                                            >
+                                                <span
+                                                    t-field="o.sum_of_debits_lines"
+                                                />
+                                            </t>
+                                            items
+                                        </b>
+                                    </td>
+                                    <td />
+                                    <td />
+                                    <td />
+                                    <td />
+                                    <td />
+                                    <td />
+                                </tr>
+                                <tr
+                                    t-foreach="o.credit_move_line_ids"
+                                    t-as="l"
+                                    align="left"
+                                >
+                                    <td />
+                                    <td>
+                                        <span t-field="l.date" />
+                                    </td>
+                                    <td>
+                                        <span t-field="l.name" />
+                                    </td>
+                                    <td>
+                                        <span t-field="l.partner_id.name" />
+                                    </td>
+                                    <td>
+                                        <span t-field="l.ref" />
+                                    </td>
+                                    <td>
+                                        <t t-if="l.cleared_cc_account">
+                                            <input
+                                                type="checkbox"
+                                                checked="checked"
+                                            />
+                                        </t>
+                                    </td>
+                                    <td>
+                                        <span
+                                            t-field="l.amount"
+                                            t-field-options='{"widget": "monetary", "display_currency": company.currency_id}'
+                                        />
+                                    </td>
+                                    <td>
+                                        <t t-if="not l.amountcur == 0.00">
+                                            <p />
+                                            <span
+                                                t-field="l.amountcur"
+                                                t-field-options='{"widget": "monetary", "display_currency": o.account_id.currency_id}'
+                                            />
+                                        </t>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <b>Total Deposits and Credits</b>
+                                    </td>
+                                    <td />
+                                    <td />
+                                    <td />
+                                    <td />
+                                    <td />
+                                    <td>
+                                        <span
+                                            t-field="o.sum_of_credits"
+                                            t-field-options='{"widget": "monetary", "display_currency": company.currency_id}'
+                                        />
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <b>Total Cleared Transactions</b>
+                                    </td>
+                                    <td />
+                                    <td />
+                                    <td />
+                                    <td />
+                                    <td />
+                                    <td>
+                                        <span
+                                            t-esc="o.sum_of_debits - o.sum_of_credits"
+                                            t-esc-options='{"widget": "monetary", "display_currency": company.currency_id}'
+                                        />
+                                    </td>
+
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <b>Cleared Balance</b>
+                                    </td>
+                                    <td />
+                                    <td />
+                                    <td />
+                                    <td />
+                                    <td />
+                                    <td>
+                                        <span
+                                            t-field="o.cleared_balance"
+                                            t-field-options='{"widget": "monetary", "display_currency": company.currency_id}'
+                                        />
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <b>Ending Balance</b>
+                                    </td>
+                                    <td />
+                                    <td />
+                                    <td />
+                                    <td />
+                                    <td />
+                                    <td>
+                                        <span
+                                            t-field="o.ending_balance"
+                                            t-field-options='{"widget": "monetary", "display_currency": company.currency_id}'
+                                        />
+                                    </td>
+                                </tr>
+
+                            </tbody>
+                        </table>
+                    </div>
+                </t>
+            </t>
+        </t>
+    </template>
+
+</odoo>
diff --git a/osi_credit_card_reconciliation/report/cc_rec_statement_summary.xml b/osi_credit_card_reconciliation/report/cc_rec_statement_summary.xml
new file mode 100644
index 000000000..5602bb8e4
--- /dev/null
+++ b/osi_credit_card_reconciliation/report/cc_rec_statement_summary.xml
@@ -0,0 +1,278 @@
+<odoo>
+
+    <!-- Copyright (C) 2019 Open Source Integrators
+         License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
+
+    <!-- Customize Report -->
+    <template id="credit_card_summary">
+        <t t-call="web.html_container">
+            <t t-foreach="docs" t-as="o">
+                <t t-set="company" t-value="o.company_id" />
+                <t t-call="web.external_layout_standard">
+                    <div class="page">
+                        <div class="row">
+                            <br />
+                            <h3 align="center">
+                                <b>Reconciliation Detail</b>
+                            </h3>
+                        </div>
+                        <div>
+                            <br />
+                            <h4 align="center">
+                                <b>Perioding Date
+                                    <t t-if="o.ending_date">
+                                        <span t-field="o.ending_date" />
+                                    </t>
+                                </b>
+                            </h4>
+                        </div>
+
+                        <table
+                            class="table table-condensed"
+                            name="move_line_ids_table"
+                        >
+                            <thead>
+                                <tr>
+                                    <th class="hidden">Column 1</th>
+                                    <th class="hidden">Column 2</th>
+                                    <th class="hidden">Column 3</th>
+                                    <th class="hidden">Column 4</th>
+                                    <th class="hidden">Column 5</th>
+                                </tr>
+                            </thead>
+                            <tbody class="move_lines_tbody">
+                                <tr>
+                                    <td>
+                                        <b>Initial Balance</b>
+                                    </td>
+                                    <td />
+                                    <td />
+                                    <td />
+                                    <td>
+                                        <b>
+                                            <span
+                                                t-field="o.starting_balance"
+                                                t-field-options='{"widget": "monetary", "display_currency": company.currency_id}'
+                                            />
+                                        </b>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td />
+                                    <td>
+                                        <b>Cleared Transactions</b>
+                                    </td>
+                                    <td />
+                                    <td />
+                                    <td />
+                                </tr>
+                                <tr>
+                                    <td />
+                                    <td />
+                                    <td>
+                                        <b>Deposits &amp; Credits -
+                                            <t
+                                                t-if="o.sum_of_debits_lines == 0.00"
+                                            />
+                                            <t
+                                                t-if="not o.sum_of_debits_lines == 0.00"
+                                            >
+                                                <span
+                                                    t-field="o.sum_of_debits_lines"
+                                                />
+                                            </t>
+                                            items
+                                        </b>
+                                    </td>
+                                    <td>
+                                        <t t-if="o.sum_of_debits == 0.00" />
+                                        <t t-if="not o.sum_of_debits == 0.00">
+                                            <span
+                                                t-field="o.sum_of_debits"
+                                                t-field-options='{"widget": "monetary", "display_currency": company.currency_id}'
+                                            />
+                                        </t>
+                                    </td>
+                                    <td>
+                                        <t t-if="o.sum_of_debits_cur == 0.00" />
+                                        <t
+                                            t-if="not o.sum_of_debits_cur == 0.00"
+                                        >
+                                            <span
+                                                t-field="o.sum_of_debits_cur"
+                                                t-field-options='{"widget": "monetary", "display_currency": o.account_id.currency_id}'
+                                            />
+                                        </t>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td />
+                                    <td />
+                                    <td>
+                                        <b>Checks &amp; Payments -
+                                            <t
+                                                t-if="o.sum_of_credits_lines == 0.00"
+                                            />
+                                            <t
+                                                t-if="not o.sum_of_credits_lines == 0.00"
+                                            >
+                                                <span
+                                                    t-field="o.sum_of_debits_lines"
+                                                />
+                                            </t>
+                                            items
+                                        </b>
+                                    </td>
+                                    <td>
+                                        <t t-if="o.sum_of_credits == 0.00" />
+                                        <t t-if="not o.sum_of_credits == 0.00">
+                                            <span
+                                                t-field="o.sum_of_credits"
+                                                t-field-options='{"widget": "monetary", "display_currency": company.currency_id}'
+                                            />
+                                        </t>
+                                    </td>
+                                    <td>
+                                        <t
+                                            t-if="o.sum_of_credits_cur == 0.00"
+                                        />
+                                        <t
+                                            t-if="not o.sum_of_credits_cur == 0.00"
+                                        >
+                                            <span
+                                                t-field="o.sum_of_credits_cur"
+                                                t-field-options='{"widget": "monetary", "display_currency": o.account_id.currency_id}'
+                                            />
+                                        </t>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td />
+                                    <td>
+                                        <b>Total Cleared Transactions</b>
+                                    </td>
+                                    <td />
+                                    <td>
+                                        <span
+                                            t-esc="o.sum_of_debits - o.sum_of_credits"
+                                            t-esc-options='{"widget": "monetary", "display_currency": company.currency_id}'
+                                        />
+                                    </td>
+                                    <td>
+                                        <span
+                                            t-esc="o.sum_of_debits_cur - o.sum_of_credits_cur"
+                                            t-esc-options='{"widget": "monetary", "display_currency": o.account_id.currency_id}'
+                                        />
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <t t-if="o.account_id.currency_id">
+                                        <td>
+                                            <b>Cleared Balance</b>
+                                        </td>
+                                        <td />
+                                        <td />
+                                        <td>
+                                            <t
+                                                t-if="o.cleared_balance == 0.00"
+                                            />
+                                            <t
+                                                t-if="not o.cleared_balance == 0.00"
+                                            >
+                                                <span
+                                                    t-field="o.cleared_balance"
+                                                    t-field-options='{"widget": "monetary", "display_currency": company.currency_id}'
+                                                />
+                                            </t>
+                                        </td>
+                                        <td>
+                                            <t
+                                                t-if="o.cleared_balance == 0.00"
+                                            />
+                                            <t
+                                                t-if="not o.cleared_balance == 0.00"
+                                            >
+                                                <b>
+                                                    <span
+                                                        t-field="o.cleared_balance"
+                                                        t-field-options='{"widget": "monetary", "display_currency": company.currency_id}'
+                                                    />
+                                                </b>
+                                            </t>
+                                        </td>
+                                    </t>
+                                    <t t-if="not o.account_id.currency_id">
+                                        <td>
+                                            <b>Cleared Balance</b>
+                                        </td>
+                                        <td />
+                                        <td>
+                                            <t
+                                                t-if="o.cleared_balance == 0.00"
+                                            />
+                                            <t
+                                                t-if="not o.cleared_balance == 0.00"
+                                            >
+                                                <span
+                                                    t-field="o.cleared_balance"
+                                                    t-field-options='{"widget": "monetary", "display_currency": company.currency_id}'
+                                                />
+                                            </t>
+                                        </td>
+                                        <td>
+                                            <t
+                                                t-if="o.cleared_balance_cur == 0.00"
+                                            />
+                                            <t
+                                                t-if="not o.cleared_balance_cur == 0.00"
+                                            >
+                                                <span
+                                                    t-field="o.cleared_balance_cur"
+                                                    t-field-options='{"widget": "monetary", "display_currency": company.currency_id}'
+                                                />
+                                            </t>
+                                        </td>
+                                        <td>
+                                            <t
+                                                t-if="o.cleared_balance_cur == 0.00"
+                                            />
+                                            <t
+                                                t-if="not o.cleared_balance_cur == 0.00"
+                                            >
+                                                <b>
+                                                    <span
+                                                        t-field="o.cleared_balance_cur"
+                                                        t-field-options='{"widget": "monetary", "display_currency": company.currency_id}'
+                                                    />
+                                                </b>
+                                            </t>
+                                        </td>
+                                    </t>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <b>Ending Balance</b>
+                                    </td>
+                                    <td />
+                                    <td />
+                                    <td />
+                                    <td>
+                                        <b>
+                                            <span
+                                                t-field="o.ending_balance"
+                                                t-field-options='{"widget": "monetary", "display_currency": company.currency_id}'
+                                            />
+                                        </b>
+                                    </td>
+                                </tr>
+
+                            </tbody>
+                        </table>
+
+                    </div>
+                </t>
+            </t>
+        </t>
+    </template>
+
+</odoo>
diff --git a/osi_credit_card_reconciliation/report/cc_rec_statement_view.xml b/osi_credit_card_reconciliation/report/cc_rec_statement_view.xml
new file mode 100644
index 000000000..8587f3c70
--- /dev/null
+++ b/osi_credit_card_reconciliation/report/cc_rec_statement_view.xml
@@ -0,0 +1,34 @@
+<odoo>
+
+    <!-- Copyright (C) 2019 Open Source Integrators
+         License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
+
+    <!-- Qweb Reports -->
+    <record id="report_credit_card_detail" model="ir.actions.report">
+        <field name="name">Credit Card-Detail</field>
+        <field name="model">cc.rec.statement</field>
+        <field name="report_type">qweb-pdf</field>
+        <field
+            name="report_name"
+        >osi_credit_card_reconciliation.credit_card_detail</field>
+        <field
+            name="report_file"
+        >osi_credit_card_reconciliation.credit_card_detail</field>
+        <field name="binding_model_id" ref="model_cc_rec_statement" />
+        <field name="attachment">'Detail Statement-' + (object.name)</field>
+    </record>
+    <record id="report_credit_card_summary" model="ir.actions.report">
+        <field name="name">Credit Card-Summary</field>
+        <field name="model">cc.rec.statement</field>
+        <field name="report_type">qweb-pdf</field>
+        <field
+            name="report_name"
+        >osi_credit_card_reconciliation.credit_card_summary</field>
+        <field
+            name="report_file"
+        >osi_credit_card_reconciliation.credit_card_summary</field>
+        <field name="binding_model_id" ref="model_cc_rec_statement" />
+        <field name="attachment">'Summary Statement-' + (object.name)</field>
+    </record>
+
+</odoo>
diff --git a/osi_credit_card_reconciliation/security/credit_card_reconciliation_security.xml b/osi_credit_card_reconciliation/security/credit_card_reconciliation_security.xml
new file mode 100644
index 000000000..8f4c00dd0
--- /dev/null
+++ b/osi_credit_card_reconciliation/security/credit_card_reconciliation_security.xml
@@ -0,0 +1,25 @@
+<odoo>
+
+    <!-- Copyright (C) 2019 Open Source Integrators
+         License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
+
+    <!-- Groups - CC Stmt Preparer , CC Stmt Verifier -->
+    <record id="group_cc_stmt_preparer" model="res.groups">
+        <field name="name">Credit Card Statement Preparer</field>
+    </record>
+
+    <record id="group_cc_stmt_verifier" model="res.groups">
+        <field name="name">Credit Card Statement Verifier</field>
+    </record>
+
+    <!-- Security Rule for CC Rec Stmts -->
+    <record id="cc_reconciliation_comp_rule" model="ir.rule">
+        <field name="name">Credit Card Statements</field>
+        <field ref="model_cc_rec_statement" name="model_id" />
+        <field eval="True" name="global" />
+        <field name="domain_force">['|', ('company_id', '=', False),
+            ('company_id', 'child_of', [user.company_id.id])]
+        </field>
+    </record>
+
+</odoo>
diff --git a/osi_credit_card_reconciliation/security/ir.model.access.csv b/osi_credit_card_reconciliation/security/ir.model.access.csv
new file mode 100644
index 000000000..4bbe38c18
--- /dev/null
+++ b/osi_credit_card_reconciliation/security/ir.model.access.csv
@@ -0,0 +1,7 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_cc_rec_statement,cc.rec.statement,model_cc_rec_statement,account.group_account_user,1,0,0,0
+access_cc_rec_statement_internal_user,cc.rec.statement internal user,model_cc_rec_statement,base.group_user,1,0,0,0
+access_cc_rec_statement_manager,cc.rec.statement,model_cc_rec_statement,account.group_account_manager,1,1,1,1
+access_cc_rec_statement_line,cc.rec.statement.line,model_cc_rec_statement_line,account.group_account_user,1,0,0,0
+access_cc_rec_statement_line_internal_user,cc.rec.statement.line internal user,model_cc_rec_statement_line,base.group_user,1,0,0,0
+access_cc_rec_statement_line_manager,cc.rec.statement.line,model_cc_rec_statement_line,account.group_account_manager,1,1,1,1
diff --git a/osi_credit_card_reconciliation/static/description/icon.png b/osi_credit_card_reconciliation/static/description/icon.png
new file mode 100644
index 000000000..84791119f
Binary files /dev/null and b/osi_credit_card_reconciliation/static/description/icon.png differ
diff --git a/osi_credit_card_reconciliation/views/account_move_line_view.xml b/osi_credit_card_reconciliation/views/account_move_line_view.xml
new file mode 100644
index 000000000..4158b0f12
--- /dev/null
+++ b/osi_credit_card_reconciliation/views/account_move_line_view.xml
@@ -0,0 +1,46 @@
+<odoo>
+
+    <!-- Copyright (C) 2019 Open Source Integrators
+         License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
+
+    <!--- Journal Items Search View -->
+    <record id="view_account_move_line_cc_rec_statement_id" model="ir.ui.view">
+        <field name="name">account.move.line.cc.rec.statement.id</field>
+        <field name="model">account.move.line</field>
+        <field name="inherit_id" ref="account.view_account_move_line_filter" />
+        <field name="arch" type="xml">
+            <field name="journal_id" position="after">
+                <field name="cc_rec_statement_id" />
+            </field>
+            <field name="partner_id" position="before">
+                <filter
+                    icon="terp-document-new"
+                    name="unclear_bank_acc_osi"
+                    string="Uncleared Bank Account"
+                    domain="[('cleared_cc_account','=',False)]"
+                    help="Journal Entries not cleared"
+                />
+                <separator orientation="vertical" />
+            </field>
+        </field>
+    </record>
+
+    <!--- Journal Items Form View -->
+    <record
+        id="view_account_move_line_cc_rec_statement_id_form"
+        model="ir.ui.view"
+    >
+        <field name="name">account.move.line.cc.rec.statement.id.form</field>
+        <field name="model">account.move.line</field>
+        <field name="inherit_id" ref="account.view_move_line_form" />
+        <field name="arch" type="xml">
+            <field name="statement_id" position="after">
+                <field name="cc_rec_statement_id" />
+            </field>
+            <field name="blocked" position="after">
+                <field name="cleared_cc_account" />
+            </field>
+        </field>
+    </record>
+
+</odoo>
diff --git a/osi_credit_card_reconciliation/views/cc_rec_statement_view.xml b/osi_credit_card_reconciliation/views/cc_rec_statement_view.xml
new file mode 100644
index 000000000..9fe42ade5
--- /dev/null
+++ b/osi_credit_card_reconciliation/views/cc_rec_statement_view.xml
@@ -0,0 +1,435 @@
+<odoo>
+
+    <!-- Copyright (C) 2019 Open Source Integrators
+         License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -->
+
+    <!-- CC Reconciliation Statement -->
+    <record id="view_cc_rec_statement_tree" model="ir.ui.view">
+        <field name="name">cc.rec.statement.tree</field>
+        <field name="model">cc.rec.statement</field>
+        <field name="arch" type="xml">
+            <tree
+                string="Credit Card Reconciliation Statements"
+                decoration-muted="state=='cancel'"
+                decoration-info="state=='to_be_reviewed'"
+            >
+                <field name="name" />
+                <field name="ending_date" />
+                <field name="account_id" />
+                <field name="verified_by_user_id" />
+                <field name="state" />
+            </tree>
+        </field>
+    </record>
+
+    <record id="view_cc_rec_statement_form" model="ir.ui.view">
+        <field name="name">cc.rec.statement.form</field>
+        <field name="model">cc.rec.statement</field>
+        <field name="arch" type="xml">
+            <form string="Credit Card Reconciliation Statement">
+                <header>
+                    <button
+                        name="action_cancel"
+                        type="object"
+                        states="draft,to_be_reviewed"
+                        string="Cancel"
+                    />
+                    <button
+                        name="action_review"
+                        type="object"
+                        states="draft"
+                        string="Ready for Review"
+                    />
+                    <button
+                        name="action_process"
+                        type="object"
+                        states="to_be_reviewed"
+                        string="Process"
+                    />
+                    <button
+                        name="action_cancel_draft"
+                        states="cancel,done"
+                        string="Set to Draft"
+                        type="object"
+                    />
+                    <button
+                        name='refresh_record'
+                        string='Refresh'
+                        confirm="Current edits in statement will be lost. Do you want to refresh?"
+                        states="draft"
+                        type='object'
+                    />
+                    <field name="state" widget="statusbar" nolabel="1" />
+                </header>
+                <sheet>
+                    <group col="4" colspan="4">
+                        <field
+                            name="journal_id"
+                            on_change="onchange_journal_id(journal_id)"
+                        />
+                        <field name="account_id" readonly="1" />
+                        <field name="name" placeholder="Enter Name" />
+                        <field
+                            name="ending_date"
+                            placeholder="Statement Date"
+                            on_change="onchange_ending_date(ending_date, suppress_ending_date_filter)"
+                        />
+                        <field
+                            name="starting_balance"
+                            placeholder="Starting Balance (b/fwd)"
+                        />
+                        <field
+                            name="ending_balance"
+                            placeholder="Statement Balance"
+                        />
+                        <field
+                            name="last_ending_date"
+                            placeholder="Last Statement Date"
+                            readonly="1"
+                        />
+                        <field
+                            name="suppress_ending_date_filter"
+                            on_change="onchange_suppress_date(ending_date, suppress_ending_date_filter)"
+                        />
+                        <field
+                            name="company_id"
+                            groups="base.group_multi_company"
+                            placeholder="Enter Company Name"
+                        />
+                    </group>
+                    <separator string="Balances - Cleared and Uncleared" />
+                    <group name="balances" col="4" colspan="4">
+                        <group name="balance1" col="2" colspan="2">
+                            <field name="cleared_balance" />
+                            <field
+                                name="cleared_balance_cur"
+                                attrs="{'invisible':[('cleared_balance_cur','=', 0.0)]}"
+                            />
+                            <field name="difference" />
+                            <field
+                                name="difference_cur"
+                                attrs="{'invisible':[('cleared_balance_cur','=', 0.0)]}"
+                            />
+                        </group>
+                        <group name="balance2" col="2" colspan="2">
+                            <field name="uncleared_balance" />
+                            <field
+                                name="uncleared_balance_cur"
+                                attrs="{'invisible':[('uncleared_balance_cur','=', 0.0)]}"
+                            />
+                        </group>
+                    </group>
+                    <notebook colspan="5">
+                        <page string="Journal Items">
+                            <label
+                                for='debit_move_line_ids'
+                                string='Credit Card Payments, Credits'
+                            />
+                            <field
+                                colspan="4"
+                                mode="tree"
+                                name="debit_move_line_ids"
+                                nolabel="1"
+                                widget="one2many_list"
+                                height="300"
+                            >
+                                <form string="Credit Card Payments, Credits">
+                                    <field name="cleared_cc_account" />
+                                    <field name="date" />
+                                    <field name="name" />
+                                    <field name="ref" />
+                                    <field name="partner_id" />
+                                    <field name="amount" />
+                                    <field name="amountcur" />
+                                    <field name="currency_id" />
+                                    <field name="research_required" />
+                                    <field name="from_filter" invisible="1" />
+                                </form>
+                                <tree
+                                    string="Credit Card Payments, Credits"
+                                    editable="top"
+                                    mute_additem="draft,to_be_reviewed,done, cancel"
+                                >
+                                    <field name="cleared_cc_account" />
+                                    <field name="date" />
+                                    <field name="name" />
+                                    <field name="ref" />
+                                    <field name="partner_id" />
+                                    <field name="amount" />
+                                    <field name="amountcur" />
+                                    <field name="currency_id" />
+                                    <field name="research_required" />
+                                    <field name="move_line_id" />
+                                    <field name="from_filter" invisible="1" />
+                                </tree>
+                            </field>
+                            <label
+                                for='credit_move_line_ids'
+                                string='Credit Card Charges, Interest, Penalties'
+                            />
+                            <field
+                                colspan="4"
+                                mode="tree"
+                                name="credit_move_line_ids"
+                                nolabel="1"
+                                widget="one2many_list"
+                                height="300"
+                            >
+                                <form
+                                    string="Credit Card Charges, Interest, Penalties"
+                                >
+                                    <field name="cleared_cc_account" />
+                                    <field name="date" />
+                                    <field name="name" />
+                                    <field name="ref" />
+                                    <field name="partner_id" />
+                                    <field name="amount" />
+                                    <field name="amountcur" />
+                                    <field name="currency_id" />
+                                    <field name="research_required" />
+                                    <field name="from_filter" invisible="1" />
+                                </form>
+                                <tree
+                                    string="Credit Card Charges, Interest, Penalties"
+                                    editable="top"
+                                    mute_additem="draft,to_be_reviewed,done, cancel"
+                                >
+                                    <field name="cleared_cc_account" />
+                                    <field name="date" />
+                                    <field name="name" />
+                                    <field name="ref" />
+                                    <field name="partner_id" />
+                                    <field name="amount" />
+                                    <field name="amountcur" />
+                                    <field name="currency_id" />
+                                    <field name="research_required" />
+                                    <field name="move_line_id" />
+                                    <field name="from_filter" invisible="1" />
+                                </tree>
+                            </field>
+                        </page>
+                        <page string="Totals - Cleared and Uncleared">
+                            <group
+                                col="2"
+                                colspan="1"
+                                groups="osi_credit_card_reconciliation.group_cc_stmt_verifier"
+                            >
+                                <button
+                                    name="action_select_all"
+                                    class="oe_highlight"
+                                    confirm="Current edits in statement will be lost. Do you want to select all?"
+                                    type="object"
+                                    states="draft,to_be_reviewed"
+                                    string="Select All"
+                                />
+                                <button
+                                    name="action_unselect_all"
+                                    class="oe_highlight"
+                                    confirm="Current edits in statement will be lost. Do you want to unselect all?"
+                                    type="object"
+                                    states="draft,to_be_reviewed"
+                                    string="Unselect All"
+                                />
+                            </group>
+                            <newline />
+                            <separator
+                                string="Totals - Cleared and Uncleared"
+                                colspan="2"
+                            />
+                            <group name="totals" col="4" colspan="4">
+
+                                <group name="total1" col="2" colspan="2">
+                                    <field name="sum_of_debits_lines" />
+                                    <field name="sum_of_debits" />
+                                    <field
+                                        name="sum_of_debits_cur"
+                                        attrs="{'invisible':[('sum_of_debits_cur','=', 0.0)]}"
+                                    />
+                                    <field name="sum_of_credits_lines" />
+                                    <field name="sum_of_credits" />
+                                    <field
+                                        name="sum_of_credits_cur"
+                                        attrs="{'invisible':[('sum_of_credits_cur','=', 0.0)]}"
+                                    />
+                                </group>
+                                <group name="total2" col="2" colspan="2">
+                                    <field name="sum_of_udebits_lines" />
+                                    <field name="sum_of_udebits" />
+                                    <field
+                                        name="sum_of_udebits_cur"
+                                        attrs="{'invisible':[('sum_of_udebits_cur','=', 0.0)]}"
+                                    />
+                                    <field name="sum_of_ucredits_lines" />
+                                    <field name="sum_of_ucredits" />
+                                    <field
+                                        name="sum_of_ucredits_cur"
+                                        attrs="{'invisible':[('sum_of_ucredits_cur','=', 0.0)]}"
+                                    />
+                                </group>
+                            </group>
+                        </page>
+                        <page string="Other Information">
+                            <separator
+                                string="Tracking Information"
+                                colspan="4"
+                            />
+                            <group colspan="2" col="2">
+                                <field
+                                    name="verified_by_user_id"
+                                    placeholder="Verified By"
+                                />
+                            </group>
+                            <group colspan="2" col="2">
+                                <field
+                                    name="verified_date"
+                                    placeholder="Verification Date"
+                                />
+                            </group>
+                        </page>
+                        <page string="Notes">
+                            <field
+                                name="notes"
+                                nolabel="1"
+                                placeholder="Notes"
+                            />
+                        </page>
+                    </notebook>
+                </sheet>
+            </form>
+        </field>
+    </record>
+
+    <record id="view_cc_rec_statement_filter" model="ir.ui.view">
+        <field name="name">cc.rec.statement.select</field>
+        <field name="model">cc.rec.statement</field>
+        <field name="arch" type="xml">
+            <search string="Search Credit Card Reconciliation Statements">
+                <filter
+                    icon="terp-document-new"
+                    string="Draft"
+                    name="draft_osi"
+                    domain="[('state','=','draft')]"
+                    help="Statements that haven't yet been confirmed"
+                />
+                <filter
+                    icon="terp-dolar"
+                    string="To be Reviewed"
+                    name="to_review_osi"
+                    domain="[('state','=','to_be_reviewed')]"
+                    help="Statements that are ready for review"
+                />
+                <filter
+                    icon="terp-check"
+                    string="Done"
+                    domain="[('state','=','done')]"
+                    name="done_osi"
+                    help="Statements that have been processed"
+                />
+                <separator orientation="vertical" />
+                <field name="name" select="1" />
+                <field name="ending_date" select="1" string="Ending Date" />
+                <field name="account_id" select="1" />
+                <field name="verified_by_user_id" select="1">
+                    <filter
+                        domain="[('verified_by_user_id','=',uid)]"
+                        name="verify_user_osi"
+                        help="Verified by me"
+                        icon="terp-personal"
+                    />
+                </field>
+                <newline />
+                <group
+                    expand="0"
+                    string="Group By..."
+                    colspan="11"
+                    col="11"
+                    groups="base.group_no_one"
+                >
+                    <filter
+                        string="Account"
+                        icon="terp-personal"
+                        name="account_osi"
+                        domain="[]"
+                        context="{'group_by':'account_id'}"
+                    />
+                    <separator orientation="vertical" />
+                    <filter
+                        string="State"
+                        icon="terp-stock_effects-object-colorize"
+                        name="state_osi"
+                        domain="[]"
+                        context="{'group_by':'state'}"
+                    />
+                </group>
+            </search>
+        </field>
+    </record>
+
+    <record id="action_cc_rec_statement" model="ir.actions.act_window">
+        <field name="name">Credit Card Statements</field>
+        <field name="res_model">cc.rec.statement</field>
+        <field name="view_mode">tree,form</field>
+        <field name="view_id" ref="view_cc_rec_statement_tree" />
+        <field name="search_view_id" ref="view_cc_rec_statement_filter" />
+    </record>
+
+    <!-- Change Reporting menu sequence from 5 to 7 -->
+    <menuitem
+        id="account.menu_finance_reports"
+        name="Reporting"
+        parent="account.menu_finance"
+        groups="account.group_account_manager"
+        sequence="7"
+    />
+
+    <!-- Credit Card menu will be display "Accounting > Credit Card" -->
+    <menuitem
+        id="menu_finance_credit_card"
+        name="Credit Card"
+        parent="account_accountant.menu_accounting"
+        groups="account.group_account_manager"
+        sequence="5"
+    />
+
+    <menuitem
+        action="action_cc_rec_statement"
+        id="cc_rec_statements_menu"
+        parent="menu_finance_credit_card"
+        groups="account.group_account_manager"
+        sequence="6"
+    />
+    <record id="act_account_move_line_to_add_cc" model="ir.actions.act_window">
+        <field name="name">Journal Items</field>
+        <field name="res_model">account.move.line</field>
+        <field
+            name="binding_model_id"
+            ref="osi_credit_card_reconciliation.model_cc_rec_statement"
+        />
+    </record>
+
+    <record id="act_supplier_payment_to_add_cc" model="ir.actions.act_window">
+        <field name="name">Supplier Payment</field>
+        <field name="res_model">account.move</field>
+        <field name="context">{'type':'payment'}</field>
+        <field
+            name="domain"
+        >[('journal_id.type', 'in', ['bank', 'cash']), ('move_type','=','receipt')]</field>
+        <field
+            name="binding_model_id"
+            ref="osi_credit_card_reconciliation.model_cc_rec_statement"
+        />
+    </record>
+
+    <record id="act_customer_payment_to_add_cc" model="ir.actions.act_window">
+        <field name="name">Customer Payment</field>
+        <field name="res_model">account.move</field>
+        <field name="context">{'type':'receipt'}</field>
+        <field
+            name="domain"
+        >[('journal_id.type', 'in', ['bank', 'cash']), ('move_type','=','receipt')]</field>
+        <field
+            name="binding_model_id"
+            ref="osi_credit_card_reconciliation.model_cc_rec_statement"
+        />
+    </record>
+</odoo>
diff --git a/osi_fifo_serialized_fix/README.rst b/osi_fifo_serialized_fix/README.rst
new file mode 100644
index 000000000..5124522c6
--- /dev/null
+++ b/osi_fifo_serialized_fix/README.rst
@@ -0,0 +1,28 @@
+.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
+   :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+   :alt: License: LGPL-3
+
+===============================
+OSI FIFO Serialized Product Fix
+===============================
+
+Properly handle Inventory Valuation
+with Serialized and Lot Tracked products
+
+Usage
+=====
+
+Properly handle Inventory Valuation
+with Serialized and Lot Tracked products
+
+Credits
+=======
+
+* Open Source Integrators <contact@opensourceintegrators.com>
+* Freni Patel <fpatel@opensourceintegrators.com>
+
+Contributors
+------------
+
+* Open Source Integrators <contact@opensourceintegrators.com>
+* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
diff --git a/osi_fifo_serialized_fix/__init__.py b/osi_fifo_serialized_fix/__init__.py
new file mode 100644
index 000000000..0650744f6
--- /dev/null
+++ b/osi_fifo_serialized_fix/__init__.py
@@ -0,0 +1,1 @@
+from . import models
diff --git a/osi_fifo_serialized_fix/__manifest__.py b/osi_fifo_serialized_fix/__manifest__.py
new file mode 100644
index 000000000..dcdc81dbf
--- /dev/null
+++ b/osi_fifo_serialized_fix/__manifest__.py
@@ -0,0 +1,17 @@
+# Copyright (C) 2021, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+{
+    "name": "OSI FIFO Serialized Product Fix",
+    "summary": """Properly handle Inventory Valuation
+     with Serialized and Lot Tracked products""",
+    "version": "14.0.0.0.1",
+    "license": "LGPL-3",
+    "author": "Open Source Integrators",
+    "website": "https://github.com/ursais/osi-addons",
+    "category": "Accounting",
+    "depends": ["stock_account"],
+    "data": ["views/stock_valuation_layer.xml"],
+    "maintainers": ["osi-scampbell"],
+    "installable": True,
+}
diff --git a/osi_fifo_serialized_fix/models/__init__.py b/osi_fifo_serialized_fix/models/__init__.py
new file mode 100644
index 000000000..24faeff31
--- /dev/null
+++ b/osi_fifo_serialized_fix/models/__init__.py
@@ -0,0 +1,6 @@
+# Copyright (C) 2021, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import stock_move
+from . import stock_quant
+from . import stock_valuation_layer
diff --git a/osi_fifo_serialized_fix/models/stock_move.py b/osi_fifo_serialized_fix/models/stock_move.py
new file mode 100644
index 000000000..ba8b84d34
--- /dev/null
+++ b/osi_fifo_serialized_fix/models/stock_move.py
@@ -0,0 +1,147 @@
+# Copyright (C) 2021, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import models
+
+
+class StockMove(models.Model):
+    _inherit = "stock.move"
+
+    def get_ji_ids(self, move, svl_ids):
+        ji_ids = self.env["account.move.line"].search(
+            [
+                ("name", "ilike", move.picking_id.name),
+                ("name", "ilike", move.product_id.name),
+            ]
+        )
+        if ji_ids:
+            if len(svl_ids) > 1:
+                final_layers = []
+                # If there are multiple layers, delete them and create correct ones
+                for layer in move.stock_valuation_layer_ids:
+                    layer.sudo().unlink()
+                for svl_id in svl_ids:
+                    val = move.product_id._prepare_out_svl_vals(
+                        svl_id[1], self.env.user.company_id
+                    )
+                    val_obj = self.env["stock.valuation.layer"].browse(svl_id[0])
+                    val["unit_cost"] = val_obj.unit_cost
+                    val["company_id"] = self.env.user.company_id.id
+                    val["lot_ids"] = [(6, 0, svl_id[2])]
+                    val["account_move_id"] = ji_ids[0].move_id.id
+                    # The qty of serial products is always 1, lots could be > 1
+                    if svl_id[3].product_id.tracking == "lot":
+                        val["quantity"] = svl_id[3] * -1
+                    val["value"] = val_obj.unit_cost * val["quantity"]
+                    final_layers.append(val)
+                final_layers = self.env["stock.valuation.layer"].create(final_layers)
+                move.write({"stock_valuation_layer_ids": [(6, 0, final_layers.ids)]})
+                ji_ids[0].move_id.button_draft()
+                ji_val = 0
+                for sv_id in move.stock_valuation_layer_ids:
+                    if sv_id.product_id == ji_ids[0].product_id:
+                        ji_val += sv_id.value * -1
+                # The Valuation Layers have been made, now edit the STJ Entries
+                for ji_id in ji_ids:
+                    if ji_id.credit != 0:
+                        ji_id.with_context(check_move_validity=False).write(
+                            {"credit": ji_val}
+                        )
+                    else:
+                        ji_id.with_context(check_move_validity=False).write(
+                            {"debit": ji_val}
+                        )
+                ji_ids[0].move_id.action_post()
+            else:
+                # Only 1 Valuation Layer, we can just change values
+                if len(move.stock_valuation_layer_ids.ids) > 1:
+                    svl = self.env["stock.valuation.layer"].browse(svl_ids[0][0])
+                    val = move.stock_valuation_layer_ids[0]
+                    val.unit_cost = -1 * svl.unit_cost
+                    for layer in move.stock_valuation_layer_ids:
+                        layer.sudo().unlink()
+                    move.write({"stock_valuation_layer_ids": [6, 0, val.id]})
+                else:
+                    svl = self.env["stock.valuation.layer"].browse(svl_ids[0][0])
+                    move.stock_valuation_layer_ids.lot_ids = [(6, 0, svl_ids[0][2])]
+                    move.stock_valuation_layer_ids.unit_cost = svl.unit_cost
+                    move.stock_valuation_layer_ids.value = (
+                        move.stock_valuation_layer_ids.quantity
+                        * move.stock_valuation_layer_ids.unit_cost
+                    )
+                ji_ids[0].move_id.button_draft()
+                # The Valuation Layer has been changed,
+                # now we have to edit the STJ Entry
+                for ji_id in ji_ids:
+                    amount = (
+                        svl.unit_cost
+                        * move.stock_valuation_layer_ids.stock_move_id.product_uom_qty
+                    )
+                    if ji_id.credit != 0:
+                        ji_id.with_context(check_move_validity=False).write(
+                            {"credit": amount}
+                        )
+                    else:
+                        ji_id.with_context(check_move_validity=False).write(
+                            {"debit": amount}
+                        )
+                ji_ids[0].move_id.action_post()
+
+    def get_svl_ids(self, move):
+        svl_ids = []
+        # We need to get all of the valuation layers associated with this product
+        test_vals = self.env["stock.valuation.layer"].search(
+            [("product_id", "=", move.product_id.id)]
+        )
+        for line_id in move.move_line_ids:
+            for valuation in test_vals:
+                # Filter so we only have the Layers we got from Incoming Moves
+                if line_id.lot_id in valuation.lot_ids and valuation.value > 0:
+                    if not self.check_found_vals(valuation.id, svl_ids):
+                        svl_ids.append(
+                            (
+                                valuation.id,
+                                1,
+                                [line_id.lot_id.id],
+                                line_id.qty_done,
+                            )
+                        )
+                        break
+                    else:
+                        self.increment_qty(valuation.id, svl_ids, line_id.lot_id.id)
+        self.get_ji_ids(move, svl_ids)
+
+    def _action_done(self, cancel_backorder=False):
+        res = super()._action_done(cancel_backorder)
+        for move in res:
+            # Only run code on outgoing moves with serial or lot products
+            if (
+                move.product_id.tracking in ["serial", "lot"]
+                and move.picking_id.picking_type_id.code == "outgoing"
+            ):
+                self.get_svl_ids(move)
+        return res
+
+    def increment_qty(self, value_id, svl_ids, lot_id):
+        index = 0
+        for svl_id in svl_ids:
+            if svl_id[0] == value_id:
+                if lot_id not in svl_id[2]:
+                    svl_id[2].append(lot_id)
+                svl_ids[index] = (svl_id[0], svl_id[1] + 1, svl_id[2])
+            index += 1
+
+    def check_found_vals(self, value_id, svl_ids):
+        for svl_id in svl_ids:
+            if value_id == svl_id[0]:
+                return True
+        return False
+
+    # Tag Incoming Valuation Layers with their lot_ids
+    def _create_in_svl(self, forced_quantity=None):
+        res = super()._create_in_svl(forced_quantity)
+        for move in self:
+            for layer in res:
+                if layer.stock_move_id.id == move.id:
+                    layer.lot_ids = [(6, 0, move.lot_ids.ids)]
+        return res
diff --git a/osi_fifo_serialized_fix/models/stock_quant.py b/osi_fifo_serialized_fix/models/stock_quant.py
new file mode 100644
index 000000000..5695265db
--- /dev/null
+++ b/osi_fifo_serialized_fix/models/stock_quant.py
@@ -0,0 +1,30 @@
+# Copyright (C) 2021, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import api, models
+
+
+class StockQuant(models.Model):
+    _inherit = "stock.quant"
+
+    # Extend method in stock_account/models/stock_quant.py
+    # Change computed value for fifo stock.quant
+    @api.depends("company_id", "location_id", "owner_id", "product_id", "quantity")
+    def _compute_value(self):
+        res = super()._compute_value()
+        for quant in self:
+            if quant.product_id.cost_method == "fifo":
+                svl_ids = self.env["stock.valuation.layer"].search(
+                    [("product_id", "=", quant.product_id.id), ("value", ">", 0)]
+                )
+                for svl_id in svl_ids:
+                    if quant.lot_id in svl_id.lot_ids:
+                        if quant.product_id.tracking == "lot":
+                            quant.value = svl_id.value / svl_id.quantity
+                        elif quant.product_id.tracking == "serial":
+                            quant.value = (
+                                svl_id.value
+                                / svl_id.quantity
+                                * quant.inventory_quantity
+                            )
+        return res
diff --git a/osi_fifo_serialized_fix/models/stock_valuation_layer.py b/osi_fifo_serialized_fix/models/stock_valuation_layer.py
new file mode 100644
index 000000000..a0ea8b94c
--- /dev/null
+++ b/osi_fifo_serialized_fix/models/stock_valuation_layer.py
@@ -0,0 +1,10 @@
+# Copyright (C) 2021, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import fields, models
+
+
+class StockValuationLayer(models.Model):
+    _inherit = "stock.valuation.layer"
+
+    lot_ids = fields.Many2many("stock.production.lot", string="Lot ID's", readonly=True)
diff --git a/osi_fifo_serialized_fix/views/stock_valuation_layer.xml b/osi_fifo_serialized_fix/views/stock_valuation_layer.xml
new file mode 100644
index 000000000..224cb0303
--- /dev/null
+++ b/osi_fifo_serialized_fix/views/stock_valuation_layer.xml
@@ -0,0 +1,15 @@
+<odoo>
+    <record id="inventory_valuation_lot_ids" model="ir.ui.view">
+        <field name="name">inventory.valuation.lot.ids</field>
+        <field name="model">stock.valuation.layer</field>
+        <field
+            name="inherit_id"
+            ref="stock_account.stock_valuation_layer_form"
+        />
+        <field name="arch" type="xml">
+            <field name="stock_move_id" position="after">
+                <field name="lot_ids" widget="many2many_tags" />
+            </field>
+        </field>
+    </record>
+</odoo>
diff --git a/osi_helpdesk_stock/README.rst b/osi_helpdesk_stock/README.rst
new file mode 100644
index 000000000..3caf2872f
--- /dev/null
+++ b/osi_helpdesk_stock/README.rst
@@ -0,0 +1,49 @@
+.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
+   :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+   :alt: License: LGPL-3
+
+================
+Helpdesk - Stock
+================
+
+Odoo Helpdesk App allows to manage support tickets or customer service requests.
+The app does not support the logistic side of those activities: Sometimes,
+helpdesk users need to ship materials to the customer or to the serviced
+location to solve a ticket.
+
+This module allows the Helpdesk user to request materials to be shipped to the
+customer location or serviced location and follow up with the Inventory team.
+
+Usage
+=====
+
+* Create a helpdesk ticket with a customer
+* In Materials, add products with quantity
+* Click on Confirm
+
+  * The delivery order is created
+  * The transfer is set on the ticket
+  * The state is updated to Confirmed
+  * The product, description and quantity requested cannot be changed
+
+* Transfer partially the delivery order
+
+  * The state is updated to Partially Shipped
+
+* Transfer completely the delivery order
+
+  * The state is updated to Done
+
+Credits
+=======
+
+* Michael Allen <mallen@opensourceintegrators.com>
+* Freni Patel <fpatel@opensourceintegrators.com>
+
+
+Contributors
+------------
+
+* Open Source Integrators <http://www.opensourceintegrators.com>
+* Brian McMaster <brian@mcmpest.com>
+* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
diff --git a/osi_helpdesk_stock/__init__.py b/osi_helpdesk_stock/__init__.py
new file mode 100644
index 000000000..7d768b54b
--- /dev/null
+++ b/osi_helpdesk_stock/__init__.py
@@ -0,0 +1,3 @@
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import models
diff --git a/osi_helpdesk_stock/__manifest__.py b/osi_helpdesk_stock/__manifest__.py
new file mode 100644
index 000000000..ef5e496f0
--- /dev/null
+++ b/osi_helpdesk_stock/__manifest__.py
@@ -0,0 +1,30 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+{
+    "name": "Helpdesk - Stock",
+    "summary": "Inventory and Stock Operations for Helpdesk Tickets",
+    "version": "14.0.1.0.0",
+    "category": "Helpdesk",
+    "author": "Open Source Integrators",
+    "website": "https://github.com/ursais/osi-addons",
+    "depends": [
+        "helpdesk_timesheet",
+        "stock_request_direction",
+        "stock_request_picking_type",
+    ],
+    "data": [
+        "security/ir.model.access.csv",
+        "views/helpdesk_ticket.xml",
+        "views/menu.xml",
+        "views/stock_request.xml",
+        "views/stock_request_order.xml",
+    ],
+    "installable": True,
+    "license": "LGPL-3",
+    "maintainers": [
+        "osimallen",
+        "wolfhall",
+        "max3903",
+    ],
+}
diff --git a/osi_helpdesk_stock/models/__init__.py b/osi_helpdesk_stock/models/__init__.py
new file mode 100644
index 000000000..ff7a08310
--- /dev/null
+++ b/osi_helpdesk_stock/models/__init__.py
@@ -0,0 +1,8 @@
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import (
+    helpdesk_ticket,
+    stock,
+    stock_request,
+    stock_request_order,
+)
diff --git a/osi_helpdesk_stock/models/helpdesk_ticket.py b/osi_helpdesk_stock/models/helpdesk_ticket.py
new file mode 100644
index 000000000..345cbf37b
--- /dev/null
+++ b/osi_helpdesk_stock/models/helpdesk_ticket.py
@@ -0,0 +1,111 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import _, api, fields, models
+from odoo.exceptions import UserError
+
+REQUEST_STATES = [
+    ("draft", "Draft"),
+    ("submitted", "Submitted"),
+    ("open", "In progress"),
+    ("done", "Done"),
+    ("cancel", "Cancelled"),
+]
+
+
+class HelpdeskTicket(models.Model):
+    _inherit = "helpdesk.ticket"
+
+    @api.model
+    def _default_warehouse_id(self):
+        company = self.env.user.company_id.id
+        warehouse_ids = self.env["stock.warehouse"].search(
+            [("company_id", "=", company)], limit=1
+        )
+        return warehouse_ids
+
+    inventory_location_id = fields.Many2one("stock.location", "Destination Location")
+    stock_request_ids = fields.One2many(
+        "stock.request", "helpdesk_ticket_id", string="Materials"
+    )
+    picking_ids = fields.One2many(
+        "stock.picking", "helpdesk_ticket_id", string="Transfers"
+    )
+    delivery_count = fields.Integer(
+        string="Delivery Orders", compute="_compute_picking_ids"
+    )
+    procurement_group_id = fields.Many2one(
+        "procurement.group", "Procurement Group", copy=False
+    )
+    warehouse_id = fields.Many2one(
+        "stock.warehouse",
+        string="Warehouse",
+        required=True,
+        default=_default_warehouse_id,
+        help="Warehouse used to ship the materials",
+    )
+    request_stage = fields.Selection(
+        REQUEST_STATES,
+        string="Request State",
+        default="draft",
+        required=True,
+        readonly=True,
+        store=True,
+    )
+
+    @api.depends("picking_ids")
+    def _compute_picking_ids(self):
+        for ticket in self:
+            ticket.delivery_count = len(ticket.picking_ids)
+
+    def action_request_submit(self):
+        for rec in self:
+            if not rec.stock_request_ids:
+                raise UserError(_("Please create a stock request."))
+            for line in rec.stock_request_ids:
+                if line.state == "draft":
+                    if line.order_id:
+                        line.order_id.action_confirm()
+                    else:
+                        line.action_confirm()
+            rec.request_stage = "submitted"
+
+    def action_request_cancel(self):
+        for rec in self:
+            if not rec.stock_request_ids:
+                raise UserError(_("Please select a Materials."))
+            for line in rec.stock_request_ids:
+                if line.state in ("draft", "submitted"):
+                    if line.order_id:
+                        line.order_id.action_cancel()
+                    else:
+                        line.action_cancel()
+            rec.request_stage = "cancel"
+
+    def action_request_draft(self):
+        for rec in self:
+            if not rec.stock_request_ids:
+                raise UserError(_("Please select a Materials."))
+            for line in rec.stock_request_ids:
+                if line.state == "cancel":
+                    if line.order_id:
+                        line.order_id.action_draft()
+                    else:
+                        line.action_draft()
+            rec.request_stage = "draft"
+
+    def action_view_delivery(self):
+        """
+        This function returns an action that display existing delivery orders
+        of given helpdesk ticket ids. It can either be a in a list or in a form
+        view, if there is only one delivery order to show.
+        """
+        action = self.env.ref("stock.action_picking_tree_all").read()[0]
+
+        pickings = self.mapped("picking_ids")
+        if len(pickings) > 1:
+            action["domain"] = [("id", "in", pickings.ids)]
+        elif pickings:
+            action["views"] = [(self.env.ref("stock.view_picking_form").id, "form")]
+            action["res_id"] = pickings.id
+        return action
diff --git a/osi_helpdesk_stock/models/stock.py b/osi_helpdesk_stock/models/stock.py
new file mode 100644
index 000000000..2b55c9ceb
--- /dev/null
+++ b/osi_helpdesk_stock/models/stock.py
@@ -0,0 +1,32 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import fields, models
+
+
+class StockMoveLine(models.Model):
+    _inherit = "stock.move.line"
+
+    def _action_done(self):
+        res = super(StockMoveLine, self)._action_done()
+        for rec in self:
+            if rec.exists():
+                for all_rec in rec.move_id.allocation_ids:
+                    request = all_rec.stock_request_id
+                    if request.state == "done" and request.helpdesk_ticket_id:
+                        request.helpdesk_ticket_id.request_stage = "done"
+        return res
+
+
+class ProcurementGroup(models.Model):
+    _inherit = "procurement.group"
+
+    helpdesk_ticket_id = fields.Many2one("helpdesk.ticket", "Helpdesk Ticket")
+
+
+class StockPicking(models.Model):
+    _inherit = "stock.picking"
+
+    helpdesk_ticket_id = fields.Many2one(
+        related="group_id.helpdesk_ticket_id", string="Helpdesk Ticket", store=True
+    )
diff --git a/osi_helpdesk_stock/models/stock_request.py b/osi_helpdesk_stock/models/stock_request.py
new file mode 100644
index 000000000..8b6a4ee19
--- /dev/null
+++ b/osi_helpdesk_stock/models/stock_request.py
@@ -0,0 +1,143 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from odoo import _, api, fields, models
+from odoo.exceptions import UserError
+
+
+class StockRequest(models.Model):
+    _inherit = "stock.request"
+
+    helpdesk_ticket_id = fields.Many2one(
+        "helpdesk.ticket", string="Ticket", ondelete="cascade", index=True, copy=False
+    )
+
+    @api.onchange("direction", "helpdesk_ticket_id")
+    def _onchange_location_id(self):
+        super()._onchange_location_id()
+        if self.helpdesk_ticket_id:
+            if self.direction == "outbound":
+                # Inventory location of the ticket
+                self.location_id = self.helpdesk_ticket_id.inventory_location_id.id
+            else:
+                # Otherwise the stock location of the warehouse
+                self.location_id = self.helpdesk_ticket_id.warehouse_id.lot_stock_id.id
+
+    def prepare_order_values(self, vals):
+        picking_type_id = self.env["stock.picking.type"].search(
+            [
+                ("code", "=", "stock_request_order"),
+                ("warehouse_id", "=", vals["warehouse_id"]),
+            ],
+            limit=1,
+        )
+        if not picking_type_id:
+            picking_type_id = self.env["stock.picking.type"].search(
+                [("code", "=", "stock_request_order")], limit=1
+            )
+        helpdesk_ticket = self.env["helpdesk.ticket"].browse(vals["helpdesk_ticket_id"])
+        # super call the fieldservice_stock_request module method
+        res = super().prepare_order_values(vals)
+        if helpdesk_ticket:
+            res.update(
+                {
+                    "picking_type_id": picking_type_id.id,
+                    "location_id": helpdesk_ticket.warehouse_id.lot_stock_id.id,
+                }
+            )
+        if "helpdesk_ticket_id" in vals and vals["helpdesk_ticket_id"]:
+            res.update({"helpdesk_ticket_id": vals["helpdesk_ticket_id"]})
+        return res
+
+    @api.model
+    def create(self, vals):
+        if (
+            "helpdesk_ticket_id" in vals
+            and vals.get("helpdesk_ticket_id", False)
+            and not vals.get("order_id", False)
+        ):
+            ticket = self.env["helpdesk.ticket"].browse(vals["helpdesk_ticket_id"])
+            ticket.request_stage = "draft"
+            vals["warehouse_id"] = ticket.warehouse_id.id
+            vals["location_id"] = (
+                ticket.warehouse_id.lot_stock_id.id or ticket.inventory_location_id.id
+            )
+            picking_type_id = self.env["stock.picking.type"].search(
+                [
+                    ("code", "=", "stock_request_order"),
+                    ("warehouse_id", "=", vals["warehouse_id"]),
+                ],
+                limit=1,
+            )
+            helpdesk_ticket = self.env["stock.request.order"].search(
+                [
+                    ("helpdesk_ticket_id", "=", vals["helpdesk_ticket_id"]),
+                    ("warehouse_id", "=", vals["warehouse_id"]),
+                    ("picking_type_id", "=", picking_type_id.id),
+                    ("direction", "=", vals["direction"]),
+                    ("state", "=", "draft"),
+                ],
+                order="id asc",
+            )
+
+            # User created a new SRO Manually
+            if len(helpdesk_ticket) > 1:
+                raise UserError(
+                    _(
+                        "There is already a Stock Request Order \
+                                  with the same Helpdesk Ticket and \
+                                  Warehouse that is in Draft state. Please \
+                                  add this Stock Request there. \
+                                  (%s)"
+                    )
+                    % helpdesk_ticket[0].name
+                )
+            # Made from an HT for the first time, create the SRO here
+            elif not helpdesk_ticket and vals.get("helpdesk_ticket_id"):
+                values = self.prepare_order_values(vals)
+                vals["order_id"] = self.env["stock.request.order"].create(values).id
+            # There is an SRO made from HT, assign here
+            elif len(helpdesk_ticket) == 1 and vals.get("helpdesk_ticket_id"):
+                vals["expected_date"] = helpdesk_ticket.expected_date
+                vals["order_id"] = helpdesk_ticket.id
+        return super().create(vals)
+
+    def _prepare_procurement_group_values(self):
+        if self.helpdesk_ticket_id:
+            ticket = self.env["helpdesk.ticket"].browse(self.helpdesk_ticket_id.id)
+            return {
+                "name": ticket.name,
+                "helpdesk_ticket_id": ticket.id,
+                "move_type": "direct",
+            }
+        else:
+            return {}
+
+    def _prepare_procurement_values(self, group_id=False):
+        res = super()._prepare_procurement_values(group_id=group_id)
+        res.update(
+            {
+                "helpdesk_ticket_id": self.helpdesk_ticket_id.id,
+                "partner_id": self.helpdesk_ticket_id.partner_id.id,
+            }
+        )
+        return res
+
+    def _action_confirm(self):
+        for req in self:
+            if (not req.procurement_group_id) and req.helpdesk_ticket_id:
+                ticket = self.env["helpdesk.ticket"].browse(req.helpdesk_ticket_id.id)
+                group = self.env["procurement.group"].search(
+                    [("helpdesk_ticket_id", "=", ticket.id)]
+                )
+                if not group:
+                    values = req._prepare_procurement_group_values()
+                    group = self.env["procurement.group"].create(values)
+                if req.order_id:
+                    req.order_id.procurement_group_id = group.id
+                req.procurement_group_id = group.id
+                res = super(StockRequest, req)._action_confirm()
+                ticket.request_stage = "open"
+            else:
+                res = super(StockRequest, req)._action_confirm()
+        return res
diff --git a/osi_helpdesk_stock/models/stock_request_order.py b/osi_helpdesk_stock/models/stock_request_order.py
new file mode 100644
index 000000000..aee0c2181
--- /dev/null
+++ b/osi_helpdesk_stock/models/stock_request_order.py
@@ -0,0 +1,54 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from odoo import api, fields, models
+
+
+class StockRequestOrder(models.Model):
+    _inherit = "stock.request.order"
+
+    helpdesk_ticket_id = fields.Many2one(
+        "helpdesk.ticket", string="Ticket", ondelete="cascade", index=True, copy=False
+    )
+
+    @api.onchange("warehouse_id", "direction", "helpdesk_ticket_id")
+    def _onchange_location_id(self):
+        super()._onchange_location_id()
+        if self.helpdesk_ticket_id:
+            if self.direction == "outbound":
+                # Inventory location of the ticket
+                self.location_id = self.helpdesk_ticket_id.inventory_location_id.id
+            else:
+                # Otherwise the stock location of the warehouse
+                self.location_id = self.helpdesk_ticket_id.warehouse_id.lot_stock_id.id
+        self.change_childs()
+
+    def change_childs(self):
+        super().change_childs()
+        if not self._context.get("no_change_childs", False):
+            for line in self.stock_request_ids:
+                line.helpdesk_ticket_id = self.helpdesk_ticket_id.id
+
+    def _prepare_procurement_group_values(self):
+        if self.helpdesk_ticket_id:
+            ticket = self.env["helpdesk.ticket"].browse(self.helpdesk_ticket_id.id)
+            return {
+                "name": ("#" + str(ticket.id)),
+                "helpdesk_ticket_id": ticket.id,
+                "move_type": "direct",
+            }
+        else:
+            return {}
+
+    def action_confirm(self):
+        if self.helpdesk_ticket_id and not self.procurement_group_id:
+            ticket = self.env["helpdesk.ticket"].browse(self.helpdesk_ticket_id.id)
+            group = self.env["procurement.group"].search(
+                [("helpdesk_ticket_id", "=", ticket.id)]
+            )
+            if not group:
+                values = self._prepare_procurement_group_values()
+                group = self.env["procurement.group"].create(values)
+            self.procurement_group_id = group.id
+            self.change_childs()
+        return super().action_confirm()
diff --git a/osi_helpdesk_stock/security/ir.model.access.csv b/osi_helpdesk_stock/security/ir.model.access.csv
new file mode 100644
index 000000000..93391070e
--- /dev/null
+++ b/osi_helpdesk_stock/security/ir.model.access.csv
@@ -0,0 +1,3 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_stock_request_helpdesk_user,stock.request.user,stock_request.model_stock_request,helpdesk.group_helpdesk_user,1,1,1,1
+access_stock_request_helpdesk_manager,stock.request.manager,stock_request.model_stock_request,helpdesk.group_helpdesk_manager,1,1,1,1
diff --git a/osi_helpdesk_stock/static/description/icon.png b/osi_helpdesk_stock/static/description/icon.png
new file mode 100644
index 000000000..84791119f
Binary files /dev/null and b/osi_helpdesk_stock/static/description/icon.png differ
diff --git a/osi_helpdesk_stock/views/helpdesk_ticket.xml b/osi_helpdesk_stock/views/helpdesk_ticket.xml
new file mode 100644
index 000000000..55fbf6394
--- /dev/null
+++ b/osi_helpdesk_stock/views/helpdesk_ticket.xml
@@ -0,0 +1,100 @@
+<odoo>
+
+    <record id="view_helpdesk_ticket_form_inherit_stock" model="ir.ui.view">
+        <field name="name">helpdesk.ticket.form.stock</field>
+        <field name="model">helpdesk.ticket</field>
+        <field
+            name="inherit_id"
+            ref="helpdesk_timesheet.helpdesk_ticket_view_form_inherit_helpdesk_timesheet"
+        />
+        <field name="arch" type="xml">
+            <div class="oe_button_box" position="inside">
+                <field name="picking_ids" invisible="1" />
+                <button
+                    type="object"
+                    name="action_view_delivery"
+                    class="oe_stat_button"
+                    icon="fa-truck"
+                    attrs="{'invisible': [('delivery_count', '=', 0)]}"
+                    groups="base.group_user"
+                >
+                    <field
+                        name="delivery_count"
+                        widget="statinfo"
+                        string="Delivery"
+                    />
+                </button>
+            </div>
+            <xpath expr="//notebook/page[1]" position="after">
+                <page string="Inventory">
+                    <header>
+                        <button
+                            name="action_request_submit"
+                            string="Submit"
+                            type="object"
+                            class="oe_highlight"
+                            attrs="{'invisible': [('request_stage', 'not in', ['draft'])]}"
+                        />
+                        <button
+                            name="action_request_draft"
+                            string="Set to Draft"
+                            type="object"
+                            attrs="{'invisible': [('request_stage', 'not in', ['cancel'])]}"
+                        />
+                        <button
+                            name="action_request_cancel"
+                            string="Cancel"
+                            type="object"
+                            attrs="{'invisible': [('request_stage', 'not in', ['draft', 'submitted'])]}"
+                        />
+                        <field name='request_stage' widget="statusbar" />
+                    </header>
+                    <group groups="stock.group_stock_user">
+                        <group id="stock-left">
+                            <field
+                                name="warehouse_id"
+                                groups="stock.group_stock_multi_warehouses"
+                            />
+                            <field
+                                name="inventory_location_id"
+                                domain="[('usage', 'in', ['internal', 'supplier', 'customer'])]"
+                            />
+                        </group>
+                        <group id="stock-right" />
+                    </group>
+                    <field name="stock_request_ids" nolabel="1">
+                        <tree editable="bottom">
+                            <field name="name" readonly="1" />
+                            <field name="product_id" />
+                            <field name="order_id" />
+                            <field
+                                name="product_uom_id"
+                                options="{'no_open': True, 'no_create': True}"
+                                groups="uom.group_uom"
+                            />
+                            <field name="direction" required="1" />
+                            <field
+                                name="route_id"
+                                options="{'no_create': True}"
+                                groups="stock.group_stock_multi_locations"
+                                invisible="1"
+                            />
+                            <field name="route_ids" invisible="1" />
+                            <field name="product_uom_qty" />
+                            <field name="qty_in_progress" />
+                            <field name="qty_done" />
+                            <field name="expected_date" />
+                            <field name="picking_policy" invisible="1" />
+                            <field name="warehouse_id" invisible="1" />
+                            <field name="location_id" invisible="1" />
+                            <field name="procurement_group_id" invisible="1" />
+                            <field name="company_id" invisible="1" />
+                            <field name="state" />
+                        </tree>
+                    </field>
+                </page>
+            </xpath>
+        </field>
+    </record>
+
+</odoo>
diff --git a/osi_helpdesk_stock/views/menu.xml b/osi_helpdesk_stock/views/menu.xml
new file mode 100644
index 000000000..543b6b364
--- /dev/null
+++ b/osi_helpdesk_stock/views/menu.xml
@@ -0,0 +1,34 @@
+<odoo>
+
+    <menuitem
+        id="menu_helpdesk_data"
+        name="Master Data"
+        parent="helpdesk.menu_helpdesk_root"
+        sequence="15"
+    />
+
+    <menuitem
+        id="menu_helpdesk_product"
+        name="Products"
+        action="stock.product_template_action_product"
+        parent="menu_helpdesk_data"
+        sequence="50"
+    />
+
+    <menuitem
+        id="menu_helpdesk_reporting_inventory"
+        name="Inventory"
+        action="stock.action_view_quants"
+        parent="helpdesk.helpdesk_ticket_report_menu_main"
+        sequence="50"
+    />
+
+    <menuitem
+        id="menu_helpdesk_stock_request"
+        name="Stock Requests"
+        action="stock_request.action_stock_request_form"
+        parent="menu_helpdesk_data"
+        sequence="90"
+    />
+
+</odoo>
diff --git a/osi_helpdesk_stock/views/stock_request.xml b/osi_helpdesk_stock/views/stock_request.xml
new file mode 100644
index 000000000..36542b467
--- /dev/null
+++ b/osi_helpdesk_stock/views/stock_request.xml
@@ -0,0 +1,31 @@
+<odoo>
+
+    <record id="stock_request_helpdesk_ticket" model="ir.ui.view">
+        <field name="model">stock.request</field>
+        <field name="inherit_id" ref="stock_request.view_stock_request_form" />
+        <field name="arch" type="xml">
+            <field name="picking_policy" position="after">
+                <field name="helpdesk_ticket_id" />
+            </field>
+        </field>
+    </record>
+
+    <record id="stock_request_helpdesk_ticket_search" model="ir.ui.view">
+        <field name="model">stock.request</field>
+        <field name="inherit_id" ref="stock_request.stock_request_search" />
+        <field name="arch" type="xml">
+            <field name="name" position="after">
+                <field name="helpdesk_ticket_id" />
+            </field>
+            <filter name="location" position="after">
+                <filter
+                    string="Helpdesk Ticket"
+                    name="helpdesk_ticket_id"
+                    domain="[]"
+                    context="{'group_by': 'helpdesk_ticket_id'}"
+                />
+            </filter>
+        </field>
+    </record>
+
+</odoo>
diff --git a/osi_helpdesk_stock/views/stock_request_order.xml b/osi_helpdesk_stock/views/stock_request_order.xml
new file mode 100644
index 000000000..55286ecd2
--- /dev/null
+++ b/osi_helpdesk_stock/views/stock_request_order.xml
@@ -0,0 +1,65 @@
+<odoo>
+
+    <record id="stock_request_order_helpdesk_ticket_form" model="ir.ui.view">
+        <field name="model">stock.request.order</field>
+        <field name="inherit_id" ref="stock_request.stock_request_order_form" />
+        <field name="arch" type="xml">
+            <field name="picking_policy" position="after">
+                <field name="helpdesk_ticket_id" />
+            </field>
+            <field name="stock_request_ids" position="attributes">
+                <attribute name="context">{
+                    'default_helpdesk_ticket_id': helpdesk_ticket_id,
+                    'default_expected_date': expected_date,
+                    'default_picking_policy': picking_policy,
+                    'default_warehouse_id': warehouse_id,
+                    'default_direction': direction,
+                    'default_location_id': location_id,
+                    'default_procurement_group_id': procurement_group_id,
+                    'default_company_id': company_id,
+                    'default_state': state}</attribute>
+            </field>
+            <xpath
+                expr="//field[@name='stock_request_ids']/tree/field[@name='route_id']"
+                position="after"
+            >
+                <field name="helpdesk_ticket_id" invisible="1" />
+            </xpath>
+        </field>
+    </record>
+
+    <record id="stock_request_order_helpdesk_ticket_tree" model="ir.ui.view">
+        <field name="model">stock.request.order</field>
+        <field name="inherit_id" ref="stock_request.stock_request_order_tree" />
+        <field name="arch" type="xml">
+            <field name="name" position="after">
+                <field name="helpdesk_ticket_id" />
+            </field>
+        </field>
+    </record>
+
+    <record id="stock_request_order_helpdesk_ticket_search" model="ir.ui.view">
+        <field name="model">stock.request.order</field>
+        <field
+            name="inherit_id"
+            ref="stock_request_picking_type.stock_request_order_search"
+        />
+        <field name="arch" type="xml">
+            <field name="name" position="after">
+                <field
+                    name="helpdesk_ticket_id"
+                    filter_domain="['|', ('helpdesk_ticket_id.name', 'ilike', self), ('helpdesk_ticket_id.id', 'ilike', self)]"
+                />
+            </field>
+            <field name="state" position="after">
+                <filter
+                    string="Helpdesk Ticket"
+                    name="helpdesk_ticket_id"
+                    domain="[]"
+                    context="{'group_by': 'helpdesk_ticket_id'}"
+                />
+            </field>
+        </field>
+    </record>
+
+</odoo>
diff --git a/osi_partner_credit_limit/README.rst b/osi_partner_credit_limit/README.rst
new file mode 100644
index 000000000..1c8801835
--- /dev/null
+++ b/osi_partner_credit_limit/README.rst
@@ -0,0 +1,53 @@
+.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
+    :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
+    :alt: License: AGPL-3
+
+========
+Overview
+========
+
+This module prevents users from shippings orders that would put customers
+above their credit limit based on open invoices.
+
+It adds a new group that allows certain users to manage credit hold of the
+customers.
+
+After this module is installed, credit limits will be verified for all
+customers.
+
+Configuration
+=============
+
+* Add users to the 'Credit Hold' group
+
+Usage
+=====
+
+* Sales Hold on Customer: Disallows new sales orders and prevents confirmation
+  of existing quotations.
+
+* Credit Hold on Customer: Allows new sales orders, confirmation of orders,
+  but prevents orders from being shipped.
+
+* Credit Limit: Maximum allowed receivable balance for a customer.
+
+* Grace period: Time allowed for the customer to make payment after the term 
+  has expired.
+
+* Credit Override: When set on sale order, allows shipment on the sale order
+  to be processed even if there is a hold on the sale order.
+
+* Credit Override requires special permission to be set on the user.
+
+Credits
+=======
+
+Contributors
+------------
+
+* OSI Dev Team <contact@opensourceintegrators.com>
+* Sandeep Mangukiya <smangukiya@opensourceintegrators.com>
+* Maxime Chambreuil <mchambreuil@opensourceintegrators.com>
+* Bhavesh Odedra <bodedra@opensourceintegrators.com>
+* Balaji Kannan <bkannan@opensourceintegrators.com>
+* Hardik Suthar <hsuthar@opensourceintegrators.com>
diff --git a/osi_partner_credit_limit/__init__.py b/osi_partner_credit_limit/__init__.py
new file mode 100644
index 000000000..74cc8d7be
--- /dev/null
+++ b/osi_partner_credit_limit/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (C) 2019 - 2021, Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from . import models
diff --git a/osi_partner_credit_limit/__manifest__.py b/osi_partner_credit_limit/__manifest__.py
new file mode 100644
index 000000000..23a84e6ad
--- /dev/null
+++ b/osi_partner_credit_limit/__manifest__.py
@@ -0,0 +1,26 @@
+# Copyright (C) 2019 - 2021, Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+{
+    "name": "OSI Partner Credit Limit",
+    "version": "14.0.1.0.0",
+    "license": "AGPL-3",
+    "author": "Open Source Integrators",
+    "category": "Sales",
+    "maintainer": "Open Source Integrators",
+    "summary": "Enforce Partner Credit Limit",
+    "website": "https://github.com/ursais/osi-addons",
+    "depends": [
+        "sale",
+        "sale_stock",
+        "stock",
+    ],
+    "data": [
+        "security/osi_partner_credit_limit.xml",
+        "views/res_partner.xml",
+        "views/sale.xml",
+        "views/stock.xml",
+    ],
+    "installable": True,
+    "maintainers": ["bodedra"],
+}
diff --git a/osi_partner_credit_limit/models/__init__.py b/osi_partner_credit_limit/models/__init__.py
new file mode 100644
index 000000000..39fa847a1
--- /dev/null
+++ b/osi_partner_credit_limit/models/__init__.py
@@ -0,0 +1,6 @@
+# Copyright (C) 2019 - 2021, Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from . import res_partner
+from . import sale_order
+from . import stock_picking
diff --git a/osi_partner_credit_limit/models/res_partner.py b/osi_partner_credit_limit/models/res_partner.py
new file mode 100644
index 000000000..fdad4b553
--- /dev/null
+++ b/osi_partner_credit_limit/models/res_partner.py
@@ -0,0 +1,104 @@
+# Copyright (C) 2019 - 2021, Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from datetime import datetime, timedelta
+
+from odoo import fields, models
+
+
+class Partner(models.Model):
+    _inherit = "res.partner"
+
+    sales_hold = fields.Boolean(
+        string="Sales Hold",
+        default=False,
+        help="If checked, new quotations cannot be confirmed",
+    )
+    credit_limit = fields.Monetary(string="Credit Limit")
+    grace_period = fields.Integer(
+        string="Grace Period",
+        help="Grace period added on top of the customer \
+        payment term "
+        "(in days)",
+    )
+    credit_hold = fields.Boolean(
+        string="Credit Hold",
+        help="Place the customer on credit hold to prevent \
+            from shipping goods",
+    )
+
+    def write(self, vals):
+        res = super(Partner, self).write(vals)
+        if "credit_limit" or "credit_hold" in vals:
+            for partner in self:
+                order_ids = self.env["sale.order"].search(
+                    [("partner_id", "=", partner.id)]
+                )
+                # only if partner is on credit hold, set sale orders on ship hold immediately
+                ship_hold = partner.credit_hold
+
+                # check for credit_limit
+                if partner.credit_limit > 0 and order_ids:
+                    if not ship_hold and not self.check_limit(order_ids[0]):
+                        ship_hold = False
+                    else:
+                        ship_hold = True
+
+                order_ids.write({"ship_hold": ship_hold})
+        return res
+
+    def check_limit(self, sale_id):
+        partner_id = sale_id.partner_id
+        # Other orders for this partner
+        order_ids = self.env["sale.order"].search(
+            [
+                ("partner_id", "=", partner_id.id),
+                ("state", "=", "sale"),
+                ("invoice_status", "!=", "invoiced"),
+            ]
+        )
+        # Open invoices (unpaid or partially paid invoices --
+        # It is already included in partner.credit
+        invoice_ids = self.env["account.move"].search(
+            [
+                ("partner_id", "=", partner_id.id),
+                # ('state', '=', 'draft'),
+                ("state", "in", ["open", "posted"]),
+                ("payment_state", "in", ["not_paid", "partial"]),
+                ("move_type", "in", ["out_invoice", "out_refund"]),
+            ]
+        )
+        # Initialize variables
+        existing_order_balance = 0.0
+        existing_invoice_balance = 0.0
+        # Confirmed orders - invoiced - draft or open / not invoiced
+        for order in order_ids:
+            existing_order_balance = existing_order_balance + order.amount_total
+        # Invoices that are open (also shows up as part of partner.
+        # Credit, so must be deducted
+        for invoice in invoice_ids:
+            if (
+                fields.Datetime.to_string(
+                    (
+                        invoice.invoice_date_due
+                        or invoice.date_invoice
+                        or invoice.create_date
+                    )
+                    + timedelta(days=partner_id.grace_period)
+                )
+            ) > fields.Datetime.to_string(datetime.now()):
+                continue
+            else:
+                existing_invoice_balance = (
+                    existing_invoice_balance + invoice.amount_residual
+                )
+        # All open sale orders + partner credit (AR balance) -
+        # Open invoices (already included in partner credit)
+        if (
+            sale_id.partner_id.credit_limit
+            and (existing_invoice_balance + existing_order_balance)
+            > sale_id.partner_id.credit_limit
+        ):
+            return True
+        else:
+            return False
diff --git a/osi_partner_credit_limit/models/sale_order.py b/osi_partner_credit_limit/models/sale_order.py
new file mode 100644
index 000000000..dcfb2ac3d
--- /dev/null
+++ b/osi_partner_credit_limit/models/sale_order.py
@@ -0,0 +1,48 @@
+# Copyright (C) 2019 - 2021, Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from odoo import _, fields, models
+from odoo.exceptions import ValidationError
+
+
+class SaleOrder(models.Model):
+    _inherit = "sale.order"
+
+    sales_hold = fields.Boolean(
+        related="partner_id.sales_hold", string="Customer Sales Hold"
+    )
+    credit_hold = fields.Boolean(
+        related="partner_id.credit_hold", string="Customer Credit Hold"
+    )
+    ship_hold = fields.Boolean(string="Delivery Hold", copy=False)
+    credit_override = fields.Boolean(
+        string="Override Hold", tracking=True, default=False
+    )
+
+    def action_confirm(self):
+        self.partner_id.check_limit(self)
+        if self.sales_hold and not self.credit_override:
+            message = _("""Cannot confirm Order! The customer is on sales hold.""")
+            # Display that the customer is on sales hold
+            raise ValidationError(message)
+        elif self.ship_hold and not self.credit_override:
+            message = _(
+                """Cannot confirm Order! The customer exceed available
+                   credit limit and is on ship hold."""
+            )
+            raise ValidationError(message)
+        else:
+            # attempt to change the state of this order to be included in \
+            #  the computation for check_limit function
+            prev_state = self.state
+            self.state = "sale"
+            if self.partner_id.check_limit(self) and not self.credit_override:
+                self.state = prev_state
+                self.ship_hold = True
+                message = _(
+                    """Cannot confirm Order!
+                        This will exceed allowed Credit Limit.
+                        To Override, check Override Sales/Credit/Delivery Hold"""
+                )
+                raise ValidationError(message)
+            return super(SaleOrder, self).action_confirm()
diff --git a/osi_partner_credit_limit/models/stock_picking.py b/osi_partner_credit_limit/models/stock_picking.py
new file mode 100644
index 000000000..b4c42d0bb
--- /dev/null
+++ b/osi_partner_credit_limit/models/stock_picking.py
@@ -0,0 +1,61 @@
+# Copyright (C) 2019 - 2021, Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from odoo import _, fields, models
+from odoo.exceptions import UserError
+
+
+class StockPicking(models.Model):
+    _inherit = "stock.picking"
+
+    def _compute_allow_transfer(self):
+        for record in self:
+
+            hold_value = False
+            record.dont_allow_transfer = False
+            # Only outgoing picking
+            if record.picking_type_code == "outgoing" and record.state not in (
+                "done",
+                "cancel",
+            ):
+                # Sales person has a hold
+                if (
+                    record.sale_id.sales_hold
+                    or record.sale_id.credit_hold
+                    or record.sale_id.ship_hold
+                ):
+                    hold_value = True
+
+                # Partner will exceed limit with current
+                # Sale order or is over-due
+                if record.sale_id.partner_id.check_limit(record.sale_id):
+                    hold_value = True
+
+                # Override applied on sale order
+                if record.sale_id.credit_override:
+                    hold_value = False
+
+                record.dont_allow_transfer = hold_value
+                record.sale_id.write({"ship_hold": hold_value})
+
+    dont_allow_transfer = fields.Boolean(
+        string="Credit Hold", compute="_compute_allow_transfer"
+    )
+
+    def button_validate(self):
+        # Only outgoing picking
+        if self.picking_type_code == "outgoing":
+            if self.dont_allow_transfer:
+                raise UserError(
+                    _(
+                        """Customer has a Credit hold.\n\nContact
+                    Sales/Accounting to verify
+                    sales hold/credit hold/overdue payments."""
+                    )
+                )
+            else:
+                return super(StockPicking, self).button_validate()
+
+        # Incoming shipments / internal transfers
+        else:
+            return super(StockPicking, self).button_validate()
diff --git a/osi_partner_credit_limit/security/osi_partner_credit_limit.xml b/osi_partner_credit_limit/security/osi_partner_credit_limit.xml
new file mode 100644
index 000000000..f20ba9764
--- /dev/null
+++ b/osi_partner_credit_limit/security/osi_partner_credit_limit.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<odoo noupdate="1">
+
+    <record id="group_credit_hold" model="res.groups">
+        <field name="name">Credit Hold</field>
+        <field
+            name="comment"
+        >Members of this group can manage the credit hold status of a customer.</field>
+        <field name="category_id" ref="base.module_category_hidden" />
+        <field name="users" eval="[(4, ref('base.user_root'))]" />
+    </record>
+
+</odoo>
diff --git a/osi_partner_credit_limit/static/description/credit_hold.png b/osi_partner_credit_limit/static/description/credit_hold.png
new file mode 100644
index 000000000..74e00fc78
Binary files /dev/null and b/osi_partner_credit_limit/static/description/credit_hold.png differ
diff --git a/osi_partner_credit_limit/static/description/credit_hold_user.png b/osi_partner_credit_limit/static/description/credit_hold_user.png
new file mode 100644
index 000000000..035ed6f08
Binary files /dev/null and b/osi_partner_credit_limit/static/description/credit_hold_user.png differ
diff --git a/osi_partner_credit_limit/static/description/credit_hold_warning.png b/osi_partner_credit_limit/static/description/credit_hold_warning.png
new file mode 100644
index 000000000..1ae2b0068
Binary files /dev/null and b/osi_partner_credit_limit/static/description/credit_hold_warning.png differ
diff --git a/osi_partner_credit_limit/static/description/credit_limit.png b/osi_partner_credit_limit/static/description/credit_limit.png
new file mode 100644
index 000000000..2f16d06f0
Binary files /dev/null and b/osi_partner_credit_limit/static/description/credit_limit.png differ
diff --git a/osi_partner_credit_limit/static/description/credit_limt.png b/osi_partner_credit_limit/static/description/credit_limt.png
new file mode 100644
index 000000000..49fb62423
Binary files /dev/null and b/osi_partner_credit_limit/static/description/credit_limt.png differ
diff --git a/osi_partner_credit_limit/static/description/credit_limt_warning.png b/osi_partner_credit_limit/static/description/credit_limt_warning.png
new file mode 100644
index 000000000..49fb62423
Binary files /dev/null and b/osi_partner_credit_limit/static/description/credit_limt_warning.png differ
diff --git a/osi_partner_credit_limit/static/description/credit_lmit.png b/osi_partner_credit_limit/static/description/credit_lmit.png
new file mode 100644
index 000000000..2f16d06f0
Binary files /dev/null and b/osi_partner_credit_limit/static/description/credit_lmit.png differ
diff --git a/osi_partner_credit_limit/static/description/credit_override.png b/osi_partner_credit_limit/static/description/credit_override.png
new file mode 100644
index 000000000..00ad8a84d
Binary files /dev/null and b/osi_partner_credit_limit/static/description/credit_override.png differ
diff --git a/osi_partner_credit_limit/static/description/fb.jpg b/osi_partner_credit_limit/static/description/fb.jpg
new file mode 100644
index 000000000..8fa52d315
Binary files /dev/null and b/osi_partner_credit_limit/static/description/fb.jpg differ
diff --git a/osi_partner_credit_limit/static/description/grace_period.png b/osi_partner_credit_limit/static/description/grace_period.png
new file mode 100644
index 000000000..d68c9b694
Binary files /dev/null and b/osi_partner_credit_limit/static/description/grace_period.png differ
diff --git a/osi_partner_credit_limit/static/description/icon.png b/osi_partner_credit_limit/static/description/icon.png
new file mode 100644
index 000000000..84791119f
Binary files /dev/null and b/osi_partner_credit_limit/static/description/icon.png differ
diff --git a/osi_partner_credit_limit/static/description/in.jpg b/osi_partner_credit_limit/static/description/in.jpg
new file mode 100644
index 000000000..d9b9a80f5
Binary files /dev/null and b/osi_partner_credit_limit/static/description/in.jpg differ
diff --git a/osi_partner_credit_limit/static/description/index.html b/osi_partner_credit_limit/static/description/index.html
new file mode 100644
index 000000000..c49a8e679
--- /dev/null
+++ b/osi_partner_credit_limit/static/description/index.html
@@ -0,0 +1,111 @@
+<!doctype html>
+<html>
+<body>
+
+    <div class="text-center" style="margin-top: 10px; margin-bottom: 20px;">
+        <h2 align="center"> Credit Override requires special permission to be set on the user.</h2>
+        <img class="img img-responsive center-block oe_demo oe_screenshot"
+            src="credit_hold_user.png" alt="Sales Hold" style="width: 90%;"/>
+    </div>
+
+    <div class="text-center" style="margin-top: 10px; margin-bottom: 20px;">
+        <h2 align="center"> Disallows new sales orders and prevents confirmation
+            of existing quotations.</h2>
+        <img class="img img-responsive center-block oe_demo oe_screenshot"
+            src="sales_hold.png" alt="Sales Hold" style="width: 90%;"/>
+    </div>
+
+    <div class="text-center" style="margin-top: 10px; margin-bottom: 20px;">
+        <h2 align="center"> Raise Warning For Sales Order On Hold.</h2>
+        <img class="img img-responsive center-block oe_demo oe_screenshot"
+            src="warning_sales_hold.png" alt="Sales Warning Hold" style="width: 90%;"/>
+    </div>
+
+    <div class="text-center" style="margin-top: 10px; margin-bottom: 20px;">
+        <h2 align="center"> Allows new sales orders, confirmation of orders,
+            but prevents orders from being shipped.</h2>
+        <img class="img img-responsive center-block oe_demo oe_screenshot"
+            src="credit_hold.png" alt="Sales Warning Hold" style="width: 90%;"/>
+    </div>
+
+    <div class="text-center" style="margin-top: 10px; margin-bottom: 20px;">
+        <h2 align="center"> Raise Warning On Credit Hold for orders from being shipped.</h2>
+        <img class="img img-responsive center-block oe_demo oe_screenshot"
+            src="credit_hold_warning.png" alt="Sales Warning Hold" style="width: 90%;"/>
+    </div>
+
+    <div class="text-center" style="margin-top: 10px; margin-bottom: 20px;">
+        <h2 align="center"> Maximum allowed receivable balance for a customer.</h2>
+        <img class="img img-responsive center-block oe_demo oe_screenshot"
+            src="credit_limit.png" alt="Sales Warning Hold" style="width: 90%;"/>
+    </div>
+
+    <div class="text-center" style="margin-top: 10px; margin-bottom: 20px;">
+        <h2 align="center"> Raise Warning On Credit Limit For Customer.</h2>
+        <img class="img img-responsive center-block oe_demo oe_screenshot"
+            src="credit_limt_warning.png" alt="Sales Warning Hold" style="width: 90%;"/>
+    </div>
+
+    <div class="text-center" style="margin-top: 10px; margin-bottom: 20px;">
+        <h2 align="center"> Time allowed for the customer to make payment after the term
+            has expired.</h2>
+        <img class="img img-responsive center-block oe_demo oe_screenshot"
+            src="grace_period.png" alt="Sales Warning Hold" style="width: 90%;"/>
+    </div>
+
+    <div class="text-center" style="margin-top: 10px; margin-bottom: 20px;">
+        <h2 align="center"> When set on sale order, allows shipment on the sale order
+            to be processed even if there is a hold on the sale order.
+          </h2>
+        <img class="img img-responsive center-block oe_demo oe_screenshot"
+            src="credit_override.png" alt="Sales Warning Hold" style="width: 90%;"/>
+    </div>
+
+    <section class="container oe_dark">
+        <div class='row justify-content-center'>
+            <hr style="border-bottom: #d74930 solid 1px; border-style: inset; width: 97%;"/>
+            <p class="fa fa-certificate fa-1x" style="color: #1f2327; font-size: calc(13.6px + 0.3vw); font-weight: bold;
+            text-align: center; margin: 0px 5px;"> For any questions,
+                support and development contact us.</p>
+            <hr style="border-bottom: #d74930 solid 1px; border-style: inset; width: 97%;"/>
+        </div>
+        <div class='row justify-content-center'>
+            <div class="col-xs-12 col-sm-6 col-md-3 col-lg-3" style="margin: 5px auto;" align="center">
+                <a href="mailto:support@opensourceintegrators.com"
+                       target="new"
+                       class="oe_button bg-primary fa fa-envelope fa-1x text-center"
+                       style="background-color: #21b799; width: 78%; font-weight: bold;"> Help! Send Mail</a>
+            </div>
+            <div class="col-xs-12 col-sm-6 col-md-3 col-lg-3" style="margin: 5px auto;" align="center">
+                <a href="https://www.opensourceintegrators.com/support"
+                       target="new"
+                       class="oe_button bg-primary fa fa-globe fa-1x text-center"
+                       style="background-color: #21b799; width: 78%; font-weight: bold;"> Support</a>
+            </div>
+        </div>
+        <div class='row justify-content-center' style="margin: 0px auto;">
+            <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 text-center">
+                <h3><span class="fa fa-whatsapp fa-1x" style="color: #697582; text-decoration: none; font-size: 13px;
+                font-weight: bold; margin-right: auto; margin-left: auto;"> 8558772377 </span>
+
+                </h3>
+                <span class="fa fa-hand-pointer-o fa-1x" style="color: #697582; text-decoration: none; font-size: 13px;
+                font-weight: bold; margin-right: auto; margin-left: auto;">Whatsapp Call 24X7</span>
+            </div>
+        </div>
+        <div class='row justify-content-center'>
+            <hr style="border-bottom: #d74930 solid 1px; border-style: inset; width: 97%;"/>
+            <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 text-center">
+                <a target="_blank"  href="https://www.facebook.com/OpenSourceIntegrators">
+                    <img src="fb.jpg" style="vertical-align: middle; border-radius: 50%; width: 25px;">
+                </a>
+
+                <a target="_blank" href="https://www.linkedin.com/company/opensourceintegrators"><img
+                        src="in.jpg" style="vertical-align: middle; border-radius: 50%; width: 25px;"></a>
+                <a target="_blank" href="https://www.youtube.com/channel/UC-E7DjI3Z3juixzPPvl2xSg/featured"><img
+                        src="youtube.jpg" style="vertical-align: middle; border-radius: 50%; width: 25px;"></a>
+
+                <a target="_blank" href="https://www.opensourceintegrators.com/"><img src="opensource-logo.svg" style="vertical-align: middle; border-radius: 50%; width: 25px;"></a>
+            </div>
+        </div>
+    </section>
\ No newline at end of file
diff --git a/osi_partner_credit_limit/static/description/opensource-logo.svg b/osi_partner_credit_limit/static/description/opensource-logo.svg
new file mode 100644
index 000000000..b4fd237f9
--- /dev/null
+++ b/osi_partner_credit_limit/static/description/opensource-logo.svg
@@ -0,0 +1,190 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 393.5 98.2" enable-background="new 0 0 393.5 98.2" xml:space="preserve">
+<g>
+	<g>
+		<path fill="#FFFFFF" d="M156.2,39.1c-1.3,0-2.4-0.2-3.4-0.6c-1-0.4-1.9-1-2.5-1.9c-0.7-0.8-1.2-1.8-1.6-2.9
+			c-0.4-1.1-0.6-2.4-0.6-3.8c0-1.4,0.2-2.7,0.6-3.9c0.4-1.2,1-2.1,1.7-3c0.7-0.8,1.6-1.4,2.6-1.9c1-0.4,2.2-0.7,3.4-0.7
+			c1.3,0,2.4,0.2,3.4,0.6c1,0.4,1.9,1,2.6,1.9c0.7,0.8,1.2,1.8,1.6,2.9c0.4,1.1,0.6,2.4,0.6,3.8c0,1.4-0.2,2.7-0.6,3.9
+			c-0.4,1.2-0.9,2.1-1.6,3c-0.7,0.8-1.6,1.5-2.6,1.9C158.7,38.9,157.5,39.1,156.2,39.1z M156.3,37.4c1.1,0,2-0.2,2.8-0.6
+			c0.8-0.4,1.4-0.9,1.9-1.6c0.5-0.7,0.9-1.5,1.1-2.4c0.2-0.9,0.3-1.9,0.3-3c0-1-0.1-2-0.3-2.9c-0.2-0.9-0.6-1.7-1.1-2.4
+			c-0.5-0.7-1.1-1.2-1.9-1.6c-0.8-0.4-1.7-0.6-2.8-0.6c-1.1,0-2,0.2-2.8,0.6c-0.8,0.4-1.4,0.9-1.9,1.6c-0.5,0.7-0.8,1.5-1.1,2.4
+			c-0.2,0.9-0.3,1.9-0.3,3c0,1.1,0.1,2.1,0.3,3c0.2,0.9,0.6,1.7,1.1,2.4c0.5,0.7,1.1,1.2,1.9,1.6C154.3,37.2,155.2,37.4,156.3,37.4z
+			"/>
+		<path fill="#FFFFFF" d="M167.9,21.1h2v2.6c0.8-1,1.7-1.8,2.6-2.3c1-0.6,2.1-0.8,3.5-0.8c1.3,0,2.4,0.2,3.3,0.7
+			c0.9,0.5,1.7,1.1,2.3,1.9c0.6,0.8,1.1,1.8,1.4,2.9c0.3,1.1,0.5,2.3,0.5,3.6c0,1.5-0.2,2.8-0.6,4c-0.4,1.2-0.9,2.2-1.6,3
+			c-0.7,0.8-1.5,1.4-2.5,1.9c-1,0.4-2,0.6-3.2,0.6c-1.1,0-2.1-0.2-3.1-0.6c-1-0.4-1.9-1.2-2.7-2.3v9h-2V21.1z M169.8,30.5
+			c0,0.8,0,1.4,0.1,2c0.1,0.6,0.2,1.1,0.4,1.5s0.4,0.9,0.7,1.2c0.3,0.4,0.7,0.7,1.1,1c0.5,0.4,1.1,0.7,1.6,0.9
+			c0.5,0.2,1.2,0.3,1.9,0.3c0.8,0,1.6-0.1,2.3-0.4c0.7-0.3,1.3-0.7,1.8-1.3c0.5-0.6,0.9-1.4,1.2-2.4c0.3-1,0.4-2.2,0.4-3.6
+			c0-1.4-0.2-2.6-0.5-3.6c-0.3-1-0.8-1.7-1.3-2.3c-0.5-0.6-1.1-1-1.8-1.2c-0.7-0.2-1.3-0.4-1.9-0.4c-0.7,0-1.3,0.1-1.9,0.2
+			c-0.6,0.2-1.1,0.5-1.7,0.9c-0.8,0.6-1.4,1.3-1.9,2.2c-0.4,0.9-0.7,2-0.7,3.4V30.5z"/>
+		<path fill="#FFFFFF" d="M201.5,34c-0.3,1.5-1,2.8-2.2,3.7c-1.2,1-2.9,1.4-5,1.4c-2.5,0-4.5-0.8-5.9-2.4c-1.4-1.6-2.1-3.8-2.1-6.7
+			c0-1.5,0.2-2.9,0.6-4.1c0.4-1.2,1-2.2,1.7-3c0.7-0.8,1.6-1.4,2.5-1.8c1-0.4,2-0.6,3.2-0.6c1.4,0,2.5,0.2,3.5,0.7
+			c1,0.4,1.7,1,2.3,1.8c0.6,0.8,1,1.7,1.3,2.7s0.4,2.2,0.4,3.4v1.3h-13.5c0,1,0.1,1.9,0.4,2.8c0.2,0.9,0.6,1.6,1.1,2.3
+			c0.5,0.6,1.1,1.2,1.9,1.5c0.7,0.4,1.6,0.6,2.6,0.6c0.9,0,1.6-0.1,2.2-0.3c0.6-0.2,1.1-0.4,1.5-0.7c0.4-0.3,0.7-0.7,1-1.1
+			c0.2-0.4,0.4-0.9,0.6-1.4H201.5z M199.7,28.6c0-1-0.1-1.8-0.3-2.6c-0.2-0.8-0.5-1.5-1-2.1c-0.4-0.6-1-1-1.7-1.3
+			c-0.7-0.3-1.5-0.5-2.5-0.5c-1.7,0-3.1,0.5-4.1,1.6c-1,1.1-1.6,2.7-1.8,4.9H199.7z"/>
+		<path fill="#FFFFFF" d="M205.2,21.1h2v2.9c1-1.2,2-2.1,3-2.6c1.1-0.5,2.2-0.8,3.4-0.8c2,0,3.5,0.6,4.4,1.7c1,1.1,1.4,2.7,1.4,4.7
+			v11.7h-2V27.5c0-1.8-0.3-3.2-1-4c-0.7-0.8-1.7-1.2-3.1-1.2c-0.7,0-1.4,0.1-2.2,0.4c-0.8,0.3-1.4,0.7-2.1,1.2
+			c-0.7,0.6-1.2,1.2-1.5,1.8c-0.3,0.6-0.5,1.5-0.5,2.6v10.3h-2V21.1z"/>
+		<path fill="#FFFFFF" d="M231.1,33.7c0.2,1.4,0.8,2.3,1.7,2.9c0.9,0.6,2.2,0.8,3.9,0.8c1.7,0,2.9-0.3,3.6-1
+			c0.7-0.6,1.1-1.4,1.1-2.4c0-0.4,0-0.8-0.1-1.1c-0.1-0.4-0.3-0.7-0.5-1c-0.3-0.3-0.6-0.5-1.1-0.7c-0.5-0.2-1.1-0.4-1.9-0.5
+			l-2.1-0.3c-0.9-0.2-1.8-0.4-2.5-0.6c-0.7-0.2-1.4-0.5-1.9-0.9c-0.5-0.4-0.9-0.8-1.2-1.4c-0.3-0.6-0.4-1.2-0.4-2.1
+			c0-0.8,0.2-1.5,0.5-2.1c0.3-0.6,0.8-1.1,1.4-1.6c0.6-0.4,1.3-0.7,2.1-1c0.8-0.2,1.7-0.3,2.6-0.3c1.2,0,2.2,0.1,3,0.4
+			c0.8,0.2,1.5,0.6,2,1c0.5,0.4,0.9,0.9,1.2,1.4c0.3,0.5,0.5,1.1,0.7,1.7l-1.8,0.4c-0.2-0.5-0.4-1-0.6-1.4c-0.2-0.4-0.5-0.7-0.9-1
+			c-0.4-0.3-0.8-0.5-1.4-0.6c-0.5-0.1-1.2-0.2-2-0.2c-0.9,0-1.7,0.1-2.3,0.3c-0.6,0.2-1.1,0.4-1.5,0.7c-0.4,0.3-0.6,0.6-0.8,1
+			c-0.2,0.4-0.2,0.8-0.2,1.2s0,0.8,0.1,1.1c0.1,0.3,0.3,0.6,0.5,0.9c0.3,0.2,0.7,0.5,1.1,0.6c0.5,0.2,1.1,0.3,1.9,0.5l2.7,0.4
+			c1.8,0.3,3.2,0.9,4.1,1.6c0.9,0.8,1.4,2,1.4,3.6c0,0.7-0.1,1.3-0.4,1.9s-0.7,1.1-1.3,1.6c-0.6,0.4-1.3,0.8-2.1,1.1
+			c-0.8,0.3-1.8,0.4-2.9,0.4c-1.1,0-2-0.1-2.9-0.3c-0.9-0.2-1.7-0.5-2.3-1c-0.7-0.4-1.2-1-1.6-1.7c-0.4-0.7-0.7-1.5-0.7-2.5H231.1z"
+			/>
+		<path fill="#FFFFFF" d="M254.1,39.1c-1.3,0-2.4-0.2-3.4-0.6c-1-0.4-1.9-1-2.5-1.9c-0.7-0.8-1.2-1.8-1.6-2.9
+			c-0.4-1.1-0.6-2.4-0.6-3.8c0-1.4,0.2-2.7,0.6-3.9c0.4-1.2,1-2.1,1.7-3c0.7-0.8,1.6-1.4,2.6-1.9c1-0.4,2.2-0.7,3.4-0.7
+			c1.3,0,2.4,0.2,3.4,0.6c1,0.4,1.9,1,2.6,1.9c0.7,0.8,1.2,1.8,1.6,2.9c0.4,1.1,0.6,2.4,0.6,3.8c0,1.4-0.2,2.7-0.6,3.9
+			c-0.4,1.2-0.9,2.1-1.6,3c-0.7,0.8-1.6,1.5-2.6,1.9C256.5,38.9,255.4,39.1,254.1,39.1z M254.1,37.4c1.1,0,2.1-0.2,2.8-0.6
+			c0.8-0.4,1.4-0.9,1.9-1.6c0.5-0.7,0.9-1.5,1.1-2.4c0.2-0.9,0.3-1.9,0.3-3c0-1-0.1-2-0.3-2.9c-0.2-0.9-0.6-1.7-1.1-2.4
+			c-0.5-0.7-1.1-1.2-1.9-1.6s-1.7-0.6-2.8-0.6c-1.1,0-2,0.2-2.8,0.6c-0.8,0.4-1.4,0.9-1.9,1.6c-0.5,0.7-0.8,1.5-1.1,2.4
+			c-0.2,0.9-0.3,1.9-0.3,3c0,1.1,0.1,2.1,0.3,3c0.2,0.9,0.6,1.7,1.1,2.4c0.5,0.7,1.1,1.2,1.9,1.6C252.1,37.2,253.1,37.4,254.1,37.4z
+			"/>
+		<path fill="#FFFFFF" d="M265.7,21.1h2v11.1c0,1.8,0.3,3.2,0.9,4c0.6,0.8,1.6,1.2,3,1.2c0.7,0,1.4-0.1,2.1-0.4
+			c0.7-0.3,1.4-0.7,2-1.2c0.7-0.6,1.2-1.2,1.5-1.8c0.3-0.6,0.5-1.5,0.5-2.6V21.1h2v17.5h-2v-2.9c-1.8,2.3-4,3.4-6.4,3.4
+			c-2,0-3.4-0.5-4.3-1.6c-0.9-1.1-1.3-2.7-1.3-4.8V21.1z"/>
+		<path fill="#FFFFFF" d="M283.7,21.1h2v2.9c0.7-1,1.5-1.8,2.4-2.3c0.9-0.5,1.9-0.8,2.9-0.8c0.2,0,0.5,0,0.7,0c0.2,0,0.4,0,0.7,0.1
+			l-0.2,1.9c-0.4-0.1-0.8-0.1-1.1-0.1c-0.6,0-1.2,0.1-1.8,0.3c-0.6,0.2-1.2,0.6-1.7,1.1c-0.5,0.5-1,1-1.3,1.6
+			c-0.3,0.6-0.5,1.4-0.5,2.3v10.5h-2V21.1z"/>
+		<path fill="#FFFFFF" d="M308.6,32.9c-0.3,2-1.1,3.5-2.3,4.6c-1.2,1.1-2.9,1.6-5,1.6c-1.3,0-2.4-0.2-3.4-0.6c-1-0.4-1.8-1-2.5-1.8
+			c-0.7-0.8-1.2-1.8-1.6-2.9c-0.4-1.1-0.5-2.4-0.5-3.8c0-1.4,0.2-2.7,0.6-3.9c0.4-1.2,0.9-2.1,1.6-3c0.7-0.8,1.6-1.4,2.6-1.9
+			c1-0.4,2.1-0.7,3.4-0.7c1.9,0,3.5,0.5,4.6,1.5c1.1,1,1.9,2.4,2.3,4.2l-1.9,0.5c-0.1-0.6-0.3-1.2-0.6-1.8c-0.3-0.5-0.6-1-1-1.4
+			c-0.4-0.4-0.9-0.7-1.4-0.9c-0.6-0.2-1.3-0.3-2.1-0.3c-1.1,0-2,0.2-2.7,0.6c-0.7,0.4-1.4,0.9-1.9,1.6c-0.5,0.7-0.9,1.5-1.1,2.4
+			c-0.2,0.9-0.3,1.9-0.3,3c0,1.1,0.1,2.1,0.3,3c0.2,0.9,0.6,1.7,1.1,2.4c0.5,0.7,1.1,1.2,1.9,1.6c0.8,0.4,1.7,0.6,2.7,0.6
+			c1.7,0,2.9-0.4,3.7-1.2c0.8-0.8,1.3-1.9,1.6-3.3H308.6z"/>
+		<path fill="#FFFFFF" d="M326.3,34c-0.3,1.5-1,2.8-2.2,3.7c-1.2,1-2.9,1.4-5,1.4c-2.5,0-4.5-0.8-5.9-2.4c-1.4-1.6-2.1-3.8-2.1-6.7
+			c0-1.5,0.2-2.9,0.6-4.1c0.4-1.2,1-2.2,1.7-3c0.7-0.8,1.6-1.4,2.5-1.8c1-0.4,2-0.6,3.2-0.6c1.4,0,2.5,0.2,3.5,0.7
+			c1,0.4,1.7,1,2.3,1.8c0.6,0.8,1,1.7,1.3,2.7s0.4,2.2,0.4,3.4v1.3h-13.5c0,1,0.1,1.9,0.4,2.8c0.2,0.9,0.6,1.6,1.1,2.3
+			c0.5,0.6,1.1,1.2,1.9,1.5c0.7,0.4,1.6,0.6,2.6,0.6c0.9,0,1.6-0.1,2.2-0.3c0.6-0.2,1.1-0.4,1.5-0.7c0.4-0.3,0.7-0.7,1-1.1
+			c0.2-0.4,0.4-0.9,0.6-1.4H326.3z M324.5,28.6c0-1-0.1-1.8-0.3-2.6c-0.2-0.8-0.5-1.5-1-2.1c-0.4-0.6-1-1-1.7-1.3
+			c-0.7-0.3-1.5-0.5-2.5-0.5c-1.7,0-3.1,0.5-4.1,1.6c-1,1.1-1.6,2.7-1.8,4.9H324.5z"/>
+		<path fill="#FFFFFF" d="M148.9,50.2h3.8v4.1h-3.8V50.2z M149.1,58.3h3.5v21.1h-3.5V58.3z"/>
+		<path fill="#FFFFFF" d="M157.1,58.3h3.5v3.2c1-1.4,2.2-2.4,3.4-3c1.2-0.6,2.6-0.9,4-0.9c2.4,0,4.2,0.7,5.3,2
+			c1.2,1.3,1.7,3.2,1.7,5.7v14h-3.5V66c0-2-0.4-3.3-1.1-4.1c-0.7-0.8-1.8-1.2-3.3-1.2c-0.8,0-1.6,0.1-2.3,0.4
+			c-0.8,0.3-1.5,0.7-2.1,1.3c-0.7,0.6-1.2,1.2-1.5,1.9c-0.4,0.7-0.5,1.5-0.5,2.6v12.5h-3.5V58.3z"/>
+		<path fill="#FFFFFF" d="M180.6,61.1h-3.3v-2.8h3.3v-5.7h3.5v5.7h5.6v2.8h-5.6v12.4c0,1,0.2,1.9,0.7,2.5c0.5,0.6,1.2,0.9,2.1,0.9
+			c0.6,0,1.1,0,1.6-0.1c0.4-0.1,0.9-0.2,1.2-0.3l0.6,2.7c-0.5,0.2-1.1,0.3-1.8,0.5c-0.6,0.1-1.4,0.2-2.3,0.2c-1.2,0-2.2-0.2-2.9-0.5
+			c-0.7-0.4-1.3-0.9-1.8-1.5c-0.4-0.7-0.7-1.4-0.9-2.3c-0.1-0.9-0.2-1.9-0.2-2.9V61.1z"/>
+		<path fill="#FFFFFF" d="M210.3,73.4c-0.4,2-1.3,3.6-2.7,4.8c-1.5,1.2-3.5,1.8-6.3,1.8c-3.2,0-5.7-1-7.4-2.9
+			c-1.7-1.9-2.6-4.7-2.6-8.1c0-1.8,0.2-3.4,0.7-4.9c0.5-1.4,1.2-2.6,2.1-3.5c0.9-1,1.9-1.7,3.2-2.2c1.2-0.5,2.6-0.8,4-0.8
+			c1.6,0,3,0.3,4.2,0.8c1.2,0.5,2.1,1.2,2.9,2.1c0.7,0.9,1.3,2,1.7,3.2c0.4,1.3,0.6,2.6,0.6,4.1v1.8H195c0,1.1,0.1,2,0.4,3
+			c0.3,0.9,0.7,1.7,1.2,2.4c0.5,0.7,1.2,1.2,2,1.6c0.8,0.4,1.7,0.6,2.7,0.6c1.8,0,3.1-0.3,3.9-1c0.8-0.7,1.4-1.6,1.7-2.7H210.3z
+			 M207.1,67c0-1-0.1-1.9-0.3-2.7c-0.2-0.8-0.6-1.5-1-2.1c-0.5-0.6-1.1-1-1.8-1.4c-0.7-0.3-1.6-0.5-2.6-0.5c-1.9,0-3.3,0.6-4.4,1.7
+			c-1,1.1-1.7,2.8-1.9,5H207.1z"/>
+		<path fill="#FFFFFF" d="M217.8,81.3c0.3,1.3,0.9,2.2,1.7,2.7c0.9,0.5,2.2,0.8,4,0.8c2.2,0,3.8-0.6,4.6-1.9c0.9-1.2,1.3-3,1.3-5.4
+			v-2.2c-0.8,1.1-1.8,2-3,2.6c-1.2,0.6-2.5,0.9-4.1,0.9c-1.5,0-2.8-0.3-4-0.8c-1.1-0.6-2.1-1.3-2.8-2.3c-0.7-1-1.3-2.1-1.7-3.4
+			c-0.4-1.3-0.6-2.7-0.6-4.1c0-1.6,0.2-3.1,0.7-4.4c0.4-1.3,1.1-2.4,1.9-3.4c0.8-0.9,1.8-1.7,3-2.2c1.2-0.5,2.5-0.8,3.9-0.8
+			c1.2,0,2.3,0.2,3.5,0.7c1.2,0.5,2.2,1.4,3.2,2.6v-2.7h3.5v17.7c0,1.8-0.1,3.5-0.4,4.9c-0.3,1.5-0.7,2.7-1.4,3.7
+			c-0.7,1-1.7,1.8-2.9,2.3c-1.2,0.5-2.8,0.8-4.7,0.8c-2.8,0-4.9-0.5-6.5-1.5c-1.6-1-2.5-2.6-2.8-4.9H217.8z M229.5,68
+			c0-1.4-0.2-2.5-0.5-3.5c-0.3-0.9-0.8-1.7-1.3-2.3c-0.6-0.6-1.2-1-2-1.3c-0.7-0.3-1.5-0.4-2.3-0.4c-0.9,0-1.7,0.1-2.4,0.4
+			c-0.7,0.3-1.4,0.7-2,1.4c-0.6,0.6-1,1.4-1.3,2.4c-0.3,1-0.5,2.2-0.5,3.5c0,1.4,0.2,2.6,0.5,3.6c0.3,1,0.8,1.8,1.3,2.4
+			c0.5,0.6,1.2,1,1.9,1.3c0.7,0.3,1.4,0.4,2.2,0.4c0.9,0,1.8-0.1,2.5-0.4c0.8-0.3,1.4-0.7,2-1.3c0.6-0.6,1-1.4,1.3-2.3
+			c0.3-0.9,0.5-2,0.5-3.2V68z"/>
+		<path fill="#FFFFFF" d="M237.5,58.3h3.5v3.3c0.8-1.2,1.7-2.1,2.8-2.7c1.1-0.6,2.2-0.9,3.4-0.9c0.7,0,1.4,0.1,1.9,0.2l-0.4,3.3
+			c-0.3-0.1-0.5-0.1-0.8-0.1c-0.3,0-0.6-0.1-0.9-0.1c-0.7,0-1.3,0.1-2,0.3c-0.7,0.2-1.3,0.6-1.9,1.2c-0.6,0.5-1.1,1.1-1.4,1.8
+			c-0.3,0.7-0.5,1.5-0.5,2.4v12.5h-3.5V58.3z"/>
+		<path fill="#FFFFFF" d="M264.4,76.5c-0.8,0.9-1.7,1.7-2.9,2.4c-1.2,0.7-2.6,1-4.4,1c-1.1,0-2-0.1-2.9-0.4
+			c-0.9-0.3-1.6-0.7-2.3-1.2c-0.6-0.5-1.1-1.2-1.5-2c-0.4-0.8-0.5-1.7-0.5-2.8c0-1.4,0.3-2.6,0.9-3.5c0.6-0.9,1.4-1.6,2.4-2.1
+			c1-0.5,2.2-0.9,3.4-1.1c1.3-0.2,2.6-0.4,4-0.4l3.6-0.1v-0.8c0-1.8-0.4-3.1-1.1-3.9c-0.8-0.8-2-1.2-3.7-1.2c-1.7,0-2.9,0.3-3.7,0.8
+			c-0.8,0.6-1.3,1.3-1.5,2.3l-3.2-0.4c0.4-1.9,1.3-3.3,2.7-4.2c1.4-0.9,3.4-1.3,5.9-1.3c1.5,0,2.8,0.2,3.9,0.6
+			c1,0.4,1.9,0.9,2.5,1.6c0.7,0.7,1.1,1.5,1.4,2.5c0.3,1,0.4,2.1,0.4,3.4v13.7h-3.4V76.5z M264.4,68.8l-3.4,0.1
+			c-1.4,0.1-2.6,0.2-3.6,0.4c-1,0.2-1.7,0.5-2.3,0.9c-0.6,0.4-1,0.8-1.2,1.4c-0.2,0.5-0.3,1.2-0.3,1.9c0,1.1,0.3,1.9,1,2.5
+			c0.6,0.6,1.7,1,3.2,1c2.1,0,3.7-0.5,4.9-1.5c1.2-1,1.8-2.4,1.8-4.2V68.8z"/>
+		<path fill="#FFFFFF" d="M273.4,61.1h-3.3v-2.8h3.3v-5.7h3.5v5.7h5.6v2.8h-5.6v12.4c0,1,0.2,1.9,0.7,2.5c0.5,0.6,1.2,0.9,2.1,0.9
+			c0.6,0,1.1,0,1.6-0.1c0.4-0.1,0.9-0.2,1.2-0.3l0.6,2.7c-0.5,0.2-1.1,0.3-1.8,0.5c-0.6,0.1-1.4,0.2-2.3,0.2c-1.2,0-2.2-0.2-2.9-0.5
+			s-1.3-0.9-1.8-1.5c-0.4-0.7-0.7-1.4-0.9-2.3c-0.1-0.9-0.2-1.9-0.2-2.9V61.1z"/>
+		<path fill="#FFFFFF" d="M294.2,80c-1.6,0-3-0.3-4.3-0.8c-1.2-0.5-2.3-1.2-3.2-2.2c-0.9-1-1.5-2.1-2-3.5c-0.5-1.4-0.7-2.9-0.7-4.6
+			s0.2-3.3,0.7-4.6c0.5-1.4,1.2-2.6,2.1-3.5c0.9-1,2-1.7,3.2-2.3c1.3-0.5,2.7-0.8,4.2-0.8c1.6,0,3,0.3,4.2,0.8
+			c1.2,0.5,2.3,1.3,3.2,2.2c0.9,1,1.6,2.1,2,3.5c0.5,1.4,0.7,2.9,0.7,4.6c0,1.7-0.2,3.3-0.7,4.7c-0.5,1.4-1.2,2.6-2,3.5
+			c-0.9,1-2,1.7-3.2,2.3C297.2,79.7,295.8,80,294.2,80z M294.3,77.1c1.1,0,2.1-0.2,2.9-0.6c0.8-0.4,1.5-1,2-1.7
+			c0.5-0.7,0.9-1.6,1.2-2.6c0.2-1,0.4-2.1,0.4-3.4c0-1.2-0.1-2.3-0.4-3.3c-0.2-1-0.6-1.9-1.2-2.6c-0.5-0.7-1.2-1.3-2-1.7
+			c-0.8-0.4-1.8-0.6-2.9-0.6c-1.1,0-2.1,0.2-2.9,0.6c-0.8,0.4-1.5,1-2,1.7c-0.5,0.7-0.9,1.6-1.2,2.6c-0.2,1-0.4,2.1-0.4,3.3
+			s0.1,2.3,0.4,3.3c0.2,1,0.6,1.9,1.1,2.6c0.5,0.7,1.2,1.3,2,1.7C292.2,76.9,293.1,77.1,294.3,77.1z"/>
+		<path fill="#FFFFFF" d="M308.2,58.3h3.5v3.3c0.8-1.2,1.7-2.1,2.8-2.7c1.1-0.6,2.2-0.9,3.4-0.9c0.7,0,1.4,0.1,1.9,0.2l-0.4,3.3
+			c-0.3-0.1-0.5-0.1-0.8-0.1c-0.3,0-0.6-0.1-0.9-0.1c-0.7,0-1.3,0.1-2,0.3c-0.7,0.2-1.3,0.6-1.9,1.2c-0.6,0.5-1.1,1.1-1.4,1.8
+			c-0.3,0.7-0.5,1.5-0.5,2.4v12.5h-3.5V58.3z"/>
+		<path fill="#FFFFFF" d="M324.5,73.2c0.2,1.5,0.9,2.5,1.9,3.1c1,0.6,2.3,0.9,4.1,0.9c1.8,0,3.1-0.3,3.8-0.9
+			c0.7-0.6,1.1-1.4,1.1-2.4c0-0.4,0-0.8-0.1-1.2c-0.1-0.4-0.3-0.7-0.6-1s-0.7-0.5-1.1-0.8c-0.5-0.2-1.1-0.4-1.9-0.5l-2.7-0.4
+			c-1.2-0.2-2.2-0.4-3.1-0.7c-0.9-0.3-1.7-0.7-2.3-1.2c-0.6-0.5-1.1-1.1-1.4-1.8c-0.3-0.7-0.5-1.5-0.5-2.5c0-1,0.2-1.8,0.6-2.6
+			c0.4-0.8,1-1.4,1.8-1.9c0.7-0.5,1.6-0.9,2.7-1.2c1-0.3,2.1-0.4,3.3-0.4c1.5,0,2.8,0.1,3.8,0.4c1,0.3,1.9,0.7,2.5,1.2
+			c0.7,0.5,1.2,1.1,1.5,1.8c0.4,0.7,0.6,1.5,0.8,2.2l-3.2,0.5c-0.2-0.6-0.4-1.1-0.7-1.5c-0.2-0.4-0.6-0.8-1-1.1
+			c-0.4-0.3-0.9-0.5-1.5-0.7c-0.6-0.1-1.3-0.2-2.2-0.2c-1,0-1.8,0.1-2.4,0.3c-0.7,0.2-1.2,0.4-1.6,0.7c-0.4,0.3-0.7,0.6-0.8,1
+			c-0.2,0.4-0.2,0.8-0.2,1.2c0,0.4,0.1,0.8,0.2,1.2c0.1,0.3,0.3,0.6,0.6,0.9c0.3,0.3,0.7,0.5,1.2,0.7c0.5,0.2,1.2,0.4,2,0.5l3.1,0.5
+			c2.5,0.4,4.2,1.1,5.3,2.1c1.1,1,1.6,2.5,1.6,4.4c0,0.9-0.2,1.7-0.5,2.5c-0.4,0.7-0.9,1.4-1.6,2c-0.7,0.6-1.6,1-2.6,1.3
+			c-1.1,0.3-2.3,0.5-3.7,0.5c-1.3,0-2.5-0.1-3.6-0.4c-1.1-0.2-2.1-0.6-2.9-1.2c-0.8-0.5-1.5-1.2-2-2.1c-0.5-0.9-0.8-1.9-0.9-3.2
+			H324.5z"/>
+		<path fill="#FFFFFF" d="M341.3,77.1h1.8v2.2h-1.8V77.1z"/>
+		<path fill="#FFFFFF" d="M355.9,75.4c-0.2,1.4-0.8,2.5-1.6,3.2c-0.9,0.8-2,1.2-3.5,1.2c-0.9,0-1.7-0.1-2.4-0.4
+			c-0.7-0.3-1.3-0.7-1.8-1.3s-0.8-1.2-1.1-2c-0.3-0.8-0.4-1.7-0.4-2.7s0.1-1.9,0.4-2.7c0.3-0.8,0.7-1.5,1.1-2.1
+			c0.5-0.6,1.1-1,1.8-1.3c0.7-0.3,1.5-0.5,2.4-0.5c1.3,0,2.4,0.3,3.2,1c0.8,0.7,1.3,1.7,1.6,2.9l-1.3,0.3c-0.1-0.4-0.2-0.9-0.4-1.2
+			c-0.2-0.4-0.4-0.7-0.7-1c-0.3-0.3-0.6-0.5-1-0.6c-0.4-0.2-0.9-0.2-1.4-0.2c-0.7,0-1.4,0.1-1.9,0.4c-0.5,0.3-1,0.6-1.3,1.1
+			s-0.6,1-0.8,1.7c-0.2,0.7-0.2,1.4-0.2,2.1c0,0.8,0.1,1.5,0.2,2.1c0.2,0.7,0.4,1.2,0.7,1.7c0.3,0.5,0.8,0.8,1.3,1.1
+			c0.5,0.3,1.2,0.4,1.9,0.4c1.2,0,2.1-0.3,2.6-0.9c0.5-0.6,0.9-1.4,1.1-2.3H355.9z"/>
+		<path fill="#FFFFFF" d="M363.4,79.7c-0.9,0-1.7-0.2-2.4-0.5c-0.7-0.3-1.3-0.7-1.8-1.3c-0.5-0.6-0.9-1.2-1.1-2
+			c-0.3-0.8-0.4-1.7-0.4-2.7c0-1,0.1-1.9,0.4-2.7s0.7-1.5,1.2-2.1c0.5-0.6,1.1-1,1.8-1.3c0.7-0.3,1.5-0.5,2.4-0.5s1.7,0.2,2.4,0.5
+			c0.7,0.3,1.3,0.7,1.8,1.3c0.5,0.6,0.9,1.2,1.1,2c0.3,0.8,0.4,1.7,0.4,2.6c0,1-0.1,1.9-0.4,2.7c-0.3,0.8-0.7,1.5-1.2,2.1
+			c-0.5,0.6-1.1,1-1.8,1.3C365.1,79.6,364.3,79.7,363.4,79.7z M363.5,78.5c0.8,0,1.4-0.1,2-0.4s1-0.7,1.3-1.1c0.3-0.5,0.6-1,0.8-1.7
+			c0.2-0.7,0.2-1.4,0.2-2.1c0-0.7-0.1-1.4-0.2-2.1c-0.2-0.6-0.4-1.2-0.8-1.7c-0.3-0.5-0.8-0.9-1.3-1.1c-0.5-0.3-1.2-0.4-2-0.4
+			c-0.8,0-1.4,0.1-2,0.4c-0.5,0.3-1,0.7-1.3,1.1c-0.3,0.5-0.6,1-0.7,1.7c-0.2,0.6-0.2,1.3-0.2,2.1c0,0.7,0.1,1.4,0.2,2.1
+			c0.2,0.7,0.4,1.2,0.7,1.7c0.3,0.5,0.8,0.9,1.3,1.1C362.1,78.4,362.7,78.5,363.5,78.5z"/>
+		<path fill="#FFFFFF" d="M371.7,67.1h1.4v2c0.6-0.8,1.2-1.4,1.9-1.8c0.7-0.4,1.4-0.6,2.1-0.6c0.9,0,1.7,0.2,2.2,0.6
+			c0.6,0.4,1,1,1.2,1.8c0.6-0.8,1.2-1.4,1.9-1.8c0.7-0.4,1.5-0.6,2.4-0.6c1.2,0,2.1,0.3,2.8,1s1,1.6,1,3v8.6h-1.4v-8.1
+			c0-0.6-0.1-1.2-0.2-1.6s-0.3-0.7-0.5-1c-0.2-0.3-0.5-0.4-0.8-0.5c-0.3-0.1-0.7-0.2-1.1-0.2c-0.4,0-0.8,0.1-1.2,0.2
+			c-0.5,0.1-0.9,0.4-1.3,0.7c-0.4,0.3-0.7,0.7-0.9,1.1c-0.2,0.4-0.4,0.9-0.4,1.5v7.8h-1.4v-8.1c0-1.2-0.2-2-0.6-2.5
+			c-0.4-0.5-1-0.7-1.9-0.7c-0.5,0-0.9,0.1-1.3,0.3c-0.4,0.2-0.8,0.5-1.2,0.8c-0.1,0.1-0.3,0.3-0.5,0.5c-0.2,0.2-0.3,0.4-0.4,0.6
+			c-0.1,0.2-0.2,0.5-0.3,0.8c-0.1,0.3-0.1,0.7-0.1,1.1v7.3h-1.4V67.1z"/>
+	</g>
+	<g>
+		<path fill="#FFFFFF" d="M288.1,89.7h1l2.8,7.3h-1l-0.8-2H287l-0.8,2h-1L288.1,89.7z M289.8,94.2l-1.3-3.4l-1.3,3.4H289.8z"/>
+		<path fill="#FFFFFF" d="M292.9,89.7h0.9l3.7,5.8v-5.8h0.9V97h-0.9l-3.7-5.7V97h-0.9V89.7z"/>
+		<path fill="#FFFFFF" d="M302.4,87.3h1.3v5.9c0,1,0.2,1.8,0.6,2.3c0.4,0.5,1,0.7,1.9,0.7c0.9,0,1.5-0.3,1.9-0.8
+			c0.4-0.5,0.5-1.3,0.5-2.2v-5.9h1.3v5.9c0,0.7-0.1,1.3-0.3,1.9c-0.2,0.5-0.4,0.9-0.7,1.3c-0.3,0.3-0.7,0.6-1.2,0.7
+			c-0.5,0.2-1,0.2-1.5,0.2c-1.2,0-2.1-0.3-2.7-1c-0.6-0.7-1-1.7-1-3.2V87.3z"/>
+		<path fill="#FFFFFF" d="M311.8,87.3h3.2c0.7,0,1.3,0.1,1.8,0.2c0.5,0.2,0.8,0.4,1.1,0.6c0.3,0.3,0.5,0.6,0.6,0.9
+			c0.1,0.3,0.1,0.7,0.1,1c0,0.6-0.1,1.1-0.4,1.6c-0.3,0.4-0.7,0.8-1.3,1l2,4.4h-1.4l-1.8-4.1c-0.1,0-0.2,0-0.4,0c-0.1,0-0.3,0-0.4,0
+			h-1.9v4h-1.2V87.3z M315.1,91.9c0.4,0,0.8,0,1.1-0.1c0.3-0.1,0.5-0.2,0.7-0.4c0.2-0.2,0.3-0.4,0.3-0.6c0.1-0.2,0.1-0.5,0.1-0.8
+			c0-0.3,0-0.5-0.1-0.7c-0.1-0.2-0.2-0.4-0.4-0.5c-0.2-0.1-0.4-0.3-0.7-0.3c-0.3-0.1-0.7-0.1-1.1-0.1h-1.9v3.5H315.1z"/>
+		<path fill="#FFFFFF" d="M321,94.2c0.1,0.7,0.4,1.2,0.8,1.5c0.4,0.3,1.1,0.5,1.9,0.5c0.4,0,0.8,0,1.1-0.1c0.3-0.1,0.5-0.2,0.7-0.4
+			c0.2-0.2,0.3-0.3,0.4-0.6c0.1-0.2,0.1-0.4,0.1-0.7c0-0.2,0-0.4-0.1-0.6c0-0.2-0.1-0.3-0.3-0.5c-0.1-0.1-0.3-0.3-0.5-0.4
+			c-0.2-0.1-0.5-0.2-0.9-0.3l-1.2-0.2c-0.5-0.1-0.9-0.2-1.3-0.3c-0.4-0.1-0.7-0.3-0.9-0.5c-0.3-0.2-0.5-0.5-0.6-0.8
+			c-0.1-0.3-0.2-0.7-0.2-1.2c0-0.4,0.1-0.8,0.3-1.2c0.2-0.3,0.4-0.6,0.8-0.8c0.3-0.2,0.7-0.4,1.1-0.5c0.4-0.1,0.9-0.2,1.4-0.2
+			c0.6,0,1.2,0.1,1.6,0.2c0.4,0.1,0.8,0.3,1.1,0.6s0.5,0.5,0.6,0.8c0.1,0.3,0.2,0.6,0.3,0.9l-1.2,0.2c-0.1-0.3-0.2-0.5-0.3-0.7
+			c-0.1-0.2-0.3-0.4-0.4-0.5c-0.2-0.1-0.4-0.2-0.7-0.3c-0.3-0.1-0.6-0.1-1-0.1c-0.4,0-0.8,0-1.1,0.1c-0.3,0.1-0.5,0.2-0.7,0.3
+			c-0.2,0.1-0.3,0.3-0.4,0.5c-0.1,0.2-0.1,0.4-0.1,0.6c0,0.2,0,0.4,0.1,0.6c0.1,0.2,0.2,0.3,0.3,0.5c0.1,0.1,0.3,0.2,0.6,0.3
+			c0.2,0.1,0.5,0.2,0.8,0.2l1.4,0.2c1,0.2,1.7,0.5,2.2,0.9c0.5,0.4,0.7,1.1,0.7,1.9c0,0.4-0.1,0.8-0.2,1.1c-0.1,0.3-0.4,0.6-0.7,0.9
+			c-0.3,0.3-0.7,0.5-1.1,0.6c-0.4,0.1-1,0.2-1.6,0.2c-0.6,0-1.1-0.1-1.6-0.2c-0.5-0.1-0.9-0.3-1.2-0.5c-0.3-0.2-0.6-0.6-0.8-0.9
+			c-0.2-0.4-0.3-0.8-0.4-1.4H321z"/>
+		<path fill="#FFFFFF" d="M331.8,87.3h1.3l3.8,9.7h-1.4l-1-2.7h-4.2l-1,2.7h-1.3L331.8,87.3z M334.2,93.2l-1.7-4.5l-1.7,4.5H334.2z"
+			/>
+		<path fill="#FFFFFF" d="M346.2,94.6c0,0.4-0.1,0.7-0.3,1c-0.1,0.3-0.3,0.6-0.6,0.8c-0.2,0.2-0.5,0.4-0.9,0.5
+			c-0.4,0.1-0.8,0.2-1.2,0.2c-0.5,0-1-0.1-1.4-0.3c-0.4-0.2-0.7-0.4-1-0.7c-0.3-0.3-0.5-0.7-0.6-1.2c-0.2-0.5-0.2-1-0.2-1.6
+			c0-0.6,0.1-1.2,0.2-1.6c0.2-0.5,0.4-0.9,0.7-1.2c0.3-0.3,0.6-0.6,1-0.7c0.4-0.2,0.8-0.3,1.3-0.3c0.4,0,0.8,0.1,1.2,0.2
+			c0.3,0.1,0.6,0.3,0.8,0.5c0.2,0.2,0.4,0.5,0.5,0.8s0.2,0.6,0.3,1l-0.9,0.2c-0.1-0.3-0.1-0.5-0.2-0.7c-0.1-0.2-0.2-0.4-0.4-0.5
+			c-0.2-0.1-0.3-0.3-0.6-0.3c-0.2-0.1-0.5-0.1-0.8-0.1c-0.4,0-0.7,0.1-1,0.2c-0.3,0.1-0.5,0.4-0.7,0.6c-0.2,0.3-0.3,0.6-0.4,0.9
+			c-0.1,0.4-0.2,0.8-0.2,1.2c0,0.4,0.1,0.9,0.2,1.2c0.1,0.4,0.2,0.7,0.4,1c0.2,0.3,0.4,0.5,0.7,0.6c0.3,0.1,0.6,0.2,1,0.2
+			c0.3,0,0.6,0,0.9-0.1c0.2-0.1,0.4-0.2,0.6-0.4s0.3-0.3,0.4-0.6c0.1-0.2,0.2-0.5,0.2-0.7H346.2z"/>
+		<path fill="#FFFFFF" d="M350.6,97.2c-0.5,0-0.9-0.1-1.4-0.3s-0.8-0.4-1.1-0.7c-0.3-0.3-0.5-0.7-0.7-1.2c-0.2-0.5-0.2-1-0.2-1.6
+			c0-0.6,0.1-1.2,0.3-1.6c0.2-0.5,0.4-0.9,0.7-1.2c0.3-0.3,0.6-0.6,1.1-0.7c0.4-0.2,0.9-0.3,1.4-0.3c0.5,0,1,0.1,1.4,0.2
+			c0.4,0.2,0.8,0.4,1.1,0.7c0.3,0.3,0.5,0.7,0.7,1.2c0.2,0.5,0.2,1,0.2,1.6c0,0.6-0.1,1.2-0.2,1.6c-0.2,0.5-0.4,0.9-0.7,1.2
+			c-0.3,0.3-0.6,0.6-1.1,0.7C351.6,97.1,351.1,97.2,350.6,97.2z M350.6,96.4c0.4,0,0.7-0.1,1-0.2c0.3-0.1,0.5-0.3,0.7-0.6
+			c0.2-0.3,0.3-0.6,0.4-0.9c0.1-0.4,0.2-0.8,0.2-1.2c0-0.4-0.1-0.9-0.2-1.2c-0.1-0.4-0.3-0.7-0.5-1c-0.2-0.3-0.4-0.5-0.7-0.6
+			c-0.3-0.1-0.6-0.2-1-0.2c-0.4,0-0.7,0.1-1,0.2c-0.3,0.1-0.5,0.3-0.7,0.6c-0.2,0.3-0.4,0.6-0.4,1c-0.1,0.4-0.1,0.8-0.1,1.2
+			c0,0.5,0,0.9,0.1,1.2c0.1,0.4,0.2,0.7,0.4,0.9c0.2,0.3,0.4,0.5,0.7,0.6C349.9,96.3,350.2,96.4,350.6,96.4z"/>
+		<path fill="#FFFFFF" d="M355.4,89.7h1.2l2.3,6.2l2.4-6.2h1.1V97h-0.9v-5.7l-2.3,5.7h-0.8l-2.2-5.7V97h-0.9V89.7z"/>
+		<path fill="#FFFFFF" d="M364.1,89.7h2.4c0.5,0,1,0.1,1.3,0.2c0.4,0.1,0.6,0.3,0.8,0.5c0.2,0.2,0.3,0.4,0.4,0.7
+			c0.1,0.3,0.1,0.5,0.1,0.8c0,0.3,0,0.6-0.1,0.9c-0.1,0.3-0.2,0.5-0.4,0.7c-0.2,0.2-0.5,0.4-0.8,0.5c-0.3,0.1-0.8,0.2-1.3,0.2H365
+			V97h-0.9V89.7z M366.5,93.4c0.4,0,0.6,0,0.9-0.1c0.2-0.1,0.4-0.2,0.5-0.3c0.1-0.1,0.2-0.3,0.3-0.5c0.1-0.2,0.1-0.4,0.1-0.6
+			c0-0.2,0-0.4-0.1-0.6c-0.1-0.2-0.1-0.3-0.3-0.4c-0.1-0.1-0.3-0.2-0.5-0.3c-0.2-0.1-0.5-0.1-0.9-0.1H365v2.9H366.5z"/>
+		<path fill="#FFFFFF" d="M372.2,89.7h1L376,97h-1l-0.8-2h-3.1l-0.8,2h-1L372.2,89.7z M373.9,94.2l-1.3-3.4l-1.3,3.4H373.9z"/>
+		<path fill="#FFFFFF" d="M377,89.7h0.9l3.7,5.8v-5.8h0.9V97h-0.9l-3.7-5.7V97H377V89.7z"/>
+		<path fill="#FFFFFF" d="M386.2,93.9l-2.5-4.2h1.1l1.9,3.4l2-3.4h1l-2.5,4.2V97h-0.9V93.9z"/>
+	</g>
+	<path fill="#FFFFFF" d="M3.9,1v96h82.8h41.4V65V1H3.9z M86.7,65v27.3H8.6V5.7h114.7V65H86.7z"/>
+</g>
+</svg>
diff --git a/osi_partner_credit_limit/static/description/sales_hold.png b/osi_partner_credit_limit/static/description/sales_hold.png
new file mode 100644
index 000000000..d5ff5bb48
Binary files /dev/null and b/osi_partner_credit_limit/static/description/sales_hold.png differ
diff --git a/osi_partner_credit_limit/static/description/youtube.jpg b/osi_partner_credit_limit/static/description/youtube.jpg
new file mode 100644
index 000000000..05382a7c1
Binary files /dev/null and b/osi_partner_credit_limit/static/description/youtube.jpg differ
diff --git a/osi_partner_credit_limit/views/res_partner.xml b/osi_partner_credit_limit/views/res_partner.xml
new file mode 100644
index 000000000..700775405
--- /dev/null
+++ b/osi_partner_credit_limit/views/res_partner.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<odoo>
+
+    <record id="partner_credit_view" model="ir.ui.view">
+        <field name="name">partner.credit.form.inherit</field>
+        <field name="model">res.partner</field>
+        <field name="type">form</field>
+        <field name="inherit_id" ref="account.view_partner_property_form" />
+        <field name="arch" type="xml">
+            <group name="fiscal_information" position="before">
+                <group string="Credit Management">
+                    <field name="sales_hold" />
+                    <field
+                        name="credit_limit"
+                        groups="osi_partner_credit_limit.group_credit_hold"
+                    />
+                    <field
+                        name="grace_period"
+                        groups="osi_partner_credit_limit.group_credit_hold"
+                    />
+                    <field
+                        name="credit_hold"
+                        groups="osi_partner_credit_limit.group_credit_hold"
+                    />
+                </group>
+            </group>
+        </field>
+    </record>
+
+</odoo>
diff --git a/osi_partner_credit_limit/views/sale.xml b/osi_partner_credit_limit/views/sale.xml
new file mode 100644
index 000000000..ac49c41af
--- /dev/null
+++ b/osi_partner_credit_limit/views/sale.xml
@@ -0,0 +1,74 @@
+<odoo>
+
+    <record id="sale_order_credit_view" model="ir.ui.view">
+        <field name="name">sale.order.credit.form.inherit</field>
+        <field name="model">sale.order</field>
+        <field name="type">form</field>
+        <field name="inherit_id" ref="sale.view_order_form" />
+        <field name="arch" type="xml">
+            <field name="client_order_ref" position="after">
+                <field name="sales_hold" />
+                <field name="credit_hold" />
+                <field name="ship_hold" readonly="1" />
+                <field
+                    name="credit_override"
+                    groups="osi_partner_credit_limit.group_credit_hold"
+                />
+            </field>
+        </field>
+    </record>
+
+    <record id="sale_order_credit_view_security" model="ir.ui.view">
+        <field name="name">sale.order.credit.view.security</field>
+        <field name="model">sale.order</field>
+        <field
+            name="inherit_id"
+            ref="osi_partner_credit_limit.sale_order_credit_view"
+        />
+        <field
+            name="groups_id"
+            eval="[(6, 0, [ref('osi_partner_credit_limit.group_credit_hold') ])]"
+        />
+        <field name="arch" type="xml">
+            <field name='ship_hold' position="attributes">
+                <attribute name="attrs">{'readonly': [
+                    ('state', 'not in', ('draft', 'sent', 'sale'))]}</attribute>
+            </field>
+            <field name='credit_override' position="attributes">
+                <attribute
+                    name="attrs"
+                >{'readonly': [('state', 'in', ('cancel', 'done'))]}</attribute>
+            </field>
+        </field>
+    </record>
+
+    <!-- Quotation Tree View with Hold fields -->
+    <record id="view_quotation_tree_credit_hold" model="ir.ui.view">
+        <field name="name">sale.order.credit.hold.tree</field>
+        <field name="model">sale.order</field>
+        <field name="inherit_id" ref="sale.view_quotation_tree" />
+        <field name="arch" type="xml">
+            <field name="state" position="after">
+                <field name="sales_hold" string="Cust. Sales Hold" />
+                <field name="credit_hold" string="Cust. Credit Hold" />
+                <field name="ship_hold" string="Order Sales Hold" />
+                <field name="credit_override" string="Hold Override" />
+            </field>
+        </field>
+    </record>
+
+    <!-- Sale Orders tree view with Warehouse field -->
+    <record id="view_order_tree_credit_hold" model="ir.ui.view">
+        <field name="name">sale.order.credit.holdtree</field>
+        <field name="model">sale.order</field>
+        <field name="inherit_id" ref="sale.view_order_tree" />
+        <field name="arch" type="xml">
+            <field name="state" position="after">
+                <field name="credit_hold" string="Cust. Credit Hold" />
+                <field name="ship_hold" string="Order Ship Hold" />
+                <field name="credit_override" string="Hold Override" />
+            </field>
+        </field>
+    </record>
+
+</odoo>
diff --git a/osi_partner_credit_limit/views/stock.xml b/osi_partner_credit_limit/views/stock.xml
new file mode 100644
index 000000000..7428c56b6
--- /dev/null
+++ b/osi_partner_credit_limit/views/stock.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<odoo>
+
+    <record id="picking_credit_view" model="ir.ui.view">
+        <field name="name">picking.credit.form.inherit</field>
+        <field name="model">stock.picking</field>
+        <field name="type">form</field>
+        <field name="inherit_id" ref="stock.view_picking_form" />
+        <field name="arch" type="xml">
+            <field name="origin" position="after">
+                <field name="dont_allow_transfer" string="Hold Shipment" />
+            </field>
+        </field>
+    </record>
+
+</odoo>
diff --git a/osi_payment_method/README.rst b/osi_payment_method/README.rst
new file mode 100644
index 000000000..688d4852f
--- /dev/null
+++ b/osi_payment_method/README.rst
@@ -0,0 +1,79 @@
+==============
+Payment Method
+==============
+
+.. |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-ursais%2Fosi--addons-lightgray.png?logo=github
+    :target: https://github.com/ursais/osi-addons/tree/12.0/sale_subscription_brand
+    :alt: ursais/osi-addons
+
+|badge1| |badge2| |badge3|
+
+This module adds a payment method on the partners and set it by default on the
+sales orders, purchase orders, customer invoices and vendor bills.
+
+**Table of contents**
+
+.. contents::
+   :local:
+
+Usage
+=====
+
+* Go to Contacts
+* Create or select a partner
+* Go to the "Accounting" tab
+* Set the payment method
+* Create a sale order, purchase order, customer invoice or vendor bill
+* Select that same partner
+* The payment method is set to the partner one
+
+Bug Tracker
+===========
+
+Bugs are tracked on `GitHub Issues <https://github.com/ursais/osi-addons/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 <https://github.com/ursais/osi-addons/issues/new?body=module:%20sale_subscription_brand%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
+
+Credits
+=======
+
+* Open Source Integrators <http://www.opensourceintegrators.com>
+* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
+
+Contributors
+------------
+
+* Michael Allen <mallen@opensourceintegrators.com>
+* Maxime Chambreuil <mchambreuil@opensourceintegrators.com>
+* Freni Patel <fpatel@opensourceintegrators.com>
+
+Maintainers
+-----------
+
+This module is maintained by Open Source Integrators.
+
+.. image:: https://github.com/ursais.png
+   :target: https://www.opensourceintegrators.com
+   :alt: Open Source Integrators
+
+Open Source Integrators™ (OSI) provides customers a unique combination of
+open source business process consulting and implementations.
+
+.. |maintainer-osimallen| image:: https://github.com/osimallen.png?size=40px
+    :target: https://github.com/osimallen
+    :alt: Michael Allen
+
+Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
+
+|maintainer-osimallen|
+
+This module is part of the `OSI Odoo Addons <https://github.com/ursais/osi-addons/tree/12.0/osi_payment_method>`_ project on GitHub.
+
+You are welcome to contribute. To learn how, please visit https://odoo-community.org/page/Contribute.
diff --git a/osi_payment_method/__init__.py b/osi_payment_method/__init__.py
new file mode 100644
index 000000000..bb83730e9
--- /dev/null
+++ b/osi_payment_method/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (C) 2021 Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from . import models
diff --git a/osi_payment_method/__manifest__.py b/osi_payment_method/__manifest__.py
new file mode 100644
index 000000000..b270ffffc
--- /dev/null
+++ b/osi_payment_method/__manifest__.py
@@ -0,0 +1,28 @@
+# Copyright (C) 2021 Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+{
+    "name": "OSI Payment Method",
+    "version": "14.0.1.0.0",
+    "author": "Open Source Integrators",
+    "summary": "Adds a payment method field to several models and views",
+    "category": "Customers",
+    "maintainer": "Open Source Integrators",
+    "website": "https://github.com/ursais/osi-addons",
+    "license": "AGPL-3",
+    "depends": [
+        "sale",
+        "purchase_stock",
+        "osi_vendor_reference",
+    ],
+    "data": [
+        "security/ir.model.access.csv",
+        "views/res_partner_views.xml",
+        "views/sale_views.xml",
+        "views/purchase_views.xml",
+        "views/account_move_views.xml",
+    ],
+    "installable": True,
+    "development_status": "Beta",
+    "maintainers": ["osimallen"],
+}
diff --git a/osi_payment_method/models/__init__.py b/osi_payment_method/models/__init__.py
new file mode 100644
index 000000000..0a844781f
--- /dev/null
+++ b/osi_payment_method/models/__init__.py
@@ -0,0 +1,9 @@
+# Copyright (C) 2021 Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from . import (
+    res_partner,
+    sale,
+    purchase,
+    account_move,
+)
diff --git a/osi_payment_method/models/account_move.py b/osi_payment_method/models/account_move.py
new file mode 100644
index 000000000..bae9d88c7
--- /dev/null
+++ b/osi_payment_method/models/account_move.py
@@ -0,0 +1,28 @@
+# Copyright (C) 2021 Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from datetime import datetime
+
+from odoo import api, fields, models
+
+
+class AccountInvoice(models.Model):
+    _inherit = "account.move"
+
+    payment_method = fields.Many2one("account.payment.method", string="Payment Method")
+    current_date = fields.Date(
+        string="Current Date",
+        copy=False,
+        help="Keep empty to use the invoice date.",
+        default=datetime.today().date(),
+        readonly=True,
+        states={"draft": [("readonly", False)]},
+    )
+
+    @api.onchange("partner_id", "purchase_id")
+    def onchange_payment_method(self):
+        if self._context.get("default_payment_method", False):
+            self.payment_method = self.purchase_id.payment_method.id or False
+        else:
+            self.payment_method = self.partner_id.payment_method.id or False
+        return {}
diff --git a/osi_payment_method/models/purchase.py b/osi_payment_method/models/purchase.py
new file mode 100644
index 000000000..aa93029aa
--- /dev/null
+++ b/osi_payment_method/models/purchase.py
@@ -0,0 +1,45 @@
+# Copyright (C) 2021 Open Source Integrators
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from odoo import api, fields, models
+from odoo.tools import frozendict
+
+
+class PurchaseOrder(models.Model):
+    _inherit = "purchase.order"
+
+    payment_method = fields.Many2one("account.payment.method", string="Payment Method")
+
+    @api.onchange("partner_id")
+    def onchange_payment_method(self):
+        self.payment_method = self.partner_id.payment_method.id or False
+        return {}
+
+    # to-do #Remove(No-need as onchange changes value)
+    def action_view_invoie(self, invoices=False):
+        res = super().action_view_invoice(invoices)
+        ctx = dict(self._context)
+        ctx.update({"default_payment_method": self.payment_method.id})
+        self.env.args = frozendict(ctx)
+        res["context"] = ctx
+        return res
+
+
+class StockRule(models.Model):
+    _inherit = "stock.rule"
+
+    def _prepare_purchase_order(
+        self, product_id, product_qty, product_uom, origin, values, partner
+    ):
+        res = super()._prepare_purchase_order(
+            product_id, product_qty, product_uom, origin, values, partner
+        )
+        if res and "payment_method" not in res:
+            res.update(
+                {
+                    "payment_method": partner.payment_method
+                    and partner.payment_method.id
+                    or False
+                }
+            )
+        return res
diff --git a/osi_payment_method/models/res_partner.py b/osi_payment_method/models/res_partner.py
new file mode 100644
index 000000000..362b1f2bf
--- /dev/null
+++ b/osi_payment_method/models/res_partner.py
@@ -0,0 +1,10 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import fields, models
+
+
+class ResPartner(models.Model):
+    _inherit = "res.partner"
+
+    payment_method = fields.Many2one("account.payment.method", string="Payment Method")
diff --git a/osi_payment_method/models/sale.py b/osi_payment_method/models/sale.py
new file mode 100644
index 000000000..fc5f4f06e
--- /dev/null
+++ b/osi_payment_method/models/sale.py
@@ -0,0 +1,20 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import api, fields, models
+
+
+class SaleOrder(models.Model):
+    _inherit = "sale.order"
+
+    payment_method = fields.Many2one("account.payment.method", string="Payment Method")
+
+    @api.onchange("partner_id")
+    def onchange_payment_method(self):
+        self.payment_method = self.partner_id.payment_method.id or False
+        return {}
+
+    def _prepare_invoice(self):
+        invoice_vals = super()._prepare_invoice()
+        invoice_vals.update({"payment_method": self.payment_method.id})
+        return invoice_vals
diff --git a/osi_payment_method/security/ir.model.access.csv b/osi_payment_method/security/ir.model.access.csv
new file mode 100644
index 000000000..1e6ff589d
--- /dev/null
+++ b/osi_payment_method/security/ir.model.access.csv
@@ -0,0 +1,2 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_account_payment_method_internal_user,account_payment_method internal user,account.model_account_payment_method,base.group_user,1,0,0,0
diff --git a/osi_payment_method/static/description/icon.png b/osi_payment_method/static/description/icon.png
new file mode 100644
index 000000000..84791119f
Binary files /dev/null and b/osi_payment_method/static/description/icon.png differ
diff --git a/osi_payment_method/views/account_move_views.xml b/osi_payment_method/views/account_move_views.xml
new file mode 100644
index 000000000..b7d80cbc9
--- /dev/null
+++ b/osi_payment_method/views/account_move_views.xml
@@ -0,0 +1,52 @@
+<odoo>
+
+    <!-- Copyright (C) 2021 Open Source Integrators
+         License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
+
+    <record id="view_in_invoice_tree_payment_method" model="ir.ui.view">
+        <field name="name">view.invoice.tree.payment.method</field>
+        <field name="model">account.move</field>
+        <field name="inherit_id" ref="account.view_in_invoice_tree" />
+        <field name="arch" type="xml">
+            <xpath
+                expr="//tree/field[@name='invoice_date_due']"
+                position="after"
+            >
+                <field name="payment_method" />
+            </xpath>
+        </field>
+    </record>
+
+    <record id="move_form_payment_method" model="ir.ui.view">
+        <field name="name">move.form.payment.method</field>
+        <field name="model">account.move</field>
+        <field name="inherit_id" ref="account.view_move_form" />
+        <field name="arch" type="xml">
+            <xpath
+                expr="//field[@name='invoice_payment_term_id']"
+                position="after"
+            >
+                <field name="payment_method" widget="selection" />
+            </xpath>
+        </field>
+    </record>
+
+    <record id="move_form_payment_method_editable" model="ir.ui.view">
+        <field name="name">move.form.payment.method.editable</field>
+        <field name="model">account.move</field>
+        <field
+            name="inherit_id"
+            ref="osi_payment_method.move_form_payment_method"
+        />
+        <field
+            name="groups_id"
+            eval="[(6, 0, [ref('account.group_account_user'),ref('account.group_account_manager'),ref('account.group_account_invoice')])]"
+        />
+        <field name="arch" type="xml">
+            <xpath expr="//field[@name='payment_method']" position="attributes">
+                <attribute name="readonly">False</attribute>
+            </xpath>
+        </field>
+    </record>
+
+</odoo>
diff --git a/osi_payment_method/views/purchase_views.xml b/osi_payment_method/views/purchase_views.xml
new file mode 100644
index 000000000..cf935f2c9
--- /dev/null
+++ b/osi_payment_method/views/purchase_views.xml
@@ -0,0 +1,42 @@
+<odoo>
+
+    <!-- Copyright (C) 2021 Open Source Integrators
+         License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
+
+    <record id="purchase_order_form_payment_method" model="ir.ui.view">
+        <field name="name">purchase.order.form.payment.method</field>
+        <field name="model">purchase.order</field>
+        <field name="inherit_id" ref="purchase.purchase_order_form" />
+        <field name="arch" type="xml">
+            <data>
+                <xpath expr="//field[@name='date_order']" position="after">
+                    <field name="payment_method" widget="selection" />
+                </xpath>
+            </data>
+        </field>
+    </record>
+
+    <record id="purchase_order_form_payment_method_editable" model="ir.ui.view">
+        <field name="name">purchase.order.form.payment.method.editable</field>
+        <field name="model">purchase.order</field>
+        <field
+            name="inherit_id"
+            ref="osi_payment_method.purchase_order_form_payment_method"
+        />
+        <field
+            name="groups_id"
+            eval="[(6, 0, [ref('purchase.group_purchase_manager')])]"
+        />
+        <field name="arch" type="xml">
+            <data>
+                <xpath
+                    expr="//field[@name='payment_method']"
+                    position="attributes"
+                >
+                    <attribute name="readonly">False</attribute>
+                </xpath>
+            </data>
+        </field>
+    </record>
+
+</odoo>
diff --git a/osi_payment_method/views/res_partner_views.xml b/osi_payment_method/views/res_partner_views.xml
new file mode 100644
index 000000000..e9e704cf1
--- /dev/null
+++ b/osi_payment_method/views/res_partner_views.xml
@@ -0,0 +1,19 @@
+<odoo>
+
+    <!-- Copyright (C) 2021 Open Source Integrators
+         License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
+
+    <record id="view_res_partner_form_payment_method" model="ir.ui.view">
+        <field name="name">res.partner.form.payment.method</field>
+        <field name="model">res.partner</field>
+        <field name="inherit_id" ref="account.view_partner_property_form" />
+        <field name="arch" type="xml">
+            <xpath expr="//group[@name='accounting_entries']" position="after">
+                <group name="payment-info" string="Payment Information">
+                    <field name="payment_method" widget="selection" />
+                </group>
+            </xpath>
+        </field>
+    </record>
+
+</odoo>
diff --git a/osi_payment_method/views/sale_views.xml b/osi_payment_method/views/sale_views.xml
new file mode 100644
index 000000000..4d0f7cc86
--- /dev/null
+++ b/osi_payment_method/views/sale_views.xml
@@ -0,0 +1,42 @@
+<odoo>
+
+    <!-- Copyright (C) 2021 Open Source Integrators
+         License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
+
+    <record id="view_order_form_payment_method" model="ir.ui.view">
+        <field name="name">order.form.payment.method</field>
+        <field name="model">sale.order</field>
+        <field name="inherit_id" ref="sale.view_order_form" />
+        <field name="arch" type="xml">
+            <data>
+                <xpath expr="//field[@name='payment_term_id']" position="after">
+                    <field name="payment_method" widget="selection" />
+                </xpath>
+            </data>
+        </field>
+    </record>
+
+    <record id="view_order_form_payment_method_editable" model="ir.ui.view">
+        <field name="name">order.form.payment.method.editable</field>
+        <field name="model">sale.order</field>
+        <field
+            name="inherit_id"
+            ref="osi_payment_method.view_order_form_payment_method"
+        />
+        <field
+            name="groups_id"
+            eval="[(6, 0, [ref('sales_team.group_sale_manager')])]"
+        />
+        <field name="arch" type="xml">
+            <data>
+                <xpath
+                    expr="//field[@name='payment_method']"
+                    position="attributes"
+                >
+                    <attribute name="readonly">False</attribute>
+                </xpath>
+            </data>
+        </field>
+    </record>
+
+</odoo>
diff --git a/osi_vendor_reference/README.rst b/osi_vendor_reference/README.rst
new file mode 100644
index 000000000..1953116fa
--- /dev/null
+++ b/osi_vendor_reference/README.rst
@@ -0,0 +1,21 @@
+.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg
+   :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+   :alt: License: LGPL-3
+
+====================
+OSI Vendor Reference
+====================
+
+When vendor bill is created, copy the vendor reference info from the PO into the bill.
+If the bill already has a reference, append to existing reference using ; [Bill can be for multiple PO's]
+
+Credits
+=======
+Mayank Gosai <mgosai@opensourceintegrators.com>
+Freni Patel <fpatel@opensourceintegrators.com>
+
+Contributors
+------------
+
+* Open Source Integrators <http://www.opensourceintegrators.com>
+* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>
diff --git a/osi_vendor_reference/__init__.py b/osi_vendor_reference/__init__.py
new file mode 100644
index 000000000..7d768b54b
--- /dev/null
+++ b/osi_vendor_reference/__init__.py
@@ -0,0 +1,3 @@
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import models
diff --git a/osi_vendor_reference/__manifest__.py b/osi_vendor_reference/__manifest__.py
new file mode 100644
index 000000000..5cc1439a5
--- /dev/null
+++ b/osi_vendor_reference/__manifest__.py
@@ -0,0 +1,18 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+{
+    "name": "OSI Vendor Reference",
+    "version": "14.0.1.0.0",
+    "author": "Open Source Integrators",
+    "summary": """When vendor bill is created, copy the vendor reference info
+    from the PO into the bill. If the bill already has a reference, append
+    to existing reference using ; [Bill can be for multiple PO's]""",
+    "license": "LGPL-3",
+    "category": "Customers",
+    "maintainer": "Open Source Integrators",
+    "website": "https://github.com/ursais/osi-addons",
+    "depends": ["purchase"],
+    "installable": True,
+    "maintainers": ["bodedra"],
+}
diff --git a/osi_vendor_reference/models/__init__.py b/osi_vendor_reference/models/__init__.py
new file mode 100644
index 000000000..8bd7e395d
--- /dev/null
+++ b/osi_vendor_reference/models/__init__.py
@@ -0,0 +1,3 @@
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import account_move
diff --git a/osi_vendor_reference/models/account_move.py b/osi_vendor_reference/models/account_move.py
new file mode 100644
index 000000000..66a155f9f
--- /dev/null
+++ b/osi_vendor_reference/models/account_move.py
@@ -0,0 +1,46 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import api, models
+
+
+class AccountMove(models.Model):
+    _inherit = "account.move"
+
+    # Load all unsold PO lines
+    @api.onchange("purchase_vendor_bill_id", "purchase_id")
+    def _onchange_purchase_auto_complete(self):
+        res = super(AccountMove, self)._onchange_purchase_auto_complete()
+
+        # Get Partner Ref from PO
+        # Check If reference in PO, if already there append new reference
+        if self.purchase_id and self.purchase_id.partner_ref:
+            if (
+                self.payment_reference
+                and self.payment_reference != self.purchase_id.partner_ref
+            ):
+                self.payment_reference = (
+                    self.payment_reference + "; " + self.purchase_id.partner_ref
+                )
+            else:
+                self.payment_reference = self.purchase_id.partner_ref
+        return res
+
+    @api.model
+    def default_get(self, default_fields):
+        res = super(AccountMove, self).default_get(default_fields)
+        if res and "purchase_id" in res:
+            po_rec = self.env["purchase.order"].browse(res.get("purchase_id"))
+
+            # Check If reference in PO, if already there append new reference
+            if "reference" in res and po_rec and po_rec.partner_ref:
+                if (
+                    res["payment_reference"]
+                    and res["payment_reference"] != po_rec.partner_ref
+                ):
+                    res["payment_reference"] = (
+                        res["payment_reference"] + "; " + po_rec.partner_ref
+                    )
+                else:
+                    res["payment_reference"] = po_rec.partner_ref
+        return res
diff --git a/osi_vendor_reference/static/description/icon.png b/osi_vendor_reference/static/description/icon.png
new file mode 100644
index 000000000..84791119f
Binary files /dev/null and b/osi_vendor_reference/static/description/icon.png differ
diff --git a/requirements.txt b/requirements.txt
index e69de29bb..9cd162922 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -0,0 +1,1 @@
+# generated from manifests external_dependencies
diff --git a/setup/.setuptools-odoo-make-default-ignore b/setup/.setuptools-odoo-make-default-ignore
new file mode 100644
index 000000000..207e61533
--- /dev/null
+++ b/setup/.setuptools-odoo-make-default-ignore
@@ -0,0 +1,2 @@
+# addons listed in this file are ignored by
+# setuptools-odoo-make-default (one addon per line)
diff --git a/setup/README b/setup/README
new file mode 100644
index 000000000..a63d633e8
--- /dev/null
+++ b/setup/README
@@ -0,0 +1,2 @@
+To learn more about this directory, please visit
+https://pypi.python.org/pypi/setuptools-odoo
diff --git a/setup/account_bank_statement_extend/odoo/addons/account_bank_statement_extend b/setup/account_bank_statement_extend/odoo/addons/account_bank_statement_extend
new file mode 120000
index 000000000..b70790213
--- /dev/null
+++ b/setup/account_bank_statement_extend/odoo/addons/account_bank_statement_extend
@@ -0,0 +1,1 @@
+../../../../account_bank_statement_extend
\ No newline at end of file
diff --git a/setup/account_bank_statement_extend/setup.py b/setup/account_bank_statement_extend/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/account_bank_statement_extend/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/account_report_budget/odoo/addons/account_report_budget b/setup/account_report_budget/odoo/addons/account_report_budget
new file mode 120000
index 000000000..05f992826
--- /dev/null
+++ b/setup/account_report_budget/odoo/addons/account_report_budget
@@ -0,0 +1,1 @@
+../../../../account_report_budget
\ No newline at end of file
diff --git a/setup/account_report_budget/setup.py b/setup/account_report_budget/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/account_report_budget/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/agreement_helpdesk/odoo/addons/agreement_helpdesk b/setup/agreement_helpdesk/odoo/addons/agreement_helpdesk
new file mode 120000
index 000000000..0da7ea105
--- /dev/null
+++ b/setup/agreement_helpdesk/odoo/addons/agreement_helpdesk
@@ -0,0 +1,1 @@
+../../../../agreement_helpdesk
\ No newline at end of file
diff --git a/setup/agreement_helpdesk/setup.py b/setup/agreement_helpdesk/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/agreement_helpdesk/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/agreement_rma/odoo/addons/agreement_rma b/setup/agreement_rma/odoo/addons/agreement_rma
new file mode 120000
index 000000000..ce1f83e97
--- /dev/null
+++ b/setup/agreement_rma/odoo/addons/agreement_rma
@@ -0,0 +1,1 @@
+../../../../agreement_rma
\ No newline at end of file
diff --git a/setup/agreement_rma/setup.py b/setup/agreement_rma/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/agreement_rma/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/documents_helpdesk/odoo/addons/documents_helpdesk b/setup/documents_helpdesk/odoo/addons/documents_helpdesk
new file mode 120000
index 000000000..b06bcf0ee
--- /dev/null
+++ b/setup/documents_helpdesk/odoo/addons/documents_helpdesk
@@ -0,0 +1,1 @@
+../../../../documents_helpdesk
\ No newline at end of file
diff --git a/setup/documents_helpdesk/setup.py b/setup/documents_helpdesk/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/documents_helpdesk/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/documents_purchase/odoo/addons/documents_purchase b/setup/documents_purchase/odoo/addons/documents_purchase
new file mode 120000
index 000000000..a3a3b7c92
--- /dev/null
+++ b/setup/documents_purchase/odoo/addons/documents_purchase
@@ -0,0 +1,1 @@
+../../../../documents_purchase
\ No newline at end of file
diff --git a/setup/documents_purchase/setup.py b/setup/documents_purchase/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/documents_purchase/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/fieldservice_agreement_helpdesk/odoo/addons/fieldservice_agreement_helpdesk b/setup/fieldservice_agreement_helpdesk/odoo/addons/fieldservice_agreement_helpdesk
new file mode 120000
index 000000000..7cf4b7311
--- /dev/null
+++ b/setup/fieldservice_agreement_helpdesk/odoo/addons/fieldservice_agreement_helpdesk
@@ -0,0 +1,1 @@
+../../../../fieldservice_agreement_helpdesk
\ No newline at end of file
diff --git a/setup/fieldservice_agreement_helpdesk/setup.py b/setup/fieldservice_agreement_helpdesk/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/fieldservice_agreement_helpdesk/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/fieldservice_googlemaps_address_autocompletion/odoo/addons/fieldservice_googlemaps_address_autocompletion b/setup/fieldservice_googlemaps_address_autocompletion/odoo/addons/fieldservice_googlemaps_address_autocompletion
new file mode 120000
index 000000000..69711c2fc
--- /dev/null
+++ b/setup/fieldservice_googlemaps_address_autocompletion/odoo/addons/fieldservice_googlemaps_address_autocompletion
@@ -0,0 +1,1 @@
+../../../../fieldservice_googlemaps_address_autocompletion
\ No newline at end of file
diff --git a/setup/fieldservice_googlemaps_address_autocompletion/setup.py b/setup/fieldservice_googlemaps_address_autocompletion/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/fieldservice_googlemaps_address_autocompletion/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/fieldservice_helpdesk_stock/odoo/addons/fieldservice_helpdesk_stock b/setup/fieldservice_helpdesk_stock/odoo/addons/fieldservice_helpdesk_stock
new file mode 120000
index 000000000..3f28153ef
--- /dev/null
+++ b/setup/fieldservice_helpdesk_stock/odoo/addons/fieldservice_helpdesk_stock
@@ -0,0 +1,1 @@
+../../../../fieldservice_helpdesk_stock
\ No newline at end of file
diff --git a/setup/fieldservice_helpdesk_stock/setup.py b/setup/fieldservice_helpdesk_stock/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/fieldservice_helpdesk_stock/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/fieldservice_mobile/odoo/addons/fieldservice_mobile b/setup/fieldservice_mobile/odoo/addons/fieldservice_mobile
new file mode 120000
index 000000000..38a8318f0
--- /dev/null
+++ b/setup/fieldservice_mobile/odoo/addons/fieldservice_mobile
@@ -0,0 +1,1 @@
+../../../../fieldservice_mobile
\ No newline at end of file
diff --git a/setup/fieldservice_mobile/setup.py b/setup/fieldservice_mobile/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/fieldservice_mobile/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/fieldservice_sign/odoo/addons/fieldservice_sign b/setup/fieldservice_sign/odoo/addons/fieldservice_sign
new file mode 120000
index 000000000..32024f8c1
--- /dev/null
+++ b/setup/fieldservice_sign/odoo/addons/fieldservice_sign
@@ -0,0 +1,1 @@
+../../../../fieldservice_sign
\ No newline at end of file
diff --git a/setup/fieldservice_sign/setup.py b/setup/fieldservice_sign/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/fieldservice_sign/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/fieldservice_tracking/odoo/addons/fieldservice_tracking b/setup/fieldservice_tracking/odoo/addons/fieldservice_tracking
new file mode 120000
index 000000000..a94556b5e
--- /dev/null
+++ b/setup/fieldservice_tracking/odoo/addons/fieldservice_tracking
@@ -0,0 +1,1 @@
+../../../../fieldservice_tracking
\ No newline at end of file
diff --git a/setup/fieldservice_tracking/setup.py b/setup/fieldservice_tracking/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/fieldservice_tracking/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/helpdesk_delivery/odoo/addons/helpdesk_delivery b/setup/helpdesk_delivery/odoo/addons/helpdesk_delivery
new file mode 120000
index 000000000..c40bd033a
--- /dev/null
+++ b/setup/helpdesk_delivery/odoo/addons/helpdesk_delivery
@@ -0,0 +1,1 @@
+../../../../helpdesk_delivery
\ No newline at end of file
diff --git a/setup/helpdesk_delivery/setup.py b/setup/helpdesk_delivery/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/helpdesk_delivery/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/helpdesk_fieldservice/odoo/addons/helpdesk_fieldservice b/setup/helpdesk_fieldservice/odoo/addons/helpdesk_fieldservice
new file mode 120000
index 000000000..70f8b6f80
--- /dev/null
+++ b/setup/helpdesk_fieldservice/odoo/addons/helpdesk_fieldservice
@@ -0,0 +1,1 @@
+../../../../helpdesk_fieldservice
\ No newline at end of file
diff --git a/setup/helpdesk_fieldservice/setup.py b/setup/helpdesk_fieldservice/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/helpdesk_fieldservice/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/helpdesk_operating_unit/odoo/addons/helpdesk_operating_unit b/setup/helpdesk_operating_unit/odoo/addons/helpdesk_operating_unit
new file mode 120000
index 000000000..355c42c7a
--- /dev/null
+++ b/setup/helpdesk_operating_unit/odoo/addons/helpdesk_operating_unit
@@ -0,0 +1,1 @@
+../../../../helpdesk_operating_unit
\ No newline at end of file
diff --git a/setup/helpdesk_operating_unit/setup.py b/setup/helpdesk_operating_unit/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/helpdesk_operating_unit/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/helpdesk_phone/odoo/addons/helpdesk_phone b/setup/helpdesk_phone/odoo/addons/helpdesk_phone
new file mode 120000
index 000000000..6d0fb832e
--- /dev/null
+++ b/setup/helpdesk_phone/odoo/addons/helpdesk_phone
@@ -0,0 +1,1 @@
+../../../../helpdesk_phone
\ No newline at end of file
diff --git a/setup/helpdesk_phone/setup.py b/setup/helpdesk_phone/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/helpdesk_phone/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/helpdesk_resolution/odoo/addons/helpdesk_resolution b/setup/helpdesk_resolution/odoo/addons/helpdesk_resolution
new file mode 120000
index 000000000..b24550451
--- /dev/null
+++ b/setup/helpdesk_resolution/odoo/addons/helpdesk_resolution
@@ -0,0 +1,1 @@
+../../../../helpdesk_resolution
\ No newline at end of file
diff --git a/setup/helpdesk_resolution/setup.py b/setup/helpdesk_resolution/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/helpdesk_resolution/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/helpdesk_scope/odoo/addons/helpdesk_scope b/setup/helpdesk_scope/odoo/addons/helpdesk_scope
new file mode 120000
index 000000000..0414b5783
--- /dev/null
+++ b/setup/helpdesk_scope/odoo/addons/helpdesk_scope
@@ -0,0 +1,1 @@
+../../../../helpdesk_scope
\ No newline at end of file
diff --git a/setup/helpdesk_scope/setup.py b/setup/helpdesk_scope/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/helpdesk_scope/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/helpdesk_stage_server_action/odoo/addons/helpdesk_stage_server_action b/setup/helpdesk_stage_server_action/odoo/addons/helpdesk_stage_server_action
new file mode 120000
index 000000000..9af858136
--- /dev/null
+++ b/setup/helpdesk_stage_server_action/odoo/addons/helpdesk_stage_server_action
@@ -0,0 +1,1 @@
+../../../../helpdesk_stage_server_action
\ No newline at end of file
diff --git a/setup/helpdesk_stage_server_action/setup.py b/setup/helpdesk_stage_server_action/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/helpdesk_stage_server_action/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/helpdesk_team_assigned_tickets/odoo/addons/helpdesk_team_assigned_tickets b/setup/helpdesk_team_assigned_tickets/odoo/addons/helpdesk_team_assigned_tickets
new file mode 120000
index 000000000..12ed218dd
--- /dev/null
+++ b/setup/helpdesk_team_assigned_tickets/odoo/addons/helpdesk_team_assigned_tickets
@@ -0,0 +1,1 @@
+../../../../helpdesk_team_assigned_tickets
\ No newline at end of file
diff --git a/setup/helpdesk_team_assigned_tickets/setup.py b/setup/helpdesk_team_assigned_tickets/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/helpdesk_team_assigned_tickets/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/helpdesk_ticket_parent/odoo/addons/helpdesk_ticket_parent b/setup/helpdesk_ticket_parent/odoo/addons/helpdesk_ticket_parent
new file mode 120000
index 000000000..6f7b4f837
--- /dev/null
+++ b/setup/helpdesk_ticket_parent/odoo/addons/helpdesk_ticket_parent
@@ -0,0 +1,1 @@
+../../../../helpdesk_ticket_parent
\ No newline at end of file
diff --git a/setup/helpdesk_ticket_parent/setup.py b/setup/helpdesk_ticket_parent/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/helpdesk_ticket_parent/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/helpdesk_ticket_to_task/odoo/addons/helpdesk_ticket_to_task b/setup/helpdesk_ticket_to_task/odoo/addons/helpdesk_ticket_to_task
new file mode 120000
index 000000000..f1cd00b63
--- /dev/null
+++ b/setup/helpdesk_ticket_to_task/odoo/addons/helpdesk_ticket_to_task
@@ -0,0 +1,1 @@
+../../../../helpdesk_ticket_to_task
\ No newline at end of file
diff --git a/setup/helpdesk_ticket_to_task/setup.py b/setup/helpdesk_ticket_to_task/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/helpdesk_ticket_to_task/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/helpdesk_ticket_type_default_priority/odoo/addons/helpdesk_ticket_type_default_priority b/setup/helpdesk_ticket_type_default_priority/odoo/addons/helpdesk_ticket_type_default_priority
new file mode 120000
index 000000000..577fd2910
--- /dev/null
+++ b/setup/helpdesk_ticket_type_default_priority/odoo/addons/helpdesk_ticket_type_default_priority
@@ -0,0 +1,1 @@
+../../../../helpdesk_ticket_type_default_priority
\ No newline at end of file
diff --git a/setup/helpdesk_ticket_type_default_priority/setup.py b/setup/helpdesk_ticket_type_default_priority/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/helpdesk_ticket_type_default_priority/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/helpdesk_timesheet_fieldservice/odoo/addons/helpdesk_timesheet_fieldservice b/setup/helpdesk_timesheet_fieldservice/odoo/addons/helpdesk_timesheet_fieldservice
new file mode 120000
index 000000000..e847f0a8f
--- /dev/null
+++ b/setup/helpdesk_timesheet_fieldservice/odoo/addons/helpdesk_timesheet_fieldservice
@@ -0,0 +1,1 @@
+../../../../helpdesk_timesheet_fieldservice
\ No newline at end of file
diff --git a/setup/helpdesk_timesheet_fieldservice/setup.py b/setup/helpdesk_timesheet_fieldservice/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/helpdesk_timesheet_fieldservice/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/osi_analytic_sales_simple/odoo/addons/osi_analytic_sales_simple b/setup/osi_analytic_sales_simple/odoo/addons/osi_analytic_sales_simple
new file mode 120000
index 000000000..92709407c
--- /dev/null
+++ b/setup/osi_analytic_sales_simple/odoo/addons/osi_analytic_sales_simple
@@ -0,0 +1,1 @@
+../../../../osi_analytic_sales_simple
\ No newline at end of file
diff --git a/setup/osi_analytic_sales_simple/setup.py b/setup/osi_analytic_sales_simple/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/osi_analytic_sales_simple/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/osi_analytic_segments/odoo/addons/osi_analytic_segments b/setup/osi_analytic_segments/odoo/addons/osi_analytic_segments
new file mode 120000
index 000000000..dd1039ed5
--- /dev/null
+++ b/setup/osi_analytic_segments/odoo/addons/osi_analytic_segments
@@ -0,0 +1,1 @@
+../../../../osi_analytic_segments
\ No newline at end of file
diff --git a/setup/osi_analytic_segments/setup.py b/setup/osi_analytic_segments/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/osi_analytic_segments/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/osi_analytic_segments_defaults/odoo/addons/osi_analytic_segments_defaults b/setup/osi_analytic_segments_defaults/odoo/addons/osi_analytic_segments_defaults
new file mode 120000
index 000000000..7d034ace5
--- /dev/null
+++ b/setup/osi_analytic_segments_defaults/odoo/addons/osi_analytic_segments_defaults
@@ -0,0 +1,1 @@
+../../../../osi_analytic_segments_defaults
\ No newline at end of file
diff --git a/setup/osi_analytic_segments_defaults/setup.py b/setup/osi_analytic_segments_defaults/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/osi_analytic_segments_defaults/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/osi_analytic_segments_expenses/odoo/addons/osi_analytic_segments_expenses b/setup/osi_analytic_segments_expenses/odoo/addons/osi_analytic_segments_expenses
new file mode 120000
index 000000000..3364dbd7b
--- /dev/null
+++ b/setup/osi_analytic_segments_expenses/odoo/addons/osi_analytic_segments_expenses
@@ -0,0 +1,1 @@
+../../../../osi_analytic_segments_expenses
\ No newline at end of file
diff --git a/setup/osi_analytic_segments_expenses/setup.py b/setup/osi_analytic_segments_expenses/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/osi_analytic_segments_expenses/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/osi_analytic_segments_multi_company/odoo/addons/osi_analytic_segments_multi_company b/setup/osi_analytic_segments_multi_company/odoo/addons/osi_analytic_segments_multi_company
new file mode 120000
index 000000000..c5d2a3082
--- /dev/null
+++ b/setup/osi_analytic_segments_multi_company/odoo/addons/osi_analytic_segments_multi_company
@@ -0,0 +1,1 @@
+../../../../osi_analytic_segments_multi_company
\ No newline at end of file
diff --git a/setup/osi_analytic_segments_multi_company/setup.py b/setup/osi_analytic_segments_multi_company/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/osi_analytic_segments_multi_company/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/osi_analytic_segments_purchase/odoo/addons/osi_analytic_segments_purchase b/setup/osi_analytic_segments_purchase/odoo/addons/osi_analytic_segments_purchase
new file mode 120000
index 000000000..6fb742a97
--- /dev/null
+++ b/setup/osi_analytic_segments_purchase/odoo/addons/osi_analytic_segments_purchase
@@ -0,0 +1,1 @@
+../../../../osi_analytic_segments_purchase
\ No newline at end of file
diff --git a/setup/osi_analytic_segments_purchase/setup.py b/setup/osi_analytic_segments_purchase/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/osi_analytic_segments_purchase/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/osi_analytic_segments_purchase_subscription/odoo/addons/osi_analytic_segments_purchase_subscription b/setup/osi_analytic_segments_purchase_subscription/odoo/addons/osi_analytic_segments_purchase_subscription
new file mode 120000
index 000000000..6e8e71a5c
--- /dev/null
+++ b/setup/osi_analytic_segments_purchase_subscription/odoo/addons/osi_analytic_segments_purchase_subscription
@@ -0,0 +1,1 @@
+../../../../osi_analytic_segments_purchase_subscription
\ No newline at end of file
diff --git a/setup/osi_analytic_segments_purchase_subscription/setup.py b/setup/osi_analytic_segments_purchase_subscription/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/osi_analytic_segments_purchase_subscription/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/osi_analytic_segments_sales/odoo/addons/osi_analytic_segments_sales b/setup/osi_analytic_segments_sales/odoo/addons/osi_analytic_segments_sales
new file mode 120000
index 000000000..9f82a6d7c
--- /dev/null
+++ b/setup/osi_analytic_segments_sales/odoo/addons/osi_analytic_segments_sales
@@ -0,0 +1,1 @@
+../../../../osi_analytic_segments_sales
\ No newline at end of file
diff --git a/setup/osi_analytic_segments_sales/setup.py b/setup/osi_analytic_segments_sales/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/osi_analytic_segments_sales/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/osi_analytic_segments_stock/odoo/addons/osi_analytic_segments_stock b/setup/osi_analytic_segments_stock/odoo/addons/osi_analytic_segments_stock
new file mode 120000
index 000000000..31c9bd713
--- /dev/null
+++ b/setup/osi_analytic_segments_stock/odoo/addons/osi_analytic_segments_stock
@@ -0,0 +1,1 @@
+../../../../osi_analytic_segments_stock
\ No newline at end of file
diff --git a/setup/osi_analytic_segments_stock/setup.py b/setup/osi_analytic_segments_stock/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/osi_analytic_segments_stock/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/osi_analytic_segments_stock_scrap/odoo/addons/osi_analytic_segments_stock_scrap b/setup/osi_analytic_segments_stock_scrap/odoo/addons/osi_analytic_segments_stock_scrap
new file mode 120000
index 000000000..47b1cb2ae
--- /dev/null
+++ b/setup/osi_analytic_segments_stock_scrap/odoo/addons/osi_analytic_segments_stock_scrap
@@ -0,0 +1,1 @@
+../../../../osi_analytic_segments_stock_scrap
\ No newline at end of file
diff --git a/setup/osi_analytic_segments_stock_scrap/setup.py b/setup/osi_analytic_segments_stock_scrap/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/osi_analytic_segments_stock_scrap/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/osi_bank_reconciled_report/odoo/addons/osi_bank_reconciled_report b/setup/osi_bank_reconciled_report/odoo/addons/osi_bank_reconciled_report
new file mode 120000
index 000000000..0e84bd673
--- /dev/null
+++ b/setup/osi_bank_reconciled_report/odoo/addons/osi_bank_reconciled_report
@@ -0,0 +1,1 @@
+../../../../osi_bank_reconciled_report
\ No newline at end of file
diff --git a/setup/osi_bank_reconciled_report/setup.py b/setup/osi_bank_reconciled_report/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/osi_bank_reconciled_report/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/osi_credit_card_reconciliation/odoo/addons/osi_credit_card_reconciliation b/setup/osi_credit_card_reconciliation/odoo/addons/osi_credit_card_reconciliation
new file mode 120000
index 000000000..da04c11d9
--- /dev/null
+++ b/setup/osi_credit_card_reconciliation/odoo/addons/osi_credit_card_reconciliation
@@ -0,0 +1,1 @@
+../../../../osi_credit_card_reconciliation
\ No newline at end of file
diff --git a/setup/osi_credit_card_reconciliation/setup.py b/setup/osi_credit_card_reconciliation/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/osi_credit_card_reconciliation/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/osi_helpdesk_stock/odoo/addons/osi_helpdesk_stock b/setup/osi_helpdesk_stock/odoo/addons/osi_helpdesk_stock
new file mode 120000
index 000000000..fb5fce3ff
--- /dev/null
+++ b/setup/osi_helpdesk_stock/odoo/addons/osi_helpdesk_stock
@@ -0,0 +1,1 @@
+../../../../osi_helpdesk_stock
\ No newline at end of file
diff --git a/setup/osi_helpdesk_stock/setup.py b/setup/osi_helpdesk_stock/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/osi_helpdesk_stock/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/osi_partner_credit_limit/odoo/addons/osi_partner_credit_limit b/setup/osi_partner_credit_limit/odoo/addons/osi_partner_credit_limit
new file mode 120000
index 000000000..273a1b00b
--- /dev/null
+++ b/setup/osi_partner_credit_limit/odoo/addons/osi_partner_credit_limit
@@ -0,0 +1,1 @@
+../../../../osi_partner_credit_limit
\ No newline at end of file
diff --git a/setup/osi_partner_credit_limit/setup.py b/setup/osi_partner_credit_limit/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/osi_partner_credit_limit/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/osi_payment_method/odoo/addons/osi_payment_method b/setup/osi_payment_method/odoo/addons/osi_payment_method
new file mode 120000
index 000000000..850487b14
--- /dev/null
+++ b/setup/osi_payment_method/odoo/addons/osi_payment_method
@@ -0,0 +1,1 @@
+../../../../osi_payment_method
\ No newline at end of file
diff --git a/setup/osi_payment_method/setup.py b/setup/osi_payment_method/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/osi_payment_method/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)
diff --git a/setup/osi_vendor_reference/odoo/addons/osi_vendor_reference b/setup/osi_vendor_reference/odoo/addons/osi_vendor_reference
new file mode 120000
index 000000000..f4a4fe52f
--- /dev/null
+++ b/setup/osi_vendor_reference/odoo/addons/osi_vendor_reference
@@ -0,0 +1,1 @@
+../../../../osi_vendor_reference
\ No newline at end of file
diff --git a/setup/osi_vendor_reference/setup.py b/setup/osi_vendor_reference/setup.py
new file mode 100644
index 000000000..28c57bb64
--- /dev/null
+++ b/setup/osi_vendor_reference/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+    setup_requires=['setuptools-odoo'],
+    odoo_addon=True,
+)


Test patch:
diff --git a/fieldservice_helpdesk_stock/tests/__init__.py b/fieldservice_helpdesk_stock/tests/__init__.py
new file mode 100644
index 000000000..4b93d7353
--- /dev/null
+++ b/fieldservice_helpdesk_stock/tests/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import test_stock_request
diff --git a/fieldservice_helpdesk_stock/tests/test_stock_request.py b/fieldservice_helpdesk_stock/tests/test_stock_request.py
new file mode 100644
index 000000000..a2d72a000
--- /dev/null
+++ b/fieldservice_helpdesk_stock/tests/test_stock_request.py
@@ -0,0 +1,70 @@
+# Copyright (C) 2021 Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl-3.0).
+
+from datetime import datetime
+
+from odoo.tests import common
+
+
+class TestStockRequest(common.TransactionCase):
+    def setUp(self):
+        super(TestStockRequest, self).setUp()
+
+        # common models
+        self.test_location = self.env.ref("fieldservice.test_location")
+
+        self.request_order = self.env["stock.request.order"]
+        self.main_company = self.env.ref("base.main_company")
+        self.warehouse = self.env.ref("stock.warehouse0")
+
+        self.product_id = self.env["product.product"].create(
+            dict(
+                name="CODEA1",
+                default_code="Product A1",
+                uom_id=self.env.ref("uom.product_uom_unit").id,
+                company_id=self.main_company.id,
+                type="product",
+            )
+        )
+
+        self.order = self.env["fsm.order"].create(
+            {"location_id": self.test_location.id}
+        )
+
+        self.stock_request = self.env["stock.request"].create(
+            {
+                "picking_policy": "direct",
+                "product_id": self.product_id.id,
+                "product_uom_id": self.env.ref("uom.product_uom_unit").id,
+                "product_uom_qty": 1.0,
+                "warehouse_id": self.warehouse.id,
+                "expected_date": datetime.today(),
+                "direction": "outbound",
+                "location_id": self.test_location.id,
+            }
+        )
+
+    def test_fsm_location(self):
+        vals = {
+            "fsm_order_id": self.order.id,
+            "picking_policy": "direct",
+            "product_id": self.product_id.id,
+            "product_uom_id": self.env.ref("uom.product_uom_unit").id,
+            "product_uom_qty": 1.0,
+            "warehouse_id": self.warehouse.id,
+            "expected_date": datetime.today(),
+            "direction": "outbound",
+            "location_id": self.test_location.id,
+        }
+        self.order.write(
+            {"stock_request_ids": [(6, 0, self.env["stock.request"].create(vals).ids)]}
+        )
+        # Check the Location on the SR is equal to the Location on the Order
+        self.assertEqual(
+            self.order.stock_request_ids[0].fsm_location_id, self.order.location_id
+        )
+        # Check the Location on the SRO is equal to the Location on the Order
+        self.assertEqual(
+            self.order.stock_request_ids[0].order_id.fsm_location_id,
+            self.order.location_id,
+        )
diff --git a/helpdesk_operating_unit/tests/__init__.py b/helpdesk_operating_unit/tests/__init__.py
new file mode 100644
index 000000000..0b20c2374
--- /dev/null
+++ b/helpdesk_operating_unit/tests/__init__.py
@@ -0,0 +1,2 @@
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
+from . import test_test_helpdesk_ticket_operating_unit
diff --git a/helpdesk_operating_unit/tests/test_test_helpdesk_ticket_operating_unit.py b/helpdesk_operating_unit/tests/test_test_helpdesk_ticket_operating_unit.py
new file mode 100644
index 000000000..4ca6ded7e
--- /dev/null
+++ b/helpdesk_operating_unit/tests/test_test_helpdesk_ticket_operating_unit.py
@@ -0,0 +1,76 @@
+# Copyright (C) 2021 Open Source Integrators
+# Copyright (C) 2021 Serpent Consulting Services
+# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).
+from odoo.tests import common
+
+
+class TestHelpdeskTicketOperatingUnit(common.TransactionCase):
+    def setUp(self):
+        super(TestHelpdeskTicketOperatingUnit, self).setUp()
+        self.helpdesk_obj = self.env["helpdesk.ticket"]
+        self.res_users_model = self.env["res.users"]
+
+        # Groups
+        self.grp_manager = self.env.ref("helpdesk.group_helpdesk_manager")
+        self.grp_user = self.env.ref("helpdesk.group_helpdesk_user")
+        # Company
+        self.company = self.env.ref("base.main_company")
+        # Main Operating Unit
+        self.main_OU = self.env.ref("operating_unit.main_operating_unit")
+        # B2C Operating Unit
+        self.b2c_OU = self.env.ref("operating_unit.b2c_operating_unit")
+        # Create User 1 with Main OU
+        self.user1 = self._create_user(
+            "user_1", [self.grp_user, self.grp_manager], self.company, [self.main_OU]
+        )
+        # Create User 2 with B2C OU
+        self.user2 = self._create_user(
+            "user_2", [self.grp_user, self.grp_manager], self.company, [self.b2c_OU]
+        )
+
+        self.helpdesk_ticket1 = self._create_helpdesk_ticket(
+            self.user1.id, self.main_OU
+        )
+        self.helpdesk_ticket2 = self._create_helpdesk_ticket(self.user2.id, self.b2c_OU)
+
+    def _create_user(self, login, groups, company, operating_units):
+        """Create a user."""
+        group_ids = [group.id for group in groups]
+        user = self.res_users_model.create(
+            {
+                "name": login,
+                "login": login,
+                "password": "demo",
+                "email": "test@yourcompany.com",
+                "company_id": company.id,
+                "company_ids": [(4, company.id)],
+                "operating_unit_ids": [(4, ou.id) for ou in operating_units],
+                "groups_id": [(6, 0, group_ids)],
+            }
+        )
+        return user
+
+    def _create_helpdesk_ticket(self, uid, operating_unit):
+        helpdesk = self.helpdesk_obj.with_user(uid).create(
+            {
+                "name": "Demo helpdesk",
+                "operating_unit_id": operating_unit.id,
+            }
+        )
+        return helpdesk
+
+    def test_helpdesk(self):
+        # User 2 is only assigned to B2C Operating Unit, and cannot
+        # access Agreement for Main Operating Unit.
+        helpdesk_ticket_ids = self.helpdesk_obj.with_user(self.user2.id).search(
+            [
+                ("id", "=", self.helpdesk_ticket2.id),
+                ("operating_unit_id", "=", self.main_OU.id),
+            ]
+        )
+        self.assertEqual(
+            helpdesk_ticket_ids.ids,
+            [],
+            "User 2 should not have " " access to %s" % self.main_OU.name,
+        )
+        self.assertEqual(self.helpdesk_ticket1.operating_unit_id.id, self.main_OU.id)
diff --git a/helpdesk_team_assigned_tickets/tests/__init__.py b/helpdesk_team_assigned_tickets/tests/__init__.py
new file mode 100644
index 000000000..bd399351b
--- /dev/null
+++ b/helpdesk_team_assigned_tickets/tests/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from . import test_helpdesk_team
diff --git a/helpdesk_team_assigned_tickets/tests/common.py b/helpdesk_team_assigned_tickets/tests/common.py
new file mode 100644
index 000000000..655b8f33c
--- /dev/null
+++ b/helpdesk_team_assigned_tickets/tests/common.py
@@ -0,0 +1,34 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo.tests.common import TransactionCase
+
+
+class HelpdeskTransactionCase(TransactionCase):
+    def setUp(self):
+        super(HelpdeskTransactionCase, self).setUp()
+
+        # Set up company, manager, and user
+        self.main_company_id = self.env.ref("base.main_company").id
+        self.helpdesk_manager = self.env["res.users"].create(
+            {
+                "company_id": self.main_company_id,
+                "name": "Helpdesk Manager",
+                "login": "hm",
+                "email": "hm@example.com",
+                "groups_id": [
+                    (6, 0, [self.env.ref("helpdesk.group_helpdesk_manager").id])
+                ],
+            }
+        )
+        self.helpdesk_user = self.env["res.users"].create(
+            {
+                "company_id": self.main_company_id,
+                "name": "Helpdesk User",
+                "login": "hu",
+                "email": "hu@example.com",
+                "groups_id": [
+                    (6, 0, [self.env.ref("helpdesk.group_helpdesk_user").id])
+                ],
+            }
+        )
diff --git a/helpdesk_team_assigned_tickets/tests/test_helpdesk_team.py b/helpdesk_team_assigned_tickets/tests/test_helpdesk_team.py
new file mode 100644
index 000000000..f3c0bd02d
--- /dev/null
+++ b/helpdesk_team_assigned_tickets/tests/test_helpdesk_team.py
@@ -0,0 +1,71 @@
+# Copyright (C) 2021 - TODAY, Open Source Integrators
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from .common import HelpdeskTransactionCase
+
+
+class TestHelpdeskAssign(HelpdeskTransactionCase):
+    """Test used to check that the base functionalities of Helpdesk Team
+    Assigned Tickets function as expected.
+    - test_number_assign: tests that the assigned_tickets field
+    computes properly.
+    """
+
+    def test_number_assign(self):
+        # helpdesk manager creates a helpdesk team
+        # (the .sudo() at the end is to avoid potential uid problems)
+        self.test_team = (
+            self.env["helpdesk.team"]
+            .sudo(self.helpdesk_manager.id)
+            .create({"name": "Test Team"})
+            .sudo()
+        )
+
+        # get possible tickets from previous installs that are not assigned
+        prev = self.env["helpdesk.ticket"].search_count([("user_id", "=", False)])
+
+        # we create 10 tickets
+        # make half assigned and half unassigned
+        for i in range(10):
+            if i % 2 == 0:
+                self.env["helpdesk.ticket"].create(
+                    {
+                        "name": "test ticket " + str(i),
+                        "team_id": self.test_team.id,
+                    }
+                )
+            else:
+                self.env["helpdesk.ticket"].create(
+                    {
+                        "name": "test ticket " + str(i),
+                        "team_id": self.test_team.id,
+                        "user_id": self.helpdesk_user.id,
+                    }
+                )
+
+        # ensure we have an equal number of assigned and unassigned tickets
+        self.assertEqual(
+            self.env["helpdesk.ticket"].search_count([("user_id", "=", False)]) - prev,
+            5,
+        )
+        self.assertEqual(
+            self.env["helpdesk.ticket"].search_count(
+                [("user_id", "=", self.helpdesk_user.id)]
+            ),
+            5,
+        )
+
+        # ensure fields assigned_tickets and unassigned_tickets are equal
+        u_count = self.env["helpdesk.team"].browse(self.test_team.id).unassigned_tickets
+        a_count = self.env["helpdesk.team"].browse(self.test_team.id).assigned_tickets
+
+        self.assertEqual(
+            self.env["helpdesk.ticket"].search_count([("user_id", "=", False)]) - prev,
+            u_count,
+        )
+        self.assertEqual(
+            self.env["helpdesk.ticket"].search_count(
+                [("user_id", "=", self.helpdesk_user.id)]
+            ),
+            a_count,
+        )
diff --git a/osi_analytic_segments_multi_company/tests/__init__.py b/osi_analytic_segments_multi_company/tests/__init__.py
new file mode 100644
index 000000000..f15da2000
--- /dev/null
+++ b/osi_analytic_segments_multi_company/tests/__init__.py
@@ -0,0 +1,1 @@
+from . import test_account_move
diff --git a/osi_analytic_segments_multi_company/tests/test_account_move.py b/osi_analytic_segments_multi_company/tests/test_account_move.py
new file mode 100644
index 000000000..327912499
--- /dev/null
+++ b/osi_analytic_segments_multi_company/tests/test_account_move.py
@@ -0,0 +1,456 @@
+import time
+
+import odoo.tests.common as common
+
+
+class TestAccountMove(common.TransactionCase):
+    def setUp(self):
+        super(TestAccountMove, self).setUp()
+
+        self.company = self.env.ref("base.main_company")
+
+        self.due_to_due_from_journal_main_company = self.env["account.journal"].create(
+            {
+                "name": "Test Due To/Due From",
+                "type": "general",
+                "code": "DUE",
+                "currency_id": self.company.currency_id.id,
+                "company_id": self.company.id,
+            }
+        )
+
+        user_type_current_liabilities = self.env.ref(
+            "account.data_account_type_current_liabilities"
+        )
+
+        self.account_due_to_main_company = self.env["account.account"].create(
+            {
+                "code": "Test 101404",
+                "name": "Test Due To Account",
+                "user_type_id": user_type_current_liabilities.id,
+                "company_id": self.company.id,
+            }
+        )
+
+        self.account_payroll_clearing_main_company = self.env["account.account"].create(
+            {
+                "code": "Test 212410",
+                "name": "Test Payroll Clearing",
+                "user_type_id": user_type_current_liabilities.id,
+                "company_id": self.company.id,
+            }
+        )
+
+        user_type_current_assets = self.env.ref(
+            "account.data_account_type_current_assets"
+        )
+
+        self.account_due_from_main_company = self.env["account.account"].create(
+            {
+                "code": "Test 100020",
+                "name": "Test Due From Account",
+                "user_type_id": user_type_current_assets.id,
+                "company_id": self.company.id,
+            }
+        )
+
+        user_type_current_expenses = self.env.ref("account.data_account_type_expenses")
+
+        self.account_salary_expense_main_company = self.env["account.account"].create(
+            {
+                "code": "Test 212400",
+                "name": "Test Salary Expenses",
+                "user_type_id": user_type_current_expenses.id,
+                "company_id": self.company.id,
+                "reconcile": True,
+            }
+        )
+
+        self.account_invoice_main_company = self.env["account.account"].create(
+            {
+                "code": "Invoice 062320",
+                "name": "Test Invoices",
+                "user_type_id": user_type_current_expenses.id,
+                "company_id": self.company.id,
+                "reconcile": True,
+            }
+        )
+
+        self.company.due_fromto_payment_journal_id = (
+            self.due_to_due_from_journal_main_company
+        )
+        self.company.due_from_account_id = self.account_due_from_main_company
+        self.company.due_to_account_id = self.account_due_to_main_company
+
+        self.partner_company_one = (
+            self.env["res.partner"].sudo().create({"name": "Test Company One"})
+        )
+        self.company_one = (
+            self.env["res.company"]
+            .sudo()
+            .create(
+                {
+                    "name": "Test Company One",
+                    "partner_id": self.partner_company_one.id,
+                    "parent_id": self.company.id,
+                }
+            )
+        )
+
+        self.due_to_due_from_journal_company_one = (
+            self.env["account.journal"]
+            .sudo()
+            .create(
+                {
+                    "name": "Test Due To/Due From",
+                    "type": "general",
+                    "code": "DUE",
+                    "currency_id": self.company.currency_id.id,
+                    "company_id": self.company_one.id,
+                }
+            )
+        )
+
+        self.account_due_to_company_one = (
+            self.env["account.account"]
+            .sudo()
+            .create(
+                {
+                    "code": "Test 101404",
+                    "name": "Test Due To Account",
+                    "user_type_id": user_type_current_liabilities.id,
+                    "company_id": self.company_one.id,
+                }
+            )
+        )
+
+        self.account_due_from_company_one = (
+            self.env["account.account"]
+            .sudo()
+            .create(
+                {
+                    "code": "Test 100020",
+                    "name": "Test Due From Account",
+                    "user_type_id": user_type_current_assets.id,
+                    "company_id": self.company_one.id,
+                }
+            )
+        )
+
+        self.account_invoice_company_one = self.env["account.account"].create(
+            {
+                "code": "Invoice 062320",
+                "name": "Test Invoices",
+                "user_type_id": user_type_current_expenses.id,
+                "company_id": self.company_one.id,
+                "reconcile": True,
+            }
+        )
+
+        self.company_one.due_fromto_payment_journal_id = (
+            self.due_to_due_from_journal_company_one
+        )
+        self.company_one.due_from_account_id = self.account_due_from_company_one
+        self.company_one.due_to_account_id = self.account_due_to_company_one
+
+        self.account_salary_expense_company_one = (
+            self.env["account.account"]
+            .sudo()
+            .create(
+                {
+                    "code": "Test 212400",
+                    "name": "Test Salary Expenses",
+                    "user_type_id": user_type_current_expenses.id,
+                    "company_id": self.company_one.id,
+                    "reconcile": True,
+                }
+            )
+        )
+
+        self.partner_company_two = (
+            self.env["res.partner"].sudo().create({"name": "Test Company Two"})
+        )
+        self.company_two = (
+            self.env["res.company"]
+            .sudo()
+            .create(
+                {
+                    "name": "Test Company Two",
+                    "partner_id": self.partner_company_two.id,
+                    "parent_id": self.company.id,
+                }
+            )
+        )
+
+        self.due_to_due_from_journal_company_two = (
+            self.env["account.journal"]
+            .sudo()
+            .create(
+                {
+                    "name": "Test Due To/Due From",
+                    "type": "general",
+                    "code": "DUE",
+                    "currency_id": self.company.currency_id.id,
+                    "company_id": self.company_two.id,
+                }
+            )
+        )
+
+        self.account_due_to_company_two = (
+            self.env["account.account"]
+            .sudo()
+            .create(
+                {
+                    "code": "Test 101404",
+                    "name": "Test Due To Account",
+                    "user_type_id": user_type_current_liabilities.id,
+                    "company_id": self.company_two.id,
+                }
+            )
+        )
+
+        self.account_due_from_company_two = (
+            self.env["account.account"]
+            .sudo()
+            .create(
+                {
+                    "code": "Test 100020",
+                    "name": "Test Due From Account",
+                    "user_type_id": user_type_current_assets.id,
+                    "company_id": self.company_two.id,
+                }
+            )
+        )
+
+        self.account_salary_expense_company_two = (
+            self.env["account.account"]
+            .sudo()
+            .create(
+                {
+                    "code": "Test 212400",
+                    "name": "Test Salary Expenses",
+                    "user_type_id": user_type_current_expenses.id,
+                    "company_id": self.company_two.id,
+                    "reconcile": True,
+                }
+            )
+        )
+
+        self.company_two.due_fromto_payment_journal_id = (
+            self.due_to_due_from_journal_company_two
+        )
+        self.company_two.due_from_account_id = self.account_due_from_company_two
+        self.company_two.due_to_account_id = self.account_due_to_company_two
+
+        self.employee_A = self.env["res.partner"].create({"name": "Employee A"})
+
+        self.employee_B = self.env["res.partner"].create({"name": "Employee B"})
+
+        self.employee_C = self.env["res.partner"].create({"name": "Employee C"})
+
+        employee_group = self.env.ref("base.group_user")
+        employee_invoice_group = self.env.ref("account.group_account_invoice")
+
+        self.account_user = (
+            self.env["res.users"]
+            .with_context({"no_reset_password": True})
+            .create(
+                dict(
+                    name="Adviser",
+                    company_id=self.company.id,
+                    login="fm",
+                    email="accountmanager@yourcompany.com",
+                    groups_id=[(6, 0, [employee_group.id, employee_invoice_group.id])],
+                )
+            )
+        )
+        self.seg_one_a = self.env["analytic.segment.one"].create(
+            {"name": "Test One Alpha", "code": "1A"}
+        )
+        self.seg_one_b = self.env["analytic.segment.one"].create(
+            {"name": "Test One Beta", "code": "1B"}
+        )
+        self.seg_one_c = self.env["analytic.segment.one"].create(
+            {"name": "Test One Charlie", "code": "1C"}
+        )
+        self.seg_two_a = self.env["analytic.segment.two"].create(
+            {"name": "Test Two Alpha", "code": "2A"}
+        )
+        self.seg_two_b = self.env["analytic.segment.two"].create(
+            {"name": "Test Two Beta", "code": "2B"}
+        )
+        self.seg_two_c = self.env["analytic.segment.two"].create(
+            {"name": "Test Two Charlie", "code": "2C"}
+        )
+
+    def test_account_move_segments(self):
+
+        self.journalrec = (
+            self.env["account.journal"]
+            .with_user(self.account_user.id)
+            .search([("type", "=", "general")])[0]
+        )
+
+        payroll_move = (
+            self.env["account.move"]
+            .with_user(self.account_user.id)
+            .with_context(default_move_type="entry")
+            .create(
+                {
+                    "journal_id": self.journalrec.id,
+                    "company_id": self.company.id,
+                    "line_ids": [
+                        (
+                            0,
+                            0,
+                            {
+                                "account_id": self.account_salary_expense_main_company.id,
+                                "partner_id": self.employee_B.id,
+                                "debit": 1000,
+                            },
+                        ),
+                        (
+                            0,
+                            0,
+                            {
+                                "account_id": self.account_salary_expense_main_company.id,
+                                "partner_id": self.employee_A.id,
+                                "debit": 500,
+                            },
+                        ),
+                        (
+                            0,
+                            0,
+                            {
+                                "account_id": self.account_salary_expense_main_company.id,
+                                "partner_id": self.employee_C.id,
+                                "debit": 500,
+                                # 'transfer_to_company_id': self.company_two.id,
+                                "analytic_segment_one_id": self.seg_one_a.id,
+                                "analytic_segment_two_id": self.seg_two_a.id,
+                            },
+                        ),
+                        (
+                            0,
+                            0,
+                            {
+                                "account_id": self.account_salary_expense_main_company.id,
+                                "partner_id": self.employee_B.id,
+                                "debit": 600,
+                                # 'transfer_to_company_id': self.company_one.id,
+                                "analytic_segment_one_id": self.seg_one_b.id,
+                                "analytic_segment_two_id": self.seg_two_b.id,
+                            },
+                        ),
+                        (
+                            0,
+                            0,
+                            {
+                                "account_id": self.account_salary_expense_main_company.id,
+                                "partner_id": self.employee_A.id,
+                                "debit": 400,
+                                # 'transfer_to_company_id': self.company_one.id,
+                                "analytic_segment_one_id": self.seg_one_c.id,
+                                "analytic_segment_two_id": self.seg_two_c.id,
+                            },
+                        ),
+                        (
+                            0,
+                            0,
+                            {
+                                "account_id": self.account_payroll_clearing_main_company.id,
+                                "credit": 3000,
+                            },
+                        ),
+                    ],
+                }
+            )
+        )
+
+        payroll_move.action_post()
+
+    def test_distribution_segments(self):
+        """Returns an open invoice"""
+        lines = [
+            (
+                0,
+                0,
+                {
+                    "product_id": self.env.ref("product.product_product_4").id,
+                    "quantity": 1,
+                    "price_unit": 100.00,
+                    "name": "something",
+                    # 'account_id': self.account_invoice_main_company.id,
+                    "analytic_segment_one_id": self.seg_one_a.id,
+                    "analytic_segment_two_id": self.seg_two_a.id,
+                },
+            )
+        ]
+        invoice_id = (
+            self.env["account.move"]
+            .with_context(default_move_type="in_invoice")
+            .create(
+                {
+                    "partner_id": self.env.ref("base.res_partner_2").id,
+                    "currency_id": self.env.ref("base.USD").id,
+                    "name": "Test Distribution Segments",
+                    # 'account_id': self.account_invoice_main_company.id,
+                    "move_type": "in_invoice",
+                    "invoice_date": time.strftime("%Y") + "-06-26",
+                    "invoice_line_ids": lines,
+                }
+            )
+        )
+        invoice_line_id = invoice_id.invoice_line_ids
+        self.env["account.invoice.line.distribution"].create(
+            {
+                "percent": 50.00,
+                "amount": 50.00,
+                "company_id": self.company_one.id,
+                "invoice_line_id": invoice_line_id.id,
+            }
+        )
+        invoice_line_id._onchange_distribution_ids_percent()
+        invoice_id.action_post()
+
+        self.due_to = (
+            self.env["account.move"]
+            .sudo()
+            .search(
+                [
+                    ("company_id", "=", self.company_one.id),
+                    ("ref", "like", invoice_id.name),
+                ]
+            )
+        )
+
+        self.assertEqual(
+            self.due_to.line_ids[0].analytic_segment_one_id.id,
+            self.due_to.line_ids[1].analytic_segment_one_id.id,
+            self.seg_one_a.id,
+        )
+
+        self.assertEqual(
+            self.due_to.line_ids[0].analytic_segment_two_id.id,
+            self.due_to.line_ids[1].analytic_segment_two_id.id,
+            self.seg_two_a.id,
+        )
+
+        self.due_from = self.env["account.move"].search(
+            [
+                ("ref", "like", invoice_id.name),
+                ("journal_id", "=", self.due_to_due_from_journal_main_company.id),
+            ]
+        )
+
+        self.assertEqual(
+            self.due_from.line_ids[0].analytic_segment_one_id.id,
+            self.due_from.line_ids[1].analytic_segment_one_id.id,
+            self.seg_one_a.id,
+        )
+
+        self.assertEqual(
+            self.due_from.line_ids[0].analytic_segment_two_id.id,
+            self.due_from.line_ids[1].analytic_segment_two_id.id,
+            self.seg_two_a.id,
+        )